Open In App

Flutter – Integrate Stripe Payment Gateway

Last Updated : 09 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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

WhatsApp-Image-2023-10-29-at-20632-PM-(2)

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:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads