paypal_checkout_flutter 0.0.6 copy "paypal_checkout_flutter: ^0.0.6" to clipboard
paypal_checkout_flutter: ^0.0.6 copied to clipboard

Flutter PayPal integration — native SDK checkout, cards, vault, subscriptions, plans, products, orders & refunds. No WebView.

paypal_checkout_flutter #

pub package License: BSD-3

A complete Flutter package for PayPal payments using the native PayPal Mobile SDK (Android v2.3.0 / iOS v2.0.1). Type-safe Dart ↔ Kotlin/Swift communication via Pigeon.

No WebView. Opens the system browser or processes cards directly with the native SDK.

Features #

Native SDK (Pigeon) #

Feature Method Backend required
PayPal Checkout pay() Yes
PayPal Checkout (no backend) payDirect() No
Pay Later (financing) pay() + payLater Yes
Card payment payWithCard() Yes
Card payment (no backend) payWithCardDirect() No
Vault PayPal account vaultPaypal() Yes
Vault card vaultCard() Yes
Vault PayPal (no backend) vaultPaypalDirect() No
Vault card (no backend) vaultCardDirect() No

REST API — Orders & Payments #

Endpoint Method
Create order createOrder()*
Get order details getOrderDetails()
Update order (PATCH) updateOrder()
Capture order captureOrder()*
Authorize order authorizeOrder()
Capture authorization captureAuthorization()
Void authorization voidAuthorization()
Refund capture refund()

REST API — Catalog Products (4/4 endpoints) #

Endpoint Method
Create product createProduct()
List products listProducts()
Show product details getProductDetails()
Update product updateProduct()

REST API — Billing Plans (7/7 endpoints) #

Endpoint Method
Create plan createPlan()
List plans listPlans()
Show plan details getPlanDetails()
Update plan updatePlan()**
Activate plan activatePlan()**
Deactivate plan deactivatePlan()**
Update pricing schemes updatePlanPricing()

REST API — Subscriptions (10/10 endpoints) #

Endpoint Method
Create subscription createSubscription()
Show subscription details getSubscriptionDetails()
List subscriptions listSubscriptions()
Update subscription updateSubscription()
Revise subscription reviseSubscription()
Activate subscription activateSubscription()
Suspend subscription suspendSubscription()
Cancel subscription cancelSubscription()
Capture payment captureSubscriptionPayment()
List transactions listSubscriptionTransactions()

* Available via PaypalOrderService and internally used by payDirect()/payWithCardDirect(). ** Available via PaypalSubscriptionService directly.

  • Full 3D Secure support for card payments
  • Clean architecture: entities, repositories, mappers
  • Either<Failure, Success> with dartz for error handling
  • 177 unit tests with full coverage

Requirements #

  • Android: minSdk 23, compileSdk 34, Java 17
  • iOS: iOS 16.0+
  • Flutter: >=1.17.0
  • A PayPal app (developer.paypal.com)

Installation #

dependencies:
  paypal_checkout_flutter: ^0.0.3

Android Setup #

Add the deep link intent filter in your AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="com.example.myapp" android:host="paypalpay" />
    </intent-filter>
</activity>

Quick Start #

Initialize (once at app startup) #

import 'package:paypal_checkout_flutter/paypal_checkout_flutter.dart';

final paypal = FlutterPaypalPayment();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await paypal.init(PaypalConfig(
    clientId: 'YOUR_CLIENT_ID',
    environment: PaypalEnvironment.sandbox,
    returnUrl: 'com.example.myapp://paypalpay',
  ));

  runApp(MyApp());
}

Usage Examples #

1. PayPal Checkout (with backend) #

Your server creates the order via PayPal Orders API and returns the orderId.

final result = await paypal.pay(
  PaymentRequest(orderId: 'ORDER_ID_FROM_BACKEND'),
);

result.fold(
  (failure) => print('Error: ${failure.message}'),
  (success) => print('Paid! Order: ${success.orderId}'),
);

2. PayPal Checkout (no backend) #

Creates the order, opens checkout, and captures — all from Flutter.

Note: Requires your clientSecret. Not recommended for production.

final result = await paypal.payDirect(
  clientSecret: 'YOUR_SECRET',
  params: PaymentParams(
    amount: '25.00',
    currencyCode: 'USD',
    description: 'Product X purchase',
  ),
);

3. Card Payment #

Charge a card directly without PayPal login. Supports 3D Secure automatically.

final result = await paypal.payWithCard(
  CardPaymentRequest(
    orderId: 'ORDER_ID',
    card: PaymentCard(
      number: '4111111111111111',
      expirationMonth: '12',
      expirationYear: '2028',
      securityCode: '123',
    ),
  ),
);

4. Pay Later (Financing) #

final result = await paypal.pay(
  PaymentRequest(
    orderId: 'ORDER_ID',
    fundingSource: PaypalFundingSource.payLater,
  ),
);

