flutterdartstripe-payments

Opening new screen is not being executed


I have a Flutter app that I want to add Stripe to so I can charge users. I have added Stripe to the registration page so when a new user registers, they can enter their payment information.

Here is the code where I try to go to the Stripe screen:

 onPressed: () async {
                    setState(() {
                      showSpinner = true;
                    });
                    try {

                      final newUser =
                          await _auth.createUserWithEmailAndPassword(
                              email: email, password: password);
                      if (newUser != null) {
                        
                        Navigator.of(context).pushReplacement(MaterialPageRoute(
                            builder: (context) => const StripePaymentScreen()));

                        Navigator.of(context).pushReplacement(MaterialPageRoute(
                            builder: (context) => const VerifyEmailScreen()));
                      } else {
                        setState(() {
                          registrationFail = true;
                        });
                      }
                      setState(() {
                        showSpinner = false;
                      });
                    } on FirebaseAuthException catch (error) {

So, if the user account for the app is created successfully, I want to go to the Stripe screen but it executes the code but the screen does not display. I want the Stripe screen to display, let the user enter their information, and then the code can proceed and sent the verification email.

What am I doing wrong?

Here is the Stripe code:

class StripePaymentScreen extends StatefulWidget {
  const StripePaymentScreen({super.key});

  @override
  _StripePaymentScreenState 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: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              child: const Text('Make Payment'),
              onPressed: () async {
                await makePayment();
                Navigator.pop(context); // return to User Registration Screen
              },
            ),
          ],
        ),
      ),
    );
  }

  Future<void> makePayment() async {
    try {
      paymentIntent = await createPaymentIntent('100', 'USD');

      //STEP 2: Initialize Payment Sheet
      await Stripe.instance
          .initPaymentSheet(
              paymentSheetParameters: SetupPaymentSheetParameters(
                  paymentIntentClientSecret: paymentIntent![
                      'client_secret'], //Gotten from payment intent
                  style: ThemeMode.dark,
                  merchantDisplayName: 'Ikay'))
          .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: (_) => const AlertDialog(
                  content: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(
                        Icons.check_circle,
                        color: Colors.green,
                        size: 100.0,
                      ),
                      SizedBox(height: 10.0),
                      Text("Payment Successful!"),
                    ],
                  ),
                ));

        paymentIntent = null;
      }).onError((error, stackTrace) {
        throw Exception(error);
      });
    } on StripeException catch (e) {
      //print('Error is:---> $e');
      const AlertDialog(
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              children: [
                Icon(
                  Icons.cancel,
                  color: Colors.red,
                ),
                Text("Payment Failed"),
              ],
            ),
          ],
        ),
      );
    } catch (e) {
      print('$e');
    }
  }

  createPaymentIntent(String amount, String currency) async {
    try {
      //Request body
      Map<String, dynamic> body = {
        'amount': calculateAmount(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());
    }
  }

  calculateAmount(String amount) {
    final calculatedAmout = (int.parse(amount)) * 100;
    return calculatedAmout.toString();
  }
}

Solution

  • if you have already create a user, then your intent to navigate to payment screen but you don't .

      if (newUser != null) {
        
        Navigator.of(context).pushReplacement(MaterialPageRoute(
            builder: (context) => const StripePaymentScreen()));
    
        Navigator.of(context).pushReplacement(MaterialPageRoute(
            builder: (context) => const VerifyEmailScreen()));
      }
    

    after you have navigated to the payment screen, you changed your navigation to verify email address screen, just navigate to payment:

      if (newUser != null) {
        
        Navigator.of(context).pushReplacement(MaterialPageRoute(
            builder: (context) => const StripePaymentScreen()));
    
      }