Search code examples
flutterstripe-paymentsflutter-stripe

Flutter: Stripe payment sheet does not appear


I copied this code from various pieces found on the internet. I followed Stripe's instructions for the integration and now I do not receive any errors:

  • Use Android 5.0 (API level 21) and above
  • Use Kotlin version 1.5.0 and above: [example](https://github.com/flutter-stripe/flutter_stripe/blob/79b201a2e9b827196d6a97bb41e1d0e526632a5a/example/android/ .gradle#L2)
  • Using a descendant of Theme.AppCompat for your activity: example, example night theme
  • Using an up-to-date Android gradle build tools version: example and an up-to-date gradle version accordingly: example
  • Using FlutterFragmentActivity instead of FlutterActivity in MainActivity.kt: example Rebuild the app, as the above changes don't update with hot reload.

However, I don't even see the Stripe payment sheet appear. Do I have to set something on the Stripe dashboard?

Below is the Dart code:

_createPaymentIntent(String amount, String currency) async {
    try {
      //Request body
      Map<String, dynamic> body = {
        'amount': amount,
        'currency': currency,
      };

      //Make post request to Stripe
      var response = await http.post(
        Uri.parse('https://api.stripe.com/v1/payment_intents'),
        headers: {
          'Authorization': 'Bearer ${dotenv.env['STRIPE_SECRET']}',
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: body,
      );
      return json.decode(response.body);
    } catch (err) {
      throw Exception(err.toString());
    }
  }


  Future<void> makePayment(String? isTripRecuperato) async {
    try {
      //STEP 1: Create Payment Intent
      final paymentIntent = await _createPaymentIntent('20', 'EUR');
      print("dentro i pagamenti:");
      //STEP 2: Initialize Payment Sheet
      await Stripe.instance
          .initPaymentSheet(
          paymentSheetParameters: SetupPaymentSheetParameters(

            customFlow: true,
            merchantDisplayName: 'Drivehome',
            paymentIntentClientSecret: paymentIntent['paymentIntent'], //Gotten from payment intent
            customerEphemeralKeySecret: paymentIntent['ephemeralKey'],
            customerId: paymentIntent['customer'],

            //applePay: const PaymentSheetApplePay(
            //  merchantCountryCode: "IT",
            //),
            style: ThemeMode.dark,
          ))
          .then((value) async {
        //STEP 3: Display Payment sheet
        await displayPaymentSheet(isTripRecuperato);
      });

    } catch (err) {
      throw Exception(err);
    }
  }

  displayPaymentSheet(String? isTripRecuperato) async {
    try {
      await Stripe.instance.presentPaymentSheet().then((value) {
print("dentro il foglio ");
        if(isTripRecuperato == "true"){
          try{
            FirebaseDatabase.instance.ref()
                .child("ALL Ride Requests")
                .child(referenceRideRequestLastTrip.toString())
                .child("paymentStatus")
                .set("successful");
          }catch(e){print(e);}
        }else {
          try {
            FirebaseDatabase.instance.ref()
                .child("ALL Ride Requests")
                .child(referenceRideRequest.toString())
                .child("paymentStatus")
                .set("successful");
          } catch (e) {
            print(e);
          }
        }

        showDialog(
            context: context,
            builder: (_) => AlertDialog(
              content: Column(
                mainAxisSize: MainAxisSize.min,
                children: const [
                  Icon(
                    Icons.check_circle,
                    color: Colors.green,
                    size: 100.0,
                  ),
                  SizedBox(height: 10.0),
                  Text("Pagamento Effettuato!"),
                ],
              ),
            ));

        var paymentIntent = null;
      }).onError((error, stackTrace) {
        throw Exception(error);
      });
    } on StripeException catch (e) {
      print('Errore di pagamento ::::   ------> $e');
      AlertDialog(
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              children: const [
                Icon(
                  Icons.cancel,
                  color: Colors.red,
                ),
                Text("Pagamento Fallito!"),
              ],
            ),
          ],
        ),
      );
    } catch (e) {
      print('$e');
    }
  }