5. Vault: Save PayPal Account #

final result = await paypal.vaultPaypal(
  VaultPaypalRequest(setupTokenId: 'SETUP_TOKEN_FROM_BACKEND'),
);

6. Vault: Save Card #

final result = await paypal.vaultCard(
  VaultCardRequest(
    setupTokenId: 'SETUP_TOKEN_FROM_BACKEND',
    card: PaymentCard(
      number: '4111111111111111',
      expirationMonth: '12',
      expirationYear: '2028',
      securityCode: '123',
    ),
  ),
);

7. Refund (Total or Partial) #

// Full refund
final result = await paypal.refund(
  clientSecret: 'YOUR_SECRET',
  captureId: 'CAPTURE_ID',
);

// Partial refund ($5.00)
final partial = await paypal.refund(
  clientSecret: 'YOUR_SECRET',
  captureId: 'CAPTURE_ID',
  amount: '5.00',
  currencyCode: 'USD',
);

8. Order Authorization Flow #

// Authorize (hold funds)
final auth = await paypal.authorizeOrder(
  clientSecret: 'YOUR_SECRET',
  orderId: 'ORDER_ID',
);

// Capture later
final capture = await paypal.captureAuthorization(
  clientSecret: 'YOUR_SECRET',
  authorizationId: 'AUTH_ID',
);

// Or void
final voided = await paypal.voidAuthorization(
  clientSecret: 'YOUR_SECRET',
  authorizationId: 'AUTH_ID',
);

9. Update Order (Shipping/Tracking) #

final result = await paypal.updateOrder(
  clientSecret: 'YOUR_SECRET',
  orderId: 'ORDER_ID',
  patchOperations: [
    {
      'op': 'add',
      'path': '/purchase_units/@reference_id==\'default\'/shipping/trackers',
      'value': [
        {
          'carrier': 'FEDEX',
          'tracking_number': '1234567890',
          'status': 'SHIPPED',
        }
      ],
    }
  ],
);

Subscriptions API #

10. Create a Product #

final result = await paypal.createProduct(
  clientSecret: 'YOUR_SECRET',
  product: {
    'name': 'Premium Plan',
    'description': 'Access to all features',
    'type': 'SERVICE',
    'category': 'SOFTWARE',
  },
);

result.fold(
  (failure) => print('Error: ${failure.message}'),
  (product) => print('Product created: ${product['id']}'),
);

11. List Products #

final result = await paypal.listProducts(
  clientSecret: 'YOUR_SECRET',
  pageSize: 10,
  page: 1,
  totalRequired: true,
);

result.fold(
  (failure) => print('Error: ${failure.message}'),
  (data) {
    final products = data['products'] as List;
    print('Total: ${data['total_items']}, Found: ${products.length}');
  },
);

12. Get Product Details #

final result = await paypal.getProductDetails(
  clientSecret: 'YOUR_SECRET',
  productId: 'PROD-XXXX',
);

13. Update Product #

final result = await paypal.updateProduct(
  clientSecret: 'YOUR_SECRET',
  productId: 'PROD-XXXX',
  patchOperations: [
    {'op': 'replace', 'path': '/description', 'value': 'New description'},
  ],
);

14. Create a Billing Plan #

final result = await paypal.createPlan(
  clientSecret: 'YOUR_SECRET',
  plan: {
    'product_id': 'PROD-XXXX',
    'name': 'Monthly Plan',
    'billing_cycles': [
      {
        'frequency': {'interval_unit': 'MONTH', 'interval_count': 1},
        'tenure_type': 'REGULAR',
        'sequence': 1,
        'total_cycles': 0,
        'pricing_scheme': {
          'fixed_price': {'value': '9.99', 'currency_code': 'USD'},
        },
      }
    ],
    'payment_preferences': {
      'auto_bill_outstanding': true,
      'payment_failure_threshold': 3,
    },
  },
);

15. List Plans #

final result = await paypal.listPlans(
  clientSecret: 'YOUR_SECRET',
  productId: 'PROD-XXXX', // optional filter
  pageSize: 10,
);

16. Update Plan Pricing #

final result = await paypal.updatePlanPricing(
  clientSecret: 'YOUR_SECRET',
  planId: 'P-XXXX',
  pricingSchemes: [
    {
      'billing_cycle_sequence': 1,
      'pricing_scheme': {
        'fixed_price': {'value': '14.99', 'currency_code': 'USD'},
      },
    }
  ],
);

17. Create a Subscription #

final result = await paypal.createSubscription(
  clientSecret: 'YOUR_SECRET',
  subscription: {
    'plan_id': 'P-XXXX',
    'subscriber': {
      'name': {'given_name': 'John', 'surname': 'Doe'},
      'email_address': 'john@example.com',
    },
    'application_context': {
      'return_url': 'https://example.com/return',
      'cancel_url': 'https://example.com/cancel',
    },
  },
);

