Stripe Checkout in Flutter Web
Flutter Web is getting more mature every day. I believe it’s about the time we should start focusing on migrating all the Flutter mobile knowledge to the browser environment. In that spirit, after writing an article on using Stripe Checkout in mobile Flutter apps, I think I should also show you how to easily collect payments on the web and that’s what this article is about.
This article is a continuation of Stripe Checkout in mobile Flutter apps. You may want to read the previous one to get the most of it.
. . .
Why is it different from mobile?
You may be thinking “Why can’t I just use the code from the previous post and deploy it on the web? It should work, right?”
Well, there is one big reason and one minor reason for that:
- The big one is that on mobile we were using WebView package for displaying the checkout page. This package doesn’t support Web so that is a party-stopper for us. Besides, why would we use WebView, when we are already on the web?
- The other reason is that we have been using a “server stub” to act a as fake server creating the session. If we run our flutter web app locally, we cannot do https request (as far as I know) and Stripe only accepts those kind requests for creating sessions. Because of that, we will modify our workflow to use client-only integration which is a way to collect payments without the backend server.
. . .
Calling JS functions without webview
As you may remember, to use Stripe Checkout, we need to call JavaScript function redirectToCheckout
from the Stripe library. On mobile, we used webviewController.evaluateJavaScript
for that, on the web we will use library named js.
For me, this library works like magic, we can use @JS()
annotations to create Dart classes that will be used as javascript classes in the running app. Honestly, I still have no idea how it works but it does so we will stay with it. ? First, we need to see what we would have to do in normal HTML/JS environment according to Stripe documentation:
The easiest part is copying <script src="https://js.stripe.com/v3/"></script>
to index.html
. You can find it in the web
directory of your Flutter project. Just copy that line inside <head>
.
Now we need to analyze what are the classes provided in the Stripe library. First, there is a Stripe
class that has a constructor accepting the key and the redirectToCheckout
method which contains some parameters. What we have to do is to create a Dart class that has the same contract as this one:
Notice that we don’t implement anything. We’re just creating a dummy Dart class and annotate it with @JS
. This will cause a running Flutter app to create a JavaScript Stripe object coming from the package we previously added in index.html.
? Ok, but what are CheckoutOptions
and how will Stripe know how to process them?
It’s just another class that will represent data needed by Stripe library. We are using them to determine products we want to sell, what time of payment we will accept and where to redirect in cases of success or cancellation.
Besides @JS
annotation, we are also using @anonymous
because in JS example from the docs you can see, that there are no class names, just anonymous objects with fields.
? Alright, we have created a few weird-looking classes that don’t really do anything. How do we use them?
The same you use any Dart code! The Dart-JS mapping will happen without you doing anything more!
Technically, that’s all. This code when run on Flutter Web should redirect you to the Stripe Checkout page. After succeeding it will then redirect you to a specified URL. In our case it’s http://localhost:8080/#/success
.
Obviously, it’s better to not redirect to the localhost in the production app and point to a nice and fancy domain. ?
On button click, we will call redirectToCheckout
and that how it should look like:
. . .
One codebase for all platforms
In this post, I showed you how to do stripe checkout which will work only on the web. In the previous one, it worked only on mobile. I think it might be a good idea to show you how to make it work on both platforms at the same time.
The crucial problem to overcome is that we cannot use JS library on mobile. We can’t even import it! In order make it work, we need to create a file that will conditionally import mobile or web packages depending on the platform it’s run on. It can look like this:
What happens here is the first redirectToCheckout
method tries to import stripe_checkout_stub.dart
but if it’s run on mobile, it will use stripe_checkout_mobile.dart
instead and on the web, it will use stripe_checkout_web.dart
instead. Therefore the stub method should never be called. The mobile and web implementations are the ones created in this and previous post.
. . .
And that’s it!
Now we can accept payments on all platforms ?
As always, the whole code is on the Github [here].
The YouTube version is [here].
If you missed part 1, be sure to see Stripe Checkout on mobile.
And if you want to learn more about Stripe Checkout, the official docs are very well written.
If you have any questions or ideas for improvements, let me know in the comments!
Cheers! ?
Marcin Szałek
Founder of Fidev
Flutter enthusiast since Alpha release in 2017. Believes that sharing is caring, which lead him to start a technical blog dedicated fo Flutter in its early days. Loves to see beautiful designs become real apps and is willing to help make it happen. Enjoys sunny beaches far from home.
Join the newsletter!
Join the newsletter to keep track with latest posts and get my special Widget to animate views' entrances without any hassle for FREE!
Check out other posts!
Stripe Checkout in mobile Flutter app
Have you ever struggled to integrate card payments into your mobile Flutter app? If so, today is your lucky day! In this post, I present how to use Stripe Checkout in the Flutter app without any hassle!
Interacting with Widgets using Framy
Have you ever developed a widget or a page and you wanted to make sure it works correctly in different scenarios but then it turned out that you can’t just reproduce all the cases you want to cover? Framy may solve such problems!
Water Drop effect in Flutter
In this post, I’d like to share with you how to achieve a water drop effect in Flutter. Why would you spend your time learning such skill? Well, I have no idea but it looks cool so let’s get started! ?
That’s amazing sir but don’t know from where do you learn all this things! please tell us so we can also create this kind of application! From where do you learn this things?
Practice, practice and even more practice!
Hi there, just wondering if you could show us how to do multiple items in a cart for web view, I managed to work it out for mobile but not web.
Putting more elements in “lineItems” doesn’t work?
Unfortunately no… Unless, I am doing it wrong. Are you able to show us an example?
hi, thanks so much for your amazing contribution, but i can’t get it to work for production keys, even though ‘client only integration’ is enabled.
“Uncaught IntegrationError: Live Stripe.js integrations must use HTTPS”
did you get it to work with production keys? Thanks again
Well, as the error says, it needs to be on HTTPS. Meaning it has to be deployed on the real server, not your local host. 🙂
Thanks for your answer, the truth is I am somewhat lost, the Stripe packages for Flutter do not work or are incomplete (despite the efforts of the creators), and I thought that Checkout would help me, but I have little time and I see that it is complicated to understand. Hope to try again later. Thanks again
hi ,thank you for your awsome video.
can you create a video tutrial or post
about flutter navigator 2.0
(thing like nested route such as instagram )
it is so hard (at least for me) to implement this
plssssss create a tut if you have enough time
????
Hey, thanks 🙂
Regarding navigator 2.0, so far I haven’t come up to try it out, I’ve heard many people complaining about it so I hesitate for now.
thanks man.
take care and stay safe
Hello, this is a fantastic tutorial. Thank you very much!
I am trying to have the success page return to me the CHECKOUT_SESSION_ID as specified in the stripe docs but don’t seem to have success with that.
I tried
http://localhost:8081/#/success?session_id={CHECKOUT_SESSION_ID}
as stated in the stripe docs.
I also tried
http://localhost:8081/#/success/{CHECKOUT_SESSION_ID}
as suggested by someone else on stackoverflow.
Neither works. Any ideas? This would be huge for me.
Hey!
Have you added it to “redirectToCheckout” method? What does it mean it doesn’t work? It redirects to /success instead?
Excellent post! Your tutorial is clear, simple and worked wonderfully for me.
Please would you be able to provide an example that doesn’t use Stripe Checkout? An example of how to use the Stripe Credit Card details page and get a tokenized version of the credit card entered to make a purchase on that card? This would be extremely useful, have search all around the web and haven’t found a single example of this sort.
Hi thanks for the tutorial! How can you add other payment methods such as ‘bancontact’ to the checkoutpage? I found documentation for other languages but not for flutter… Can you please help me?
hi is it possible to do on flutter_stripe_web package
Thanks for the tutorial! How can I update the user info on the flutter frontend after buying a product?