flutter_braintree_native
A Flutter plugin that wraps the official Braintree Android and iOS native SDKs, enabling fully custom payment flows built with Flutter.
Unlike older Flutter Braintree plugins, this package does not rely on Braintree Drop-In. Instead, it exposes functionality from Braintree's native SDKs so you can build your own payment experience in Flutter while retaining native tokenization and authentication capabilities.
Note: This is a community-driven package and is not officially affiliated with Braintree or PayPal.
β¨ Features
- π³ Credit Card payments (optional 3D Secure, optional billing & customer information)
- π ΏοΈ PayPal Checkout
- π Google Pay (Android)
- ο£Ώ Apple Pay (IOS)
- π£ Venmo
- π Device Data Collection (Fraud Detection)
- π Native SDK integration (no WebView-based payment UI or Drop-In)
| Platform | Card | PayPal | Google Pay | Venmo | Apple Pay |
|---|---|---|---|---|---|
| Android | β | β | β | β | β |
| iOS | β | β | β | β | β |
π¦ Installation
Add flutter_braintree_native to your pubspec.yaml:
dependencies:
...
flutter_braintree_native: <version>
Run:
flutter pub get
π§ Android
You must migrate to AndroidX.
In /app/build.gradle, set your minSdkVersion to at least 24.
Important: Your app's URL scheme must begin with your app's package ID and end with .braintree. For example, if the Package ID is com.your-company.your-app, then your URL scheme should be com.your-company.your-app.braintree. ${applicationId} is automatically applied with your app's
package when using Gradle.
Note: The scheme you define must use all lowercase letters. If your package contains underscores, the underscores should be removed when specifying the scheme in your Android Manifest.
Google Pay (Android Only)
Add the wallet enabled meta-data tag to your AndroidManifest.xml (inside the <application> body):
<meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true" />
π iOS
The iOS implementation requires iOS 16.0 or later.
If your project uses CocoaPods, make sure your ios/Podfile contains:
platform :ios, '16.0'
Swift Package Manager
This plugin supports Swift Package Manager (SPM) and CocoaPods.
For projects using a recent version of Flutter with Swift Package Manager enabled, no additional Braintree package configuration is required. Flutter automatically integrates the plugin's Swift package and its Braintree dependencies.
The plugin also retains CocoaPods support for compatibility with Flutter projects and other plugins that still depend on CocoaPods.
Note: Your application can continue using CocoaPods even though this plugin supports Swift Package Manager. You do not need to migrate your entire application to SPM just to use
flutter_braintree_native. But SPM should be preferred for better build times and future support.
Apple Pay (iOS Only)
β οΈ Important: Apple Pay requires additional Xcode configuration.
If not configured correctly, the Apple Pay sheet may briefly appear and then immediately dismiss.
1οΈβ£ Enable Apple Pay Capability
In Xcode:
Runner β Signing & Capabilities β + Capability β Apple Pay
Then select your Merchant ID.
If this capability is missing, Apple Pay will silently cancel.
2οΈβ£ Create a Merchant ID (Apple Developer)
Apple Pay requires your own Merchant ID and additional configuration in Xcode and the Apple Developer account.
You must:
Create a Merchant ID in the Apple Developer portal Example:
- merchant.com.yourcompany.yourapp
- Create/configure your Merchant ID in the Apple Developer portal.
- Create the required Apple Pay processing certificate.
- Upload the certificate to: Braintree Control Panel β Processing β Apple Pay
For PayPal / Venmo / 3D Secure
β οΈ Important: Upon cancellation (user canceled the operation/payment) Venmo doesn't return null, (we handled user cancellation like this only for Venmo, the rest of the payment methods return null). It returns an error with the message "User canceled Venmo".
iOS PayPal / Venmo / 3D Secure Redirects
Braintree may need to return control to your application after an external authentication or payment flow.
Add the following URL handling to your AppDelegate:
CocoaPods projects
If your iOS application uses CocoaPods:
import Braintree
If your iOS application uses Swift Package Manager:
import BraintreeCore
And add the following to your AppDelegate:
override func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if BTAppContextSwitcher.sharedInstance.handleOpen(url) {
return true
}
return super.application(app, open: url, options: options)
}
override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return false
}
return BTAppContextSwitcher.sharedInstance.handleOpen(url)
}
Credit/Debit Card
final result = await Braintree.startCardPayment(
authorization: clientToken,
cardNumber: "4111111111111111",
expirationMonth: "12",
expirationYear: "2028",
cvv: "123",
amount: "10.00",
// Optional
billingFirstName: "John",
billingLastName: "Doe",
billingAddress: "123 Main Street",
billingCity: "New York",
billingZipCode: "10001",
billingCountryCode: "US",
billingPhoneNumber: "+15551234567",
email: "john@example.com",
require3DS: true,
forceChallenge: false,
);
if (result != null) {
print(result["nonce"]);
}
Card Payment Response
{
"nonce": "...",
"deviceData": "...",
"liabilityShifted": true,
"liabilityShiftPossible": true,
}
The authorization parameter accepts either:
- a Client Token (recommended)
- a Tokenization Key
No separate APIs are required.
Billing and customer information are optional but recommended when using 3D Secure, as they may improve issuer authentication and fraud detection.
3D Secure
startCardPayment() supports optional 3D Secure verification.
| Option | Description |
|---|---|
require3DS |
Enables or disables 3D Secure authentication. Defaults to true. |
forceChallenge |
Requests that the issuer display a challenge (OTP, banking app approval, biometric verification, etc.). Defaults to false. |
Even when
forceChallengeistrue, the issuing bank ultimately decides whether a challenge is shown.
Return URL Configuration
Moreover, you need to specify the same URL scheme in your Info.plist:
<key>CFBundleURLTypes</key><array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.your-company.your-app.braintree</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.your-company.your-app.braintree</string>
</array>
</dict>
</array>
See the official Braintree documentation for a more detailed explanation.
Usage Example
You must first create a Braintree account. In your control panel you can create a tokenization key. You likely also want to set up a backend server. Make sure to read the Braintree developer documentation so you understand all key concepts.
In your code, import the plugin:
import 'package:flutter_braintree_native/flutter_braintree_native.dart';
You can build your own payment UI entirely in Flutter while using the official Braintree native SDKs for tokenization and payment authentication.
Braintree's native UI
Access the payment nonce (if successful):
final result = await Braintree.startPayPal(
authorization: BRAINTREE_TOKEN,
amount: 10.12,
currencyCode: "USD",
returnUrl: "https://your-domain.com/mobile/paypal",
);
if (result != null) {
if (result.containsKey('error')) {
debugPrint("Error => ${result['error']}");
} else {
debugPrint("Nonce => ${result['nonce']}");
// if you need the device data for your backend (only required in case of fraud detection so its optional)
debugPrint("Device Data => ${result['deviceData']}");
}
}
β οΈ Security Notice
This plugin only tokenizes payment methods and returns a payment nonce.
Always send the returned nonce to your backend server to create or authorize transactions using the Braintree Server SDK.
Never process payments or store sensitive payment information directly from the client.
π Known Limitations
Venmo support has limited testing (sandbox support is restricted by region), so please test venmo at your end before using it in production.
Vaulting is not yet implemented.
Responses are currently returned as a generic Map. Strongly typed models are planned for a future release.
Contributions and improvements are welcome.