Mastering Stripe Subscription Custom Checkout Flow: Server Side and Client Side Implementation
Nikin Shan Faizal
January 23, 2024
Stripe Subscriptions is a sophisticated service provided by Stripe, a popular online payment processing platform. It lets businesses to effortlessly manage and bill their consumers on a recurring basis, generally for subscription-based products or services. Let’s break down some key concepts:
note : you should have to add a price to save the product
Install the Stripe client of your choice:
Plan and pricing model will be created in stripe account and will be displayed in client side with the help of priceId as shown below. After you create the prices, record the price IDs so you can use them in other steps. Price IDs look like this: price_1ORsMKDXxvvhRkJtLHm0O2yT.
Each price id represents different price plan, Its recommended to create priceId for free plan too with zero value so that you can provide free trial for 3 months or one month as per your convenience.
Stripe needs a customer for each subscription. In your application frontend, collect any necessary information from your users and pass it to the backend. Customers can be created in initial stage while registering to an account or can be created while choosing a plan based on your use case.
On the server, create the Stripe customer object with the necessary information passed from the frontend.
Then the customer would be added into the stripe account as show below.
By a choosing a plan from step-2, customer will be directed to a checkout form where they have to enter their credit or debit card details for purchasing a subscription. Stripe often provide prebuilt checkout form but here we are discussing about how to collect payment from a custom checkout form of our design or brand.
By clicking on the choose plan option, send the priceId selected by the user to backend(server side)
Create the subscription with status incomplete using payment_behaviour=default_incomplete. Then return the client_secret from the subscription’s first payment intent to the front end to complete payment.
Set save_default_payment_method to on_subscription to save the payment method as the default for a subscription when a payment succeeds. Saving a default payment method increases the success rate of future subscription payments.
Here we are sending back paymentIntent-client secret and subscriptionId to frontend for completing the payment, this client secret acts as a connection to the subscription which the user has selected. At this point subscription will be inactive and will be active only once the payment is confirmed from the client side.
For collecting payment informations like credit or debit card details, cvv, expiry are collected using Stripe Elements. They securely collect all payment informations and also you can customize Elements to match the look-and-feel of your application.
Load Stripe by using loadStripe from “@stripe/stripe-js” and wrap your whole checkout form with Element provided by “@stripe/react-stripe-js” as shown below.
Use PaymentElement provided by ‘@stripe/react-stripe-js’ to display checkout form
note : If you want to customize each field like card number , Expiry or CVV, stripe provides:
To pass confidential information collected from users to stripe, the best practice is to access the elements and use it with stripe.ConfirmPayment as shown below. Here stripeHooke provides a reference to the Stripe instance passed to the Elements provider.
stripe.confirmPayment confirms the payment and once the payment succeeds, it redirects users to the return URL
You will be able to add HTTP URL in local event listener, such that you will be able to test working of webhook in local.
Add this middleware to handle incoming requests. If the original URL is “/webhook,” it allows the request to pass through without parsing the JSON body. Otherwise, it uses the bodyParser middleware to parse the JSON body of the request.
The variable endpointSecret holds the secret key associated with your webhook endpoint. This key is used to verify the authenticity of incoming webhook events.
This part of the code is responsible for verifying the Stripe webhook signature and extracting the event.
In our specific context, we have already initiated the subscription process on Stripe, but it remains partial or incomplete. To finalize and update the subscription details upon payment confirmation, we rely on webhook events provided by Stripe. In particular, we are interested in the “payment_intent.succeeded” event.
If the event called “payment_intent.succeeded” is triggered, then we could update our local database as well and this could complete your whole subscription payout journey.
We discussed whole stripe subscription checkout journey from initiation to the completion using stripe webhook. The initialization of the Stripe library is a crucial step, and it’s important to replace the test secret key with the live secret key in a production environment. This ensures that real transactions are securely processed, maintaining the integrity and confidentiality of sensitive information. You can also use the help of test clock in stripe so that you could analyze the working of your subscription by providing future date in the test clock, thus make your subscription integration flawless.