Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Payment Element Stripe with Flutter Web

anyone managed to integrate stripe payment buttons such as gpay and apple pay to flutter web, I know there is still support for flutter web, but if there was another way to achieve it, it would be of great help

Thanks

https://stripe.com/docs/stripe-js/elements/payment-request-button

I give you the stripe link where you can see the documentation and the buttons to which I refer

https://stripe.com/docs/stripe-js/elements/payment-request-button

News: Review the example of my github repo, I solve it https://github.com/TKevinTL/stripe_monei_payment_flutter.git

like image 988
Kevin Avatar asked Jun 23 '26 21:06

Kevin


1 Answers

It is theoretically possible to use Apple Pay or Google Pay using the PaymentElement object in the flutter_stripe_web package. However at the time of this writing, the flutter_stripe_web documentation is not clear and I was unable to use it successfully in my own testing.

Instead for my Flutter web project, I used Stripe.js to add an Apple Pay button to an HTML page, then I embedded the HTML page in my Flutter screen using the HtmlElementView widget. Here are instructions for how to do this.

Getting started

Before starting the code, you'll first need to:

  1. Have an active Stripe account
  2. Add your web domain to the Payment Method Domains in your Stripe dashboard
  3. Follow the instructions to verify your domain, which means adding the domain association file (provided by Stripe) to your project and making it available at https://yourdomain/.well-known/apple-developer-merchantid-domain-association

HTML file and Stripe.js element options

Then you should create an HTML file in the web directory in your Flutter project and place the Stripe payment element in it. There are two primary options with Stripe.js to get an Apple Pay or Google Pay button:

  • You can use a Stripe Payment Request Button
  • Or you can use a Stripe Express Checkout Element

The Payment Request Button is deprecated, and Stripe recommends the Express Checkout Element. The primary difference is that the Express Checkout Element displays multiple platform payment options/buttons on the screen at one time vs. the Payment Request Button only shows one button (Apple Pay, Google Pay or Link depending on what the user's browser and device supports).

For my project, I was looking for a very simple solution to support Apple Pay only, so I chose to use the Payment Request Button. But the approach is the same either way.

Here is a simplified version of my HTML file:

<!DOCTYPE html>
<html>

<body>

<form id="stripeForm">
    <div id="payment-request-button"></div>
</form>

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://js.stripe.com/v3/"></script>

<script>
var stripe = Stripe('your stripe publishable key');

const appearance = {
    theme: 'stripe',
};
var elements = stripe.elements({ appearance });

const paymentRequest = stripe.paymentRequest({
    country: 'US',
    currency: 'usd',
    total: {
        label: 'Your Payment Description',
        amount: 100,
    },
});

paymentRequest.on('token', function(event) {
    event.complete('success'); // this tells the device to close the payment sheet
    parent.stripe_result(event.token.id); // send the token back to Flutter
});

const paymentButton = elements.create('paymentRequestButton', {
    paymentRequest,
});

(async () => {
    // canMakePayment determines if the user has a wallet available (Apple Pay, Google Pay, or Link)
    // We use this to only display the payment button if the user has Apple Pay
    const result = await paymentRequest.canMakePayment();
    if ((result != null) && (result.applePay == true)) {
        paymentButton.mount('#payment-request-button');
    } else {
        console.log('Apple Pay not available');
    }
})();

</script>
</body>
</html>

This creates a payment request and adds the button to the screen. canMakePayment() in Stripe.js is effectively the same as isPlatformPaySupported() in the flutter_stripe package. It verifies if the user's browser and device supports platform pay. The code then only displays the button if it does (and in my case, it only displays a button if Apple Pay is supported because my use case for now is for Apple Pay only).

Handling the payment

You will want to customize the code depending on your payment use case. In my project, I only needed to get a token back from Stripe to then use for future recurring, variable payments. If you are trying to have the user pay for a specific charge, then you would likely:

  1. Have your Flutter code pass in the payment amount and details to then use in the JS paymentRequest
  2. Create a Stripe payment intent using a server side function called from either your Dart code or additional JavaScript in the HTML file, then get the Stripe client secret from the payment intent and use it when initializing Stripe elements
  3. Add more JavaScript code to complete the payment, or pass the data back to your Dart code and have it complete the payment

My example omits those steps because they were not needed for my project.

Dart file with HtmlElementView

Lastly you should create a Dart file in your Flutter project that includes an HtmlElementView to embed the HTML file and view the button. Here is a simplified example:

class WebApplePay extends StatefulWidget {
  const WebApplePay({
    Key? key,
  }) : super(key: key);

  @override
  _WebApplePayState createState() => _WebApplePayState();
}

class _WebApplePayState extends State<WebApplePay> {
  html.IFrameElement? _element;

  @override
  void initState() {

    // This creates the iframe element
    _element = html.IFrameElement()
      ..width = '200px'
      ..height = '50px'
      ..style.border = 'none'
      ..allow = 'payment'
      ..src =
          'apple_pay.html';

    // This registers the HTML element (the iframe) to allow us to embed it in the Flutter UI below
    // ignore:undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory(
      'StripeApplePay',
          (int viewId) => _element!,
    );

    // This listens to the result from the HTML/JS; when the HTML/JS page sends a result to parent.stripe_result in the JS code, the same data then is received here in our Flutter code
    js.context["stripe_result"] = (result) {
      print('Flutter received Stripe result');
      print(result);
      // ADD YOUR CODE TO DO SOMETHING WITH THE RESULT HERE
    };

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
          width: 250,
          height: 100,
          child: HtmlElementView(
            viewType: 'StripeApplePay',
          ),
        ));
  }
}

My project is published on web, iOS and Android so this screen is only used when web is detected.

I hope this is helpful to others!

like image 121
most200 Avatar answered Jun 27 '26 08:06

most200



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!