18. List Subscriptions #

final result = await paypal.listSubscriptions(
  clientSecret: 'YOUR_SECRET',
  planIds: 'P-XXXX',
  statuses: 'ACTIVE',
  pageSize: 20,
);

19. Manage Subscription Lifecycle #

// Activate
await paypal.activateSubscription(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  reason: 'Reactivating after pause',
);

// Suspend
await paypal.suspendSubscription(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  reason: 'Customer requested pause',
);

// Cancel
await paypal.cancelSubscription(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  reason: 'Customer requested cancellation',
);

// Revise (change plan)
final revised = await paypal.reviseSubscription(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  revisionDetails: {'plan_id': 'P-NEW-PLAN'},
);

20. Capture Outstanding Payment #

final result = await paypal.captureSubscriptionPayment(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  captureRequest: {
    'note': 'Charging outstanding balance',
    'capture_type': 'OUTSTANDING_BALANCE',
    'amount': {'currency_code': 'USD', 'value': '10.00'},
  },
);

21. List Subscription Transactions #

final result = await paypal.listSubscriptionTransactions(
  clientSecret: 'YOUR_SECRET',
  subscriptionId: 'I-XXXX',
  startTime: '2026-01-01T00:00:00Z',
  endTime: '2026-04-18T23:59:59Z',
);

result.fold(
  (failure) => print('Error: ${failure.message}'),
  (data) {
    final txns = data['transactions'] as List;
    for (final txn in txns) {
      print('${txn['id']}: ${txn['status']} — ${txn['amount_with_breakdown']}');
    }
  },
);

Using the Service Directly #

For advanced usage, you can use PaypalSubscriptionService or PaypalOrderService directly:

final service = PaypalSubscriptionService(
  config: PaypalConfig(
    clientId: 'YOUR_CLIENT_ID',
    environment: PaypalEnvironment.sandbox,
    returnUrl: 'com.example.myapp://paypalpay',
  ),
  clientSecret: 'YOUR_SECRET',
);

try {
  // Plan lifecycle methods only available via service
  await service.updatePlan('P-XXXX', patchOperations: [...]);
  await service.activatePlan('P-XXXX');
  await service.deactivatePlan('P-XXXX');
} finally {
  service.dispose();
}

Dependency Injection #

GetIt #

final getIt = GetIt.instance;

Future<void> configureDependencies() async {
  final paypal = FlutterPaypalPayment();
  await paypal.init(PaypalConfig(
    clientId: 'YOUR_CLIENT_ID',
    environment: PaypalEnvironment.sandbox,
    returnUrl: 'com.example.myapp://paypalpay',
  ));
  getIt.registerSingleton<FlutterPaypalPayment>(paypal);
}

Riverpod #

final paypalProvider = Provider<FlutterPaypalPayment>((ref) {
  throw UnimplementedError('Initialized in main');
});

// In main:
runApp(
  ProviderScope(
    overrides: [paypalProvider.overrideWithValue(paypal)],
    child: MyApp(),
  ),
);

Architecture #

lib/
├── paypal_checkout_flutter.dart       # Public exports
└── src/
    ├── flutter_paypal_payment_plugin.dart  # Public API (FlutterPaypalPayment)
    ├── domain/
    │   ├── entities/                 # PaypalConfig, PaymentRequest, PaymentCard, etc.
    │   └── repositories/            # Abstract contracts
    ├── data/
    │   ├── repositories/            # Implementation delegating to Pigeon
    │   ├── mappers/                 # Dart ↔ Pigeon message mappers
    │   └── services/                # PaypalOrderService, PaypalSubscriptionService
    └── generated/                   # Auto-generated Pigeon code

android/src/main/kotlin/
└── FlutterPaypalPaymentPlugin.kt    # Native implementation (PayPal Android SDK)

ios/Classes/
└── PaypalCheckoutFlutterPlugin.swift # Native implementation (PayPal iOS SDK)

Error Handling #

All methods return Either<Failure, Success>. Use .fold() to handle both cases:

result.fold(
  (failure) {
    // failure.code  — e.g. 'NOT_INITIALIZED', 'CAPTURE_ERROR'
    // failure.message — human-readable description
    print('${failure.code}: ${failure.message}');
  },
  (success) {
    // Handle success
  },
);

Support #

If this package helps you, consider supporting its development:

ko-fi

License #

BSD-3-Clause — See LICENSE for details.

0
likes
0
points
116
downloads

Publisher

verified publisherignacio-manchu.com

Weekly Downloads

Flutter PayPal integration — native SDK checkout, cards, vault, subscriptions, plans, products, orders & refunds. No WebView.

Repository (GitHub)
View/report issues

Topics

#paypal #payments #checkout #subscriptions #in-app-purchase

License

unknown (license)

Dependencies

dartz, flutter, http

More

Packages that depend on paypal_checkout_flutter

Packages that implement paypal_checkout_flutter