Picture this. You are building an amazing app that allows users to subscribe or to buy anything available on your app. When considering the User Experience, you decide that redirecting out of your app is not ideal and you want to build out an in-app solution yourself.
If this is you, you are in the right place! In this tutorial, we are going to go over how to create your own Subscription module inside your app, that is powered by Stripe.
This is going to be a multi-part series starting with subscriptions, then one off payments, frontend implementation, and best practices.
Step 1: Setting up a Stripe Account
In order for you to interact with Stripe in any manner, you need to make sure that you have an account. If you don’t have one yet, go over to https://stripe.com to sign up.
One of the prerequisites for creating a Stripe account, is selecting a country that they currently cover. This is because, once you decide to go live, there are some business details that they want you to provide.
If your country is not covered, you could explore the configuration in the test environment or better yet, you may need to look for a local payment provider.
Step 2: Integration with Your Backend
Once you are in the Dashboard, you will simply head over to the “Developers” section and this is where you will find your API keys
Stripe does an amazing job documenting their APIs and therefore it should be a breeze for you to get this configured in your backend.
The First API we are going to configure is the Create Customer API. All we will need to do, is head over to the Customer section of the documentation and select Create Customer. You will find a cURL command that you will copy and paste in the Import cURL section of our External API Request feature.
Unfortunately, it does not have other attributes attached but you can manually add those yourself similar to how we are adding the name field below.
In the end, you will have something that looks like this
In our use case, we want to use dynamic data from our User table, we want to check that the API has gone through successfully using the If-Condition then update the user record to now store the customer id Stripe sends back to us.
And we are done!
The other amazing thing about their APIs is that, if you do face any errors in trying to set up a certain API call, they'll give you the exact information about where you might be going wrong.
For example, if you try to pass a value that the Stripe API does not recognize or is not expecting and run the API, it will return the following error (I named the parameter “no” to break it on purpose😁):
Step 3: Creating Cards, Products and Prices
Before we dive in, I just want to talk about use cases. First question I would ask myself is, “What is my use case?”. For example, I might have an app that only requires fixed prices/products so therefore I could define these directly in the Stripe Dashboard.
From there I would store the price/product ID in my Xano database and always reference it from there.
The second scenario could be where we don't know the final price that the user is going to end up having to pay once they checkout, therefore we would need to dynamically create these prices.
If your Use Case is scenario 2, The great news is, Xano already has a Prices Snippet and a Products snippet in the Marketplace, specifically inside the Payments category. These contain the full suite configuration of each object as well as a webhook API. Snippets are an easy way to share API endpoints with the Xano community and the ones mentioned above will allow you to manage everything related to your prices and your products directly inside your app.
For this tutorial, my use case is, I have an app where users pay one fixed price monthly or one fixed price annually. I would then create a “controller” table and create the fields that will store the monthly and annual price ids.
Create A Card (Payment Method)
Similar to the configuration above, we are going to head to the Stripe documentation, specifically the Card section.
In the end, we will have our function looking like this:
In the first step, we are fetching our user record, then in the second step, we are concatenating the url with the current user’s Stripe ID then call the API.
Unfortunately, the cURL provided to us does not include all the attributes we will need but we can manually add them just like we did with the Customer API.
From there, we only store the token returned by Stripe and link it to our user’s id.
The If condition will be a common theme because it is essential that we listen for possible errors and take the necessary actions (e.g Creating an error log table that will store the full json response as well as send you/product owner/team an email that an error has occurred.)
Create A Subscription
Now that we've created our customer, our prices and payment details for our user’s wallet, we can actually proceed to charging the user for this subscription.
When we go over to the Stripe docs’ Subscription section, the cURL code has all we need to make the API call. As shown previously, we will fetch our customer id from our user table and in this scenario, we will fetch the price id from our controller table.
Depending on your bandwidth/feature priority, you can manage cancellations by using the Delete API or you could manually handle those in the Dashboard.
Step 4. Implementing Webhooks
Webhooks allow us to know about the important activities that are happening without having to get into our Stripe dashboard. Inside here we will be able to define configurations such as communications to clients, logging of the subscription’s monthly transactions (when they got paid, invoice data, invoice status, etc.) and much more.
In order to implement this, you will go to the “Developers” section and head to the webhooks tab. You may be tempted to select multiple events at a time however Stripe will not be able to resolve that because different events return different response data.
To avoid this mix up, only select 1 event at a time or if the events share the same json output structure, you can have more than 1 event listener in the API. However, keep it limited just to be one the safe side at the beginning. Then gradually add others to the webhook.
In this scenario I will be pairing the “invoice.payment_succeeded” and “invoice.payment_failed” events. Below is an image where Stripe illustrates how their webhook process works
Once a new payment goes through/ fails, Stripe will call our endpoint and send some payload data that we can work with.
You will know that your endpoint has been notified by going to your API Request History but to avoid having to manually check, you can add a step inside the function stack that sends out notifications to the relevant stakeholders (including your user).
The Payload data will include the subscription id therefore we can use this to search for any existing subscriptions in our table that match this id. We could also create a table to log transactions so that we can store the invoice ids for future use.
And just like that, we have reached the end of Part 1. We have tons more to explore, so feel free to let me know in the comments what you would like to see next in this Stripe Integration series.
Further Reading
API Documentation: https://stripe.com/docs/api
Error Codes: https://stripe.com/docs/api/errors#errors-code
Test Cards: https://stripe.com/docs/search#query-fields-for-subscriptions
Webhooks: https://stripe.com/docs/webhooks#secure-webhook
https://docs.xano.com/api/webhooks