DEV Community

vmodal_ai
vmodal_ai

Posted on Originally published at example.com

PayPal Android SDK with Flutter: Integrate PayPal Checkout Using Platform Channels

PayPal Android SDK with Flutter: Integrate PayPal Checkout Using Platform Channels

Flutter does not need a Dart package for every native Android SDK. When an application depends on an Android-only SDK, Flutter can communicate with Kotlin through platform channels.

This is especially useful for payment SDKs.

In this tutorial, we'll demonstrate the architecture for integrating the PayPal Android SDK through Braintree's PayPal module into a Flutter Android application.

Important: Braintree's current Android documentation recommends the PayPal module for checkout. The older PayPalNativeCheckout module was deprecated. Braintree also documents certificate-related requirements for older mobile SDKs, so verify the current SDK and migration guidance before production release.

Step 1: Create the Flutter Project

flutter create paypal_flutter_demo
cd paypal_flutter_demo
Enter fullscreen mode Exit fullscreen mode

This tutorial focuses on Android.

Step 2: Add the Android PayPal Dependency

In the Android application's Gradle dependencies:

dependencies {
    implementation("com.braintreepayments.api:paypal:5.8.0")
}
Enter fullscreen mode Exit fullscreen mode

Verify the current Braintree version before production use.

Step 3: Understand Credentials

Do not put private credentials in Flutter.

The mobile client can use an appropriate client authorization value such as a client token or tokenization key, depending on the integration.

For production, obtain client authorization from your backend.

Step 4: Create the Flutter MethodChannel

import 'package:flutter/services.dart';

class PayPalBridge {
  static const _channel = MethodChannel(
    'com.example.paypal/checkout',
  );

  static Future<String?> startCheckout() {
    return _channel.invokeMethod<String>(
      'startCheckout',
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Flutter platform channels allow Dart to call Android Kotlin code.

Step 5: Implement the Android Channel

In MainActivity.kt:

class MainActivity : FlutterActivity() {

    private val channelName = "com.example.paypal/checkout"

    override fun configureFlutterEngine(
        flutterEngine: FlutterEngine
    ) {
        super.configureFlutterEngine(flutterEngine)

        MethodChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            channelName
        ).setMethodCallHandler { call, result ->

            when (call.method) {
                "startCheckout" -> {
                    startPayPalCheckout(result)
                }

                else -> result.notImplemented()
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Initialize the Native SDK

Braintree's Android documentation shows creating a PayPalLauncher in Activity.onCreate() and creating a PayPalClient with an authorization value and app-link return URL.

Conceptually:

private lateinit var payPalLauncher: PayPalLauncher
private lateinit var payPalClient: PayPalClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    payPalLauncher = PayPalLauncher()

    payPalClient = PayPalClient(
        context = this,
        authorization = clientAuthorization,
        appLinkReturnUrl = Uri.parse(
            "https://merchant-app.example"
        )
    )
}
Enter fullscreen mode Exit fullscreen mode

Use the exact current API from the SDK version you install.

Step 7: Start Checkout

Keep the payment implementation in a dedicated class:

private fun startPayPalCheckout(
    result: MethodChannel.Result
) {
    // Start the current PayPal checkout flow.
    // Return success or error through `result`.
}
Enter fullscreen mode Exit fullscreen mode

Avoid putting the entire payment implementation into MainActivity.

Step 8: Return the Result to Flutter

Success:

result.success("completed")
Enter fullscreen mode Exit fullscreen mode

Failure:

result.error(
    "PAYPAL_ERROR",
    "Payment could not be completed",
    null
)
Enter fullscreen mode Exit fullscreen mode

Flutter:

try {
  final status = await PayPalBridge.startCheckout();

  if (status == 'completed') {
    debugPrint('Checkout completed');
  }
} on PlatformException catch (e) {
  debugPrint('PayPal error: ${e.message}');
}
Enter fullscreen mode Exit fullscreen mode

Step 9: Verify Payments on Your Backend

Never treat a mobile callback as the only source of truth for fulfilling an order.

Use:

Flutter
   ↓
Native PayPal SDK
   ↓
PayPal / Braintree
   ↓
Backend
   ↓
Verify transaction
   ↓
Fulfill order
Enter fullscreen mode Exit fullscreen mode

Your backend should verify payment state before marking an order as paid.

Step 10: Separate Flutter and Native Code

A clean structure:

lib/
  payments/
    paypal_bridge.dart

android/
  app/
    src/main/kotlin/
      PayPalManager.kt
      MainActivity.kt
Enter fullscreen mode Exit fullscreen mode

PayPalBridge should expose a small Dart API.

PayPalManager should own Android-specific payment logic.

Security Best Practices

Never:

  • Hard-code private credentials.
  • Trust only a client-side success callback.
  • Log payment tokens.
  • Store sensitive credentials in ordinary preferences.
  • Fulfill orders without server-side verification.

Use:

  • Backend-generated client authorization.
  • HTTPS.
  • Server-side transaction verification.
  • Current supported SDK versions.
  • Minimal logging of payment information.

Why Platform Channels Matter

Flutter's platform-channel architecture allows Dart to communicate with Android Kotlin/Java APIs. This makes it possible to use native SDKs when a suitable Flutter plugin is unavailable.

Common Problems

Dependency Resolution Failure

Check the Android repository and dependency version required by the current Braintree documentation.

Checkout Does Not Return to the App

Check your App Link / return URL configuration.

Payment Appears Successful but Order Is Not Updated

Do not rely exclusively on the mobile callback. Verify the transaction on your backend.

SDK Version Problems

Payment SDKs change over time. Check the current Braintree migration and certificate guidance before releasing.

Conclusion

SDK integrations are easiest to maintain when credentials, platform-specific configuration, networking, and UI responsibilities are separated. Start with the smallest working flow, verify it on a physical device, and then add production concerns such as authentication, error handling, lifecycle management, and secure credential handling.

Stay tuned for more advanced Flutter SDK integration tutorials!

SEO Keywords

Flutter SDK tutorial, Flutter integration, Flutter mobile development, Dart SDK integration, Flutter Android, Flutter iOS, SDK integration

Tags

flutter dart mobiledevelopment sdk android

Useful Links

Website: www.v-modal.com

SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter

SDK Android: https://github.com/v-modal/vmodal_sdk_android

Discord: https://discord.gg/K72z28KUx

Top comments (0)