How to integrate your Bubble.io app with Stripe via the API connector

Dennis H. Lewis shows how to connect Stripe to Bubble.io using the API connector instead of the native plugin. You get embedded payments, multiple customer IDs per user, better error handling, and access to Stripe's full API. He walks through the API Connector setup, subscription parameters, and webhook handling for renewals.
Questions this video answers
Dennis H. Lewis (Ratio.dev).
application/x-www-form-urlencoded.
Stripe payment element bds (referred to as the Stripe payment element plugin).
ratio.dev (no Code Resource Center).
Chapters
All right, listen up. If you're using Bubble's native Stripe plugin for processing payments, you're probably bumping into obstacles that are making your life harder than it needs to be. And I'm about to show you exactly why, and even more important, how to fix it. Here's the thing that most Bubble developers don't realize. I'm Dennis Lewis from Ratio.dev and after 40 years in tech problems, from IBM's secret AIX team to building applications that serve hundreds of thousands of users, I can tell you this. Your payment flow is the most critical element in your entire application. Every single drop of friction matters. And here's what drives me crazy. Bubble's native Stripe functionality. It's holding you back in ways that you probably don't even realize yet. And today, I'm pulling back the curtain and showing you exactly how we integrate stripe@ratio.dev using the API connector, the same method we use for clients who are processing real money, real transactions, and can't afford to have things break. So let me paint you a picture that's probably way too familiar. You've been spent weeks building your app. You're ready to take payments. You install the native Stripe plugin because, hey, it's built in by Bubble. It's supposed to work, right? And it does. I'm not saying it doesn't, but. And then issues start popping up. First issue, it always redirects users away from your app. They click buy, and they get whisked off to Stripe's checkout page. And then hopefully they come back. But what if they don't? What if they close the tab? What if the redirect fails? Your workflow just stops dead and you really don't have any control. Second issue is you can only handle one Stripe customer ID created per user, which often is fine until you're building a marketplace, or you need sellers and buyers, or you want different payment profiles for different use cases. Or maybe you have a company table and that's who the client really is, and they have separate users under there. And now you've got the Stripe payment thing associated with one employee of your customer's company, and they happen to move on, and suddenly that Stripe account is no longer viable. And all those subscriptions, it can just get messy and you're stuck. And the third issue is, and this is the killer, when a payment fails, your entire workflow breaks. There's no graceful recovery. There's not really any retry logic, just crickets. And good luck debugging what actually went wrong. Because Bubble's native functionality doesn't really give you much visibility into what's going on. And for me, these are reasons why I prefer to build my Stripe integrations another way. And that's what I'm going to show you right now. Look, before we do, I do want to recommend that you go to ratio.dev and you sign up for our no Code Resource Center. It is chock full of vetted plugins, how to videos, great books to read, our podcast episodes, and it will level up your game on this Bubble journey that you're on. It's totally free. All you have to do is go in, put in your name and your email. You get immediate access. We update it every week so you know you're getting fresh content and I think it's really worth your while. But anyway, let's continue with the video. Look, I'm not saying that the native Bubble plugin is bad for lots of very simple use cases. It's fine. But if you're serious about building a real business, if you want control, flexibility and the ability to handle Edge cases gracefully, you need to integrate with Stripe directly. And I recommend just doing it with Bubble's API connector. Here's what that gets you. First of all, you get embedded payments. And yes, we do use the Stripe JS plugin for that, but you can do that natively as well. And everything stays in your app, so so you've got complete control over the look and feel of that payment flow and you can reduce friction. They don't get sent off to hosted checkout pages. Full API access. You can do anything that Stripe offers, not just what Bubble has decided to expose. One case that happened to me not long ago was that Stripe updated their API and changed some parameters. They weren't terribly important, but Hubble hasn't caught up to that yet. And it broke the ability to pass coupon codes with subscriptions on Stripe users that are on that latest API. And unfortunately, if your Stripe account is relatively new, you can't go back. So you're kind of stuck. And the only way around that was to actually go straight and modify those parameters in the API calls and boom, it works really, really well. Multiple customer IDs per user, so great for marketplaces and more complicated payment flows. Graceful error handling, you can, you can recover back and decide you know what how to proceed when something goes wrong. And first of all, I'm going to jump into the Bubble builder and I'm going to show you how to the pieces of everything that we're going to be using. So first of all, I do recommend a plugin called the Stripe payment element bds. This gives you a lot of the functions API calls already pre built, which is great. Usually that's more than enough for what you're going to need. But the good thing about this plugin is that you can combine with your own API calls in the API connector and still use this for the embedded checkout functions and more normal sort of things that you don't need to build API calls for. I have a whole video on this how to use this plugin, so I'm not going to go into too much detail, but you just put in your API keys up there at the top and you're good to go. Now here's a pro tip. When you're setting this up, make sure you use Bubble's built in environment variables so you're not hard coding in sensitive keys into your app. We'll talk about that later as well. But once you've got this plugin, you're able to do a lot of things just right off the bat with that. The next thing I'm going to show you is a reusable element that we built and we use inside our apps to encapsulate all of the stripe checkout process so that you can easily put it on any page that you want and you're not having to maintain multiple versions of the, of the workflows and the steps in the process. So here I'm going to come in and we have a reusable element called stripe payment and it goes through steps. In this case we're asking the user for their email and their name.
Beforehand and then we proceed through. We have here the actual embedded checkout widget and then thank you. Or if there's an error, there's also going to be an error section here and we can also integrate this into your onboarding with your for your application. So user clicks on the button, sets up their subscription automatically. The pop up shows them the form to sign up for your platform and boom, in the end you've done the whole process in one seamless user flow. That makes it super simple for your users to purchase and log in all in one one flow. So one of the things this does, this gives you the ability to customize primary colors, background colors, what fields you're going to be asking for from the user. You can put the border radius so it can match yours. You can, you can adjust the color of the buttons. Um, you can tell it, do you want it to include phone numbers or Addresses and just gives you a lot of control so that the experience of purchasing feels like it's part of your application. The now let's look at some of the workflows that are going on inside this reusable element. We expose from this reusable element a custom event so that when I just put this reusable element on a page, all I have to do is trigger this custom event to open the pop up, show the stripe and go through the whole sequence. So all my logic in one nice little package here, one thing I am passing it through here as a parameter to the reusable element is I'm sending it back the pricing plan that they're signing up for. If I want to let them purchase or know with refunds are available. If it's just a one off purchase, I can also send them just the amount and it will just directly charge them. So I've got a lot of control there. And then when I'm in the workflows, what I do, I create a sales log. This allows me to make sure that I can keep track of abandoned checkouts because I'm keeping a log. And then I launch the actual subscription payment process here. And first step, I just move them from step zero to step one after they've given me their name and their email. This is important because Stripe's going to want the email to be able to create a customer. Then I need to create a customer if they don't have one already in the, in the table. So I do that with a another custom event which actually checks to see if they have a customer id. If it does, it just returns it. And if not it creates a new one for them and it returns that one. So now I have a seamless place to get the customer ID from. And then we're going to start using some actual API calls. And so I'm going to jump into the API connector and I'm going to go to Stripe. This is important that you see this because I was looking around and I don't think anybody has actually explained the, the, the intricacies of how to make the backend API calls. With Stripe. There's a lot of little peculiarities that if you don't get right, that's just not gonna work. And there's, it's. It's not documented anywhere clearly. First thing you wanna do is you wanna create your API. Create private key in the header because you don't wanna be passing the keys from your, from the client side in here. So you just put those and Those are going to stay in the server side. Content type needs to be application forward slash this X form URL encoded and these are the common headers. And then I'm going to show you here for creating a new subscription, you're going to make it an action. You're going to tell it that the data type is JSON. You're going to use the stripe post to the stripe subscriptions here. And. And now instead of what we would normally do is put in down here in the JSON object. Our parameters won't work with striper. So you're going to want to add the parameters in up here with add parameter and then you're going to want to make sure you include query string on all of them. The ones that are optional, you can mark optional. The ones you want to allow to be blank, you can do that. The ones that you want to be hidden from the interface, you just mark them as private. And so now you can just put in the customer ID the item you're going to need usually just one. So you just pass it through this key which is items bracket zero bracket price. So that's going to be the first element of the items array. You could have multiple ones if you want and you would just need to create more parameters and put them in there. Then you're going to put in the price code for that item which you're going to get from your Stripe account. Once you've created the product in stripe, you can pass the trial period, days, the behavior period. And here you can also pass through if you need for stripe to expand when it returns back the object. So here I'm asking it to expand the latest invoice confirmation and the pending price, pending setup intent, because I want that information to come back. And then finally I'm passing in a coupon code and you could have multiple of them or multiple discounts. So I'm with this format, I'm able to tell it which one and I'm just passing in one coupon and I've allowed it to be blank and optional so you don't have to pass a coupon. And then all you have to do is reinitialize the call up here and you just save that. And now you have this API call that you can call directly from inside the workflow that you are building in your, in your reusable element. And all you have to do here is pass it in the customer id the price, the trial period and the and the coupon code. One of another thing that I find useful is to create an option set for your pricing plans, you could do this in a database, but it makes it trickier when you want to be able to just assign a button to a specific plan because you know it doesn't have the unique ID necessarily for the specific row. Whereas with an option set, you can just pick it. So I would go here to pricing plan and here you can create the, if you want to have a default coupon text for it. If you have an ID number that's different for your development from your production, you can have that there. The trial days that it has, the price that goes with this, you can put as many different attributes in there and then you can just create as many plans as you want. And from there you can associate this, this option set with the subscription, with the sales log, with whatever else in your database. And by doing it this way, when you create the customer, you can put that, the customer ID in any table that you want. You don't have to use the secret fields that Bubble has, which are only for users. Here if you have company, you know, as a, you can just create the, you know, the customer ID from stripe as a field in that table. Be sure to keep your privacy rules set up correctly. And that way you can have multiple users for that company and they all share that one stripe connection on a company basis, which is a lot more coherent with many B2B business sort of scenarios. So I think that's, that's important. And then after we've created the subscription, we're going to retrieve the setup intent. This is just a standard stripe workflow. I'm creating a row in my subscription table for it. And then I'm also here, I'm making some changes to the user and to the company that the company name. And then what I do is I initialize the payment element. And what that will do is it'll, it'll, it'll make, that little embedded stripe element, will verify everything and make it show up. And then once they click through on the button, the payment button, it will either activate the success event. So if this stripe embed was successful, then you can trigger whatever custom event or backend workflow that you want to have happen. And if it fails, you can do another one and you can handle the failure gracefully. And that is a much more robust process for handling your payments, where you also have complete control over everything that's going on. One last element that you'll want to do is in your backend workflows, create a webhook so that stripe will be able to send you notifications every time that subscription is either renewed or if it fails, and then you can log that information and then you can make changes to the subscription and you can do whatever process internally in your application that you need to do to actually manage correctly those transactions. If it comes in and it the subscription is renewed, you're going to be able to get the amount and you can create a lot of that. If it fails, then you might want to send a notification email to the customer. You may want to flag that customer so that they have a big banner that says hey, your payment didn't go through. We can't let your accounts blocked or whatever it is that you need to do that will come in via this backend API that you're going to expose to Stripe and you put this information into Stripe so that it knows knows where it needs to send these signals. And with that you're pretty much there. You want to make sure that you configure the webhook correctly so that you're getting the right information. You can have multiple webhooks for different types of messages from Stripe. So that's good test mode versus Live mode. So always be sure to keep your keys in the API calls. Clear error handling, we've mentioned that. Then security Just be really careful with your privacy rules on any Stripe related or transaction related information you're getting back from Stripe so that you don't store it where it could be exposed in the user's browser. So let's just wrap this up. Why the native Stripe plugin falls short well, you're always redirecting. You can't associate the Stripe account with anything other than a user. Now the plugin I recommend for being able to embed the payment process in your application is the stripe payment element 3Ds that I shared with you. We've seen the reusable element here. We've looked at the workflows, we've looked at how to handle secret how to handle subscriptions, and we've also seen how to store the customer IDs wherever you want to store them. After all of this, if you would like some help doing this in your bubble application, feel free to reach out to us here at ratio.dev, we'd be more than happy to get you unstuck if you're stuck or just save you a bunch of time because we've done this many, many times. And if you have questions, leave them below. Also Remember, go to ratio.dev and sign up for our no Code Resource Center. You're gonna really like it. If you've enjoyed this video, please give it a. Like a thumbs up. If you would subscribe to our channel. That would just make my smile go from ear to ear. We really appreciate that, and thank you very much for watching this video. See you on the next one.
More from Dennis

Is Google Killing Websites? The Future of Search, SEO & Web Design After Google I/O

Something we're still looking forward to in Bubble: richer design experiences! #bubble #nocode #ai

Big mistake companies are making right now: firing employees instead of empowering them. #ai