Solution

  • Sheet not opening because in payment intent api, APi not provide Empheral key secret just comment empheral key secret and sheet opening started..

    await Stripe.instance
              .initPaymentSheet(
              paymentSheetParameters: SetupPaymentSheetParameters(
    
                customFlow: true,
                merchantDisplayName: 'Drivehome',
                paymentIntentClientSecret: paymentIntent['paymentIntent'], //Gotten from payment intent
             //   customerEphemeralKeySecret: paymentIntent['ephemeralKey'],
                customerId: paymentIntent['customer'],
    
                //applePay: const PaymentSheetApplePay(
                //  merchantCountryCode: "IT",
                //),
                style: ThemeMode.dark,
              ))
    

    If you need to provide Empheral key secret then call this api before payment intent was call...

    cUrl: (Just paste this cUrl and you can call this api for customerEmpheral secret)

    curl https://api.stripe.com/v1/ephemeral_keys \
      -u sk_test_.....................................................: \
      -d "customer"="{{CUSTOMER_ID}}" \
      -H "Stripe-Version: {{API_VERSION}}"
    

    Official Stripe Doc: https://stripe.com/docs/mobile/android/basic#set-up-ephemeral-key-server-side

    Full code here:

     Future<void> makePayment() async {
        try {
          paymentIntent = await createPaymentIntent('34', 'USD');
          log("paymentIntent:::::::::${paymentIntent}");
          //STEP 2: Initialize Payment Sheet
          await Stripe.instance
              .initPaymentSheet(
                  paymentSheetParameters: SetupPaymentSheetParameters(
                // customFlow: true,
                merchantDisplayName: 'My Shop',
                customerId: paymentIntent['customer'],
                // customerEphemeralKeySecret: 'ephkey_1M...........',
    
                paymentIntentClientSecret: paymentIntent['client_secret'],
              ))
              .then((value) {});
    
          //STEP 3: Display Payment sheet
          displayPaymentSheet();
        } catch (err) {
          throw Exception(err);
        }
      }
    
      displayPaymentSheet() async {
        try {
          await Stripe.instance.presentPaymentSheet().then((value) {
            showDialog(
                context: context,
                builder: (_) => AlertDialog(
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: const [
                          Icon(
                            Icons.check_circle,
                            color: Colors.green,
                            size: 100.0,
                          ),
                          SizedBox(height: 10.0),
                          Text("Payment Successful!"),
                        ],
                      ),
                    ));
    
            paymentIntent = {};
          }).onError((error, stackTrace) {
            throw Exception(error);
          });
        } on StripeException catch (e) {
          print('Error is:---> $e');
          AlertDialog(
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  children: const [
                    Icon(
                      Icons.cancel,
                      color: Colors.red,
                    ),
                    Text("Payment Failed"),
                  ],
                ),
              ],
            ),
          );
        } catch (e) {
          print('DErrrrrr$e');
        }
      }
    
      createPaymentIntent(String amount, String currency) async {
        print("In Price");
        final dio = Dio();
    
        try {
          print("In Try");
    
          var response = await dio.post("https://api.stripe.com/v1/payment_intents",
              // url("https://api.stripe.com/v1/prices"),
              // queryParameters: {},
              options: Options(headers: {
                'Authorization': 'Bearer sk_test_your_key_here',
                'Content-Type': 'application/x-www-form-urlencoded',
              }),
              queryParameters: {'amount': calculateAmount(amount), 'currency': currency, 'customer': 'cus...', 'payment_method_types[]': 'card'});
    
          if (response.statusCode == 200) {
            print(response.data);
    
            print("Ram::::::::::::Success");
          } else {
            print(response.data);
          }
          return response.data;
        } catch (e) {
          print("In Try");
    
          print(e);
          print("Ram::::::::::::False");
        }
      }
    
      calculateAmount(String amount) {
        final calculatedAmout = (int.parse(amount)) * 100;
        return calculatedAmout.toString();
      }
    

    Put your client_secret, customerId and etc..

    That after call makePaument method on ButtonClick

    TextButton(
                  child: const Text('Make Payment'),
                  onPressed: () async {
                    await makePayment();
                  },
                ),