We are back again with the series of Stripe integration to ReactJS applications. A fortnight ago we discussed about the first most used method of which is direct checkout stripe integration in ReactJS application. Today we are going to explore yet another method which is subscription integration in ReactJS application.
Prerequisites
As we saw in the direct integration blog, the prerequisites of the subscription integration is also the similar. The prerequisites can be explored in the blog we wrote before for the direct checkout integration of Stripe in ReactJS applications.
Implementation guide
**
Step 1: Define product
For creating a subscription we need a product, this can be static i.e fixed products or dynamic products. We can create these products by stripe api as well.
Creating product api : Server.js
const stripe = require('stripe')('sk_test_XXXXXXXX');
const product = await stripe.products.create({
name: 'Gold Plan',
});
This would create a product which could be used in subscription.
This product need not to be a physical product, it can be a digital product such as Gold membership or Buying a course or any Saas tools etc.
Also these products can be created from stripe dashboard as well, and all the created products can be seen here.
Once a product is created we can add price to the product, a product can have one or more than one prices, once the price is created the product is ready to be used in subscriptions.
Step 2: Create price for product
Price is a key component that defines the cost and billing structure of your products or services. For subscriptions, Price defines how much and how often a customer is billed (e.g., $20 per month).This is also where having clear documentation, including ready-to-use invoice templates, can simplify how you present recurring charges and billing details to customers.
Each product can have multiple prices, i.e a Gold plan can be £20/per month, £100/per six months and £2000/per year.
Prices can be created using the stripe dashboard or stripe api also.
Api for creating price and associating it to the product
const price = await stripe.prices.create({
currency: 'usd',
unit_amount: 1000,
recurring: {
interval: 'month',
},
product: ‘product id ',
});
Different physical goods or levels of service should be represented by products, and pricing options should be represented by prices. This approach lets you change prices without having to change your provisioning scheme.
You can create product and price together using the stripe price api, where instead of product you can use the param
product_data: {
name: 'Gold Plan',
},
And this would create a product by name Gold Plan and attach the price mentioned to that product.
Step 3: Build a price/product view page
Now we need to show the price/products preview to users for them to subscribe, for this purpose either we can store the products in our database or we can retrieve the products and their prices from stripe as well, here showing how to retrieve the prices and products from stripe
const stripe = require('stripe')('sk_test_XXXX');
const prices = await stripe.prices.list({
limit: 3,
});
This will provide the product is as well associate with the price so we can retrieve the product as well using this id.
const stripe = require('stripe')('sk_test_XXXX’);
const product = await stripe.products.retrieve(‘product_id);
Step 4 : Register/Retrieve a customer
If the customer is already registered in stripe we would need its customer_id else we can create another customer and use customer_id to create subscriptions.
const stripe = require('stripe')('sk_test_XXXX');
const customer = await stripe.customers.create({
name: 'Jenny Rosen',
email: 'jennyrosen@example.com',
});
This would provide us the customer id which could be used for subscription.
Step 5 : Using all the above apis in client (react js) and creating a subscription.
const ProductDisplay = () => (
<section>
<div className="product">
<Logo />
<div className="description">
<h3>Starter plan</h3>
<h5>$20.00 / month</h5>
</div>
</div>
<form action="/create-checkout-session" method="POST">
{/* Add a hidden field with the lookup_key of your Price */}
<input type="hidden" name="lookup_key" value="{{PRICE_LOOKUP_KEY}}" />
Add checkout button for payment
<button id="checkout-and-portal-button" type="submit">
Checkout
</button>
</form>
</section>
);
Step 6 : Creating check out session for subscription in server.js
const stripe = require('stripe')('sk_test_XXXX');
app.post('/create-checkout-session', async (req, res) => {
const session = await stripe.checkout.sessions.create({
billing_address_collection: 'auto',
line_items: [
{
price: price_id,
// For metered billing, do not pass quantity
quantity: 1,
},
],
mode: 'subscription',
success_url: '(YOUR_DOMAIN)/?success=true&session_id={CHECKOUT_SESSION_ID}',
cancel_url: '(YOUR_DOMAIN)?canceled=true',
});
res.redirect(303, session.url);
});
This would create the subscription for the price with billing mode as auto debit, and mode of checkout as subscription, once success it will redirect your page to the Success or failure url.
This would create the subscription for that user.
Step 7 : Retrieve customer’s subscriptions
We can also retrieve the subscriptions for a particular user using the customer id.
const stripe = require('stripe')('sk_test_XXXX');
const subscriptions = await stripe.subscriptions.list({
limit: 3,
customer : customer_id
});
In this we can pass status as well to filter the customers subscription by the following status as cancelled, ended, incomplete, active, past_due etc.
Step 8 : Cancel a subscription
A subscription can be cancelled anytime using the following method of stripe in server.
const stripe = require('stripe')('sk_test_XXXX');
const subscription = await stripe.subscriptions.cancel(
‘subscriptionId’
);
This would cancel the mentioned subscription id and money will never be deducted for that subscription.
These are the general scenarios of implementation, now comes tracking the payments and what if first payment is successful but subsequent next payment fails due to card expired or insufficient balance, what if you want to provide 30 days free trial and then charge the customers for subscriptions, these all things are handled in stripe very smoothly.
Step 9 : Configure webhooks and listen to events
To track the subscription and payments we have webhooks, yes stripe subscriptions have different events which could be listened to on webhooks, so let's check the events and the status of subscription past each event.
-
Customer.subscription.created:** This event is triggered when the subscription is created first. Whenever the subscription is created the status of the subscription is incomplete.
-
Invoice.paid: Wherever a payment is attached and payment initiated this webhook event is called.
-
Invoice.payment_succeeded: Whenever the payment succeeds this webhook event is called, so you can do the database modifications as and when required.
-
Invoice.payment_failed: Whenever payment fails this webhook is called with the reason for failure, you can use this to do the necessary modifications.
Actual Life cycle of subscription from creation to cancellation
**
Create the Subscription:
When you create the subscription, its status will be "incomplete" if you follow the recommended flow. However, if you don't specify the payment_behavior, the default status will be "active."
Invoice Creation:
An invoice is generated for the subscription, initially with a status of "open."
Customer Payment:
The customer pays the first invoice.
Payment Success:
-
The subscription status changes to "active."
-
The invoice status updates to "paid."
-
Stripe triggers the invoice.paid webhook event.
Provision Access:
You can provide access to your product. To verify the invoice payment:
-
Set up a webhook endpoint to listen for the invoice.paid event.
-
Alternatively, manually check the subscription object to confirm the status is "active." This status indicates payment has been completed, either automatically or manually by the customer.
If you offer trials that don’t require payments, the status may initially be "trialing." Once the trial ends, the status changes to "active," and the customer begins to be charged.
Points to consider while integrating Subscriptions for stripe
-
Subscription Plans: ** Clearly define your subscription plans, including pricing, billing cycles (e.g., monthly, annually), and any special features like free trials or tiered pricing.
-
**Trial Periods: ** If offering free trials, make sure the transition to a paid subscription is clearly communicated and automated.
-
**Status Handling: ** Be prepared to manage different subscription statuses like active, past_due, canceled, unpaid, etc. Implement logic to handle each status appropriately, such as notifying users of payment issues.
-
**Payment Failures: ** Implement retry logic for failed payments and notify users of issues, offering them a chance to update their payment method. Stripe also provides smart retries in its settings.
-
**Communication: ** Set up email notifications for subscription events like successful payments, upcoming renewals, or cancellations. Stripe also has emails setup for sending emails with customised templates.
-
**Stripe Webhooks: ** Use webhooks to listen for events like successful payments, subscription renewals, or failed payments. This helps keep your system synchronized with Stripe’s data.
-
**End-to-End Testing: ** Conduct thorough end-to-end testing of the entire subscription process, from sign-up to billing to cancellation, ensuring a smooth user experience.
Possible errors and troubleshooting them
**
- Incorrect API Key Usage:**
"Invalid API Key provided." Using the wrong API key (e.g., using a test key in a live environment or vice versa).
Double-check that you are using the correct API key for the environment (test or live). Ensure keys are securely stored and not hard-coded in the client-side code.
**
- Webhook Signature Verification Failures :**
"Invalid signature" error when verifying webhooks. The webhook signature is not properly validated or the signing secret is incorrect.
Ensure that you correctly retrieve and use the webhook signing secret from your Stripe dashboard. Implement the signature verification process as per Stripe’s documentation to secure webhook handling.
**
- Handling Failed Payments :**
Payment failures resulting in subscriptions being marked as past_due or unpaid.
Cause: Insufficient funds, expired card, or incorrect payment details.
Implement retry logic for failed payments, and send notifications to users to update their payment information. Use Stripe’s automatic dunning features to handle failed payments effectively. Also provide option to manually retry the payment using invoice id.
**
- Subscription Creation Errors :**
"Invalid request" or "Subscription could not be created."
Ensure that all required fields are correctly populated when creating a subscription. Validate that the customer and plan IDs exist and are correct. Confirm that the customer has a valid payment method on file.
**
- Subscription Status Not Updating Properly :**
Subscriptions remain in an incorrect status (e.g., still active after a failed payment). Webhooks not properly handled or missing logic to update subscription statuses.
Implement and monitor webhooks that notify your system of subscription events (e.g., payment failures, cancellations). Ensure your application updates the subscription status in response to these events.
**
- Missing or Misconfigured Webhooks :**
Your application is out of sync with Stripe (e.g., missing notifications for subscription renewals). Not setting up or incorrectly configuring webhooks.
Set up necessary webhooks in the Stripe dashboard and ensure your server is properly handling them. Regularly test webhook delivery and processing.
**
- Misconfigured Trial Periods :**
Customers are charged before the trial period ends or not charged at all. Incorrect setup of trial periods or misunderstanding of how trials work in Stripe.
Ensure that trial periods are correctly configured in the subscription plan. Test the transition from trial to paid subscription to confirm proper billing.
**
BONUS: Some addons in subscriptions
-
Setup payment intents: ** Subscriptions that include free trials, usage-based billing, invoices with coupons, or applied customer credit balances often result in non-payment invoices. This means you don’t immediately charge your customer when you create the subscription. ** Even though you don’t charge customers for the first invoice, authenticating and authorizing their card is often beneficial as it can increase the chance that the first non-zero payment completes successfully. Payments made this way are known as off-session payments. To manage these scenarios, Stripe created SetupIntents. Know more about it.
-
Trial Periods and how to implement them: ** You can start a customer’s subscription with a free trial period by providing a trial_end argument when creating the subscription. The trial_end parameter takes a timestamp indicating the exact moment the trial ends. When creating a subscription, you can alternatively use the trial_period_days parameter: an integer representing the number of days the trial lasts, from the current moment. Read more about it.
-
**Scheduled subscriptions: ** Use subscription schedules to automate changes to subscriptions over time. You can create subscriptions directly through a schedule or you can add a schedule to an existing subscription. Use the phases attribute to define the changes you want to make to the subscription. After a schedule completes all of its phases, it completes based on its end_behaviour. Read and understand more about it.
Conclusion
As per our promise, we have covered the subscription method integration of Stripe in ReactJS applications this week. We being a top reactjs development company will further on contribute to this series with the Stripe connect integration in ReactJS applications in the next part. Stay tuned for more technical blogs.