Stripe payment gateway in Flutter

Installation 

dart pub add flutter_stripe

Requirements 

Android

This plugin requires several changes to be able to work on Android devices. Please make sure you follow all these steps:

  1. Use Android 5.0 (API level 21) and above
  2. Use Kotlin version 1.5.0 and above: example
  3. Using a descendant of Theme.AppCompat for your activity: exampleexample night theme
  4. Using an up-to-date Android gradle build tools version: example and an up-to-date gradle version accordingly: example
  5. Using FlutterFragmentActivity instead of FlutterActivity in MainActivity.ktexample
  6. Rebuild the app, as the above changes don’t update with hot reload

These changes are needed because the Android Stripe SDK requires the use of the AppCompat theme for their UI components and the Support Fragment Manager for the Payment Sheets

If you are having troubles to make this package to work on Android, join this discussion to get some support

iOS

Compatible with apps targeting iOS 12 or above.

Web (Experimental)

Now you can use Stripe with Flutter web! Notice right now it is highly experimental and only a subset of features is implemented.

Check the steps needed here

Usage 

The library provides three UI componets for accepting card payments: the CardFieldCardForm, and the Paymentsheet.

We recommend using the PaymentSheet for the most easy and smooth Stripe integration. It provides out of the box support for:

  • Localized labels and error messages to the users
  • Build-in animations
  • Build-in Google Pay and Apple Pay buttons
  • Handling 3D-secure

Notice that PaymentSheet is only available for Android and iOS.

On the other side the CardField allows you to create a more customizable payment flow inside your app.

Example 

// main.dart
import 'package:flutter_stripe/flutter_stripe.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // set the publishable key for Stripe - this is mandatory
  Stripe.publishableKey = stripePublishableKey;
  runApp(PaymentScreen());
}

// payment_screen.dart
class PaymentScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          CardField(
            onCardChanged: (card) {
              print(card);
            },
          ),
          TextButton(
            onPressed: () async {
              // create payment method
              final paymentMethod =
                  await Stripe.instance.createPaymentMethod(PaymentMethodParams.card());
            },
            child: Text('pay'),
          )
        ],
      ),
    );
  }
}
Dart

Stripe initialization 

To initialize Stripe in your Flutter app, use the Stripe base class.

Stripe offers publishableKeystripeAccountIdthreeDSecureParams and merchantIdentifier. Only publishableKey is required.

Dart API 

The library offers several methods to handle stripe related actions:

Future<PaymentMethod> createPaymentMethod(...);
Future<PaymentIntent> handleNextAction(...);
Future<PaymentIntent> confirmPayment(...);
Future<void> configure3dSecure(...);
Future<bool> isApplePaySupported();
Future<void> presentApplePay(...);
Future<void> confirmApplePayPayment(...);
Future<SetupIntent> confirmSetupIntent(...);
Future<PaymentIntent> retrievePaymentIntent(...);
Future<String> createTokenForCVCUpdate(...);

Future<void> initPaymentSheet(...);
Future<void> presentPaymentSheet(...);
Future<void> confirmPaymentSheetPayment()
Dart

The example app offers examples on how to use these methods.

Pay Plugin support 

flutter_stripe fully supports the Pay plugin from the Google Pay team. By including a few lines you can integrate Stripe as a payment processor for Google / Apple Pay:

Future<void> onGooglePayResult(paymentResult) async {
    final response = await fetchPaymentIntentClientSecret();
    final clientSecret = response['clientSecret'];
    final token = paymentResult['paymentMethodData']['tokenizationData']['token'];
    final tokenJson = Map.castFrom(json.decode(token));

    final params = PaymentMethodParams.cardFromToken(
      token: tokenJson['id'],
    );
    // Confirm Google pay payment method
    await Stripe.instance.confirmPayment(
      clientSecret,
      params,
    );
}
Dart

Run the example app 

  • Navigate to the example folder cd example
  • Install the dependencies
    • flutter pub get
  • Set up env vars for the flutter app and a local backend.
    • Get your test Stripe API keys
    • cp lib/.env.example.dart lib/.env.dart and set your Stripe publishable key.
    • cp server/.env.example server/.env and set the variable values in your newly created .env file.
  • Install the server dependencies: yarn --cwd "server"
  • Start the example
    • Terminal 1: yarn --cwd "server" start
    • Terminal 2: flutter run
Additional steps for webhook forwarding

Contributing 

You can help us make this project better, feel free to open an new issue or a pull request.

Setup

This project uses melos to manage all the packages inside this repo.

  • Install melos: dart pub global activate melos
  • Setup melos in your local folder: melos bootstrap
Useful commands
  • Format melos run format
  • Analyze melos run analyze
  • Test melos run test
  • Pub get melos run get

Add payment:

  Map<String, dynamic>? paymentIntentData;
  Future<void> makePayment(
      {required String amount, required String currency}) async {
    try {
      paymentIntentData = await createPaymentIntent(amount, currency);
      if (paymentIntentData != null) {
        await Stripe.instance.initPaymentSheet(
            paymentSheetParameters: SetupPaymentSheetParameters(
              // applePay: PaymentSheetApplePay(
              //   merchantCountryCode: 'US',),
              googlePay: PaymentSheetGooglePay(
                merchantCountryCode: 'US',),
              merchantDisplayName: 'Prospects',
              customerId: paymentIntentData!['customer'],
              paymentIntentClientSecret: paymentIntentData!['client_secret'],
              customerEphemeralKeySecret: paymentIntentData!['ephemeralKey'],
            ));
        displayPaymentSheet();
      }
    } catch (e, s) {
      print('exception:$e$s');
    }
  }

  displayPaymentSheet() async {
    try {
      await Stripe.instance.presentPaymentSheet();
      Get.snackbar('Payment', 'Payment Successful',
          snackPosition: SnackPosition.BOTTOM,
          backgroundColor: Colors.green,
          colorText: Colors.white,
          margin: const EdgeInsets.all(10),
          duration: const Duration(seconds: 2));
      await Shared_Preferences.prefSetBool("ad", false);
      Navigator.pop(context);
      } on Exception catch (e) {
      if (e is StripeException) {
        print("Error from Stripe: ${e.error.localizedMessage}");
      } else {
        print("Unforeseen error: ${e}");
      }
    } catch (e) {
      print("exception:$e");
    }
  }

  //  Future<Map<String, dynamic>>
  createPaymentIntent(String amount, String currency) async {
    try {
      Map<String, dynamic> body = {
        'amount': calculateAmount(amount),
        'currency': currency,
        'payment_method_types[]': 'card'
      };
      var response = await http.post(
          Uri.parse('https://api.stripe.com/v1/payment_intents'),
          body: body,
          headers: {
            'Authorization': 'Bearer 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',
            'Content-Type': 'application/x-www-form-urlencoded'
          });
      return jsonDecode(response.body);
    } catch (err) {
      print('err charging user: ${err.toString()}');
    }
  }
Dart