Flutter – Integrate Stripe Payment Gateway
Stripe is a platform that allows businesses to handle online transactions and add payment gateway in your applications or websites all over the world with different currencies.
- It is secure and easy to use.
- It supports 135+ countries and can handle foreign currency automatically.
- It gives proper report and It is used by many international apps
A sample video is given below to get an idea about what we are going to do in this article.
Step By Step Implementation
Step 1: Create a New Project in Android Studio
To set up Flutter Development on Android Studio please refer to Android Studio Setup for Flutter Development, and then create a new project in Android Studio please refer to Creating a Simple Application in Flutter.
Step 2: Add the flutter_stripe and http package
Add the following package to your pubspec.yaml file
Dart
dependencies: flutter_stripe: ^10.0.0 http: ^1.1.2 |
The version may get change depending on your usage. We have preferred this package because it is developed by stripe itself and it is well maintained project with error free code
Important Tip: Always Prefer to use package that are developed by some big companies. Use that is maintained regularly by publisher.
Step 3: Create a stripe account and get publishable and secret key from it and store it in dotenv file
To get this key you need to create a stripe and go to Developers section on top left corner
Then go to API key and copy both the keys in dotenv file. You can refer following Dotenv article to save this apikeys
Step 4: Set the publishable key in void main function
Dart
void main() { WidgetsFlutterBinding.ensureInitialized(); Stripe.publishableKey = '<your_publishable_key>' ; runApp( const MyApp()); } |
Step 5: Add some permissions and files in platforms folder like android and iOS
Let’s start with android first
- We will have to change the minSDKVersion to 21.
- We have to add FlutterFragmentActivity in android/app/src/main/kotlin/com/flutterwings/gradient_widgets/MainActivity.kt like this
Kotlin
package com.flutterwings.gradient_widgets import io.flutter.embedding.android.FlutterActivity class MainActivity: FlutterActivity() { } |
Add the Proguard file with name proguard-rules.pro at location android/app/
Dart
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivity$g -dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Args -dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error -dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter -dontwarn com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider |
Add the following in android/app/src/main/AndroidManifest.xml
XML
< application android:label = "flutter_stripe_template" android:name = "${applicationName}" android:icon = "@mipmap/ic_launcher" android:enableOnBackInvokedCallback = "true" > <!-- This line you need to add in your manifest file --> |
Step 6: Add 1 button from where a bottomsheet for payment will open
We will add 1 elevated button in screen with OnTap Function which will open the payment page and we can handle the different case like payment is successful or cancelled. Let’s learn step by step process to open the payment sheet and handle different scenario
1. Payment intent data via http request:
Dart
createPaymentIntent(String amount, String currency) async { try { Map<String, dynamic> body = { // Amount must be in smaller unit of currency // so we have multiply it by 100 'amount' : (( int .parse(amount)) * 100).toString(), 'currency' : currency, 'payment_method_types[]' : 'card' , }; var secretKey = "<your_secret_key_via_dotenv>" ; var response = await http.post( Uri.parse( 'https://api.stripe.com/v1/payment_intents' ), headers: { 'Authorization' : 'Bearer $secretKey' , 'Content-Type' : 'application/x-www-form-urlencoded' }, body: body, ); print( 'Payment Intent Body: ${response.body.toString()}' ); return jsonDecode(response.body.toString()); } catch (err) { print( 'Error charging user: ${err.toString()}' ); } } |
2. Intialise the payment intent:
Dart
await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( // Client secret key from payment data paymentIntentClientSecret: paymentIntent![ 'client_secret' ], googlePay: const PaymentSheetGooglePay( // Currency and country code is accourding to India testEnv: true , currencyCode: "INR" , merchantCountryCode: "IN" ), // Merchant Name merchantDisplayName: 'Flutterwings' , ` // return URl if you want to add // returnURL: 'flutterstripe://redirect', ), ); |
3. Display paymentsheet:
Dart
displayPaymentSheet() async { try { // "Display payment sheet"; await Stripe.instance.presentPaymentSheet(); // Show when payment is done // Displaying snackbar for it ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text( "Paid successfully" )), ); paymentIntent = null; } on StripeException catch (e) { // If any error comes during payment // so payment will be cancelled print( 'Error: $e' ); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text( " Payment Cancelled" )), ); } catch (e) { print( "Error in displaying" ); print( '$e' ); } } |
We will combine all this method and will call that function in elevated button
Dart
Future< void > makePayment() async { try { // Create payment intent data paymentIntent = await createPaymentIntent( '10' , 'INR' ); // initialise the payment sheet setup await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( // Client secret key from payment data paymentIntentClientSecret: paymentIntent![ 'client_secret' ], googlePay: const PaymentSheetGooglePay( // Currency and country code // is accourding to India testEnv: true , currencyCode: "INR" , merchantCountryCode: "IN" ), // Merchant Name merchantDisplayName: 'Flutterwings' , // return URl if you want to add // returnURL: 'flutterstripe://redirect', ), ); //Display payment sheet displayPaymentSheet(); } catch (e) { print( "exception $e" ); if (e is StripeConfigException) { print( "Stripe exception ${e.message}" ); } else { print( "exception $e" ); } } } |
Complete Code:
Dart
import 'dart:convert' ; import 'package:flutter/material.dart' ; import 'package:flutter_stripe/flutter_stripe.dart' ; import 'package:http/http.dart' as http; void main() { WidgetsFlutterBinding.ensureInitialized(); Stripe.publishableKey = 'pk_test_51JFH9zSGTdxZA1VVPlzCM1b4ztYvbz452v792r5iofLUkOdc15YdKHAv6VLSkt7qT5l643GIanpkbi8YCAQo47fm004YSyva3s' ; runApp( const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( debugShowCheckedModeBanner: false , title: 'Flutter Demo' , home: StripePaymentScreen(), ); } } class StripePaymentScreen extends StatefulWidget { const StripePaymentScreen({super.key}); @override State<StripePaymentScreen> createState() => _StripePaymentScreenState(); } class _StripePaymentScreenState extends State<StripePaymentScreen> { Map<String, dynamic>? paymentIntent; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text( 'Stripe Payment' ), ), body: Center( child: ElevatedButton( child: const Text( 'Make Payment' ), onPressed: () async { await makePayment(); }, ), ), ); } Future< void > makePayment() async { try { // Create payment intent data paymentIntent = await createPaymentIntent( '10' , 'INR' ); // initialise the payment sheet setup await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( // Client secret key from payment data paymentIntentClientSecret: paymentIntent![ 'client_secret' ], googlePay: const PaymentSheetGooglePay( // Currency and country code is accourding to India testEnv: true , currencyCode: "INR" , merchantCountryCode: "IN" ), // Merchant Name merchantDisplayName: 'Flutterwings' , // return URl if you want to add // returnURL: 'flutterstripe://redirect', ), ); // Display payment sheet displayPaymentSheet(); } catch (e) { print( "exception $e" ); if (e is StripeConfigException) { print( "Stripe exception ${e.message}" ); } else { print( "exception $e" ); } } } displayPaymentSheet() async { try { // "Display payment sheet"; await Stripe.instance.presentPaymentSheet(); // Show when payment is done // Displaying snackbar for it ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text( "Paid successfully" )), ); paymentIntent = null; } on StripeException catch (e) { // If any error comes during payment // so payment will be cancelled print( 'Error: $e' ); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text( " Payment Cancelled" )), ); } catch (e) { print( "Error in displaying" ); print( '$e' ); } } createPaymentIntent(String amount, String currency) async { try { Map<String, dynamic> body = { 'amount' : (( int .parse(amount)) * 100).toString(), 'currency' : currency, 'payment_method_types[]' : 'card' , }; var secretKey = "<secret_key>" ; var response = await http.post( Uri.parse( 'https://api.stripe.com/v1/payment_intents' ), headers: { 'Authorization' : 'Bearer $secretKey' , 'Content-Type' : 'application/x-www-form-urlencoded' }, body: body, ); print( 'Payment Intent Body: ${response.body.toString()}' ); return jsonDecode(response.body.toString()); } catch (err) { print( 'Error charging user: ${err.toString()}' ); } } } |
Output:
When Payment is uccessful:
When Payment is Cancelled:
Contact Us