am_flutter_paypal 0.1.1 copy "am_flutter_paypal: ^0.1.1" to clipboard
am_flutter_paypal: ^0.1.1 copied to clipboard

A secure Flutter plugin for PayPal Advanced Checkout integration using native Android and iOS SDKs (Card Approval Only).

DISCLAIMER: This is an unofficial, community-driven Flutter plugin for PayPal Advanced Checkout (Card Approval Only). It is not developed, maintained, or supported by PayPal.

A secure Flutter plugin for PayPal card payments using native Android and iOS SDKs.

This plugin handles only:

  • SDK initialization
  • Secure card data submission via native SDK
  • Payment approval (including 3DS / authentication)
  • Native error and status reporting

It does NOT:

  • Create PayPal orders
  • Capture payments
  • Store or manage PayPal secrets
  • Expose any backend logic

🔌 Plugin Scope #

This plugin is a thin native wrapper over PayPal mobile SDKs.

It is responsible only for:

✔ Native SDK initialization ✔ Card-based payment approval ✔ 3DS authentication handling ✔ Returning payment result to Flutter

It does NOT include:

❌ Backend APIs ❌ Order creation ❌ Payment capture ❌ Business logic

🏗 Architecture & Payment Flow #

This plugin is designed for a secure backend-driven payment system.

Payment Flow

Flutter Card Form
   ↓
Backend API → Create Order
   ↓
Returns Order ID
   ↓
am_flutter_paypal → approveOrder()
   ↓
PayPal Native SDK (Android / iOS)
   ↓
3DS / Authentication
   ↓
Approval Success
   ↓
Backend API → Capture Payment

Responsibilities

Backend

  • Create PayPal Order (Orders v2 API)
  • Capture payment after approval

Plugin

  • Handles approval only via native SDK
  • Manages 3DS flow
  • Returns result to Flutter

🚀 Getting Started #

Requirements

  • Android: minSdk 24+
  • iOS: iOS 14.0+

🤖 Android Setup #

Add this inside your AndroidManifest.xml activity:

<intent-filter android:label="paypalpay">
    <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.am.amflutterpaypal" android:host="paypalpay" />
</intent-filter>

⚠️ Ensure the scheme matches the returnUrl used in initialization.

🍏 iOS Setup #

Add URL scheme in Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>paypalpay</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.am.amflutterpaypal</string>
        </array>
    </dict>
</array>

⚙️ Usage #

Step 1 — Initialize SDK (once only) #

final bool initialized = await AmFlutterPaypal.initialize(
  clientId: "YOUR_PAYPAL_CLIENT_ID",
  environment: PayPalEnvironment.sandbox, // or live
  returnUrl: "com.am.amflutterpaypal://paypalpay",
);

Step 2 — Create Order (Backend call) #

final response = await http.post(
  Uri.parse("https://your-backend.com/api/paypal/create-order"),
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN",
  },
  body: jsonEncode({
    "amount": amount,
    "currency": "USD",
  }),
);

final orderId = jsonDecode(response.body)["order_id"];

Step 3 — Approve Payment #

final card = PayPalCard(
  cardholderName: "John Doe",
  cardNumber: "4111111111111111",
  expirationMonth: "12",
  expirationYear: "2025",
  securityCode: "123",
  billingAddress: {
    "street": "123 Main St",
    "city": "San Jose",
    "state": "CA",
    "zip": "95131",
    "country": "US",
  },
);

final result = await AmFlutterPaypal.approveOrder(
  orderId: orderId,
  card: card,
);

Step 4 — Capture Payment (Backend) #

final response = await http.post(
  Uri.parse("https://your-backend.com/api/paypal/capture-payment"),
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN",
  },
  body: jsonEncode({
    "payment_id": result.paymentId,
  }),
);

final captured = jsonDecode(response.body)["payment_id"];

⚠️ Show success UI only after capture succeeds

💡 Best Practices #

  • Initialize SDK once only (app startup)
  • Never initialize on every payment click
  • Disable button during payment processing
  • Always capture payment after approval
  • Use live environment only in production
  • Prevent duplicate payment requests

🔐 Security #

  • Card data is never stored or logged
  • All sensitive operations handled by native PayPal SDK
  • No PayPal secrets exist in this plugin
  • Backend must handle:
    • Order creation
    • Payment capture
  • 3DS authentication handled natively

⚠️ Error Codes #

Code Description
SDK_NOT_INITIALIZED Plugin not initialized
PAYMENT_IN_PROGRESS Another payment is active
PAYMENT_TIMEOUT Approval timed out
USER_CANCELLED User cancelled payment
INVALID_ARGUMENTS Missing/invalid data
ACTIVITY_NULL Android activity not available
MISSING_RETURN_URL Return URL missing
AUTHORIZATION_REQUIRED 3DS required
UNKNOWN_ERROR Unexpected native error

🚀 Production Checklist #

  • Live PayPal client ID configured
  • Backend order creation API ready
  • Backend capture API ready
  • Sandbox end-to-end testing completed
  • 3DS authentication tested
  • Cancellation handling tested
  • Timeout handling tested
  • Duplicate payment prevention tested

📦 Repository #

GitHub: https://github.com/Abdul520Mannan/am_flutter_paypal

📄 License #

1. Initialization #

Initialize the SDK once with your Client ID and a unique return URL.

final bool initialized = await AmFlutterPaypal.initialize(
  clientId: "YOUR_PAYPAL_CLIENT_ID",
  environment: PayPalEnvironment.sandbox, // or PayPalEnvironment.live
  returnUrl: "com.am.amflutterpaypal://paypalpay",
);

2. Approve Order #

Call your backend to get an orderId, then pass it to the plugin along with the PayPalCard details.

final card = PayPalCard(
  cardholderName: "John Doe",
  cardNumber: "1234567812345678",
  expirationMonth: "12",
  expirationYear: "2025",
  securityCode: "123",
  billingAddress: {
    "street": "123 Main St",
    "city": "San Jose",
    "state": "CA",
    "zip": "95131",
    "country": "US",
  },
);

final result = await AmFlutterPaypal.approveOrder(
  orderId: "ORDER_ID_FROM_BACKEND",
  card: card,
);

if (result.success) {
  print("Payment Approved! Order ID: ${result.orderId}");
  // Now call your backend to CAPTURE the payment using result.orderId
} else {
  print("Payment Failed: ${result.errorCode} - ${result.message}");
}

Error Codes #

Error Code Description
SDK_NOT_INITIALIZED initialize was not called or failed.
PAYMENT_IN_PROGRESS Another payment approval is already active.
PAYMENT_TIMEOUT No response from native SDK after 60 seconds.
USER_CANCELLED User closed the payment/3DS UI.
INVALID_ARGUMENTS Missing Order ID or card details.
AUTHORIZATION_REQUIRED Additional authorization (like 3DS) was required but not completed.
PLATFORM_ERROR An error occurred in the native Android or iOS layer.

Important Security Note #

Never include your PayPal Secret Key in your Flutter code. Always use a secure backend to interact with PayPal's REST APIs for order creation and capture.

1
likes
150
points
72
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A secure Flutter plugin for PayPal Advanced Checkout integration using native Android and iOS SDKs (Card Approval Only).

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on am_flutter_paypal

Packages that implement am_flutter_paypal