Grow your SaaS organically with Programmatic SEO.
Try for free →This is the Part 3 in the series of guides on adding, managing, and keeping track of subscription payments using Stripe and Mongo for your SaaS app.
Subscription Payments are the bread and butter of a SaaS application; it's how you start generating revenue. In a well-implemented system, users need to first be able to change or cancel their plans, and second, undergo a trial phase to see if they would even like to pay for premium features. Typically, it's a hassle to set these up. In this set of guides, we will go through all the steps required to build a complete Subscription Payments system for your SaaS app.
In Part 3, we will:
Let's start!
One of the great things about Stripe is that it has Billing Portal features already built in. Things like, View Previous Invoices,*_**Change Billing Information,*___Allow Promotion Codes etc. can be turned on in the Billing Portal Settings page here.
Let's enable a few options.
Allow customers to cancel subscriptions
Allow customers to switch to a different pricing plan
Save
.Configuring Stripe Billing Portal Add our products so customers can see the other available plans when switching.
Add Products to Stripe Billing Portal
Add Terms & Services to Stripe Billing Portal That's it! Stripe just did the bulk of our work for us. All we have to do now is to trigger the Manage Billing screen. Let's do that next.
We can add a Manage Billing button in views/account.ejs
that shows up only when the customer is on an active plan. This will give them the option to update or cancel their plan.
Let's start by editing views/account.ejs
:
<% } else{ %> // ...
<p>
Not happy with your current plan? Cancel or Upgrade by clicking the button
below.
</p>
<button id="manage-billing-button" type="submit">Manage Billing</button>
<% }
When the button is clicked, we will send customer information along and trigger the Customer Billing Session on the /billing
endpoint. Edit the public/js/account.js
// ..
const manageBillingButton = $("#manage-billing-button");
manageBillingButton.click(function () {
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
customer: customer.billingID,
}),
};
fetch("/billing", requestOptions)
.then((response) => response.json())
.then((result) => window.location.replace(result.url))
.catch((error) => console.log("error", error));
});
Let's create a server-side session for Billing in app.js
app.post("/billing", async (req, res) => {
const { customer } = req.body;
const session = await Stripe.createBillingSession(customer);
res.json({ url: session.url });
});
We need to edit the src/connect/stripe.js
so we can add the createBillingSession
method.
const createBillingSession = async (customer) => {
const session = await Stripe.billingPortal.sessions.create({
customer,
return_url: "<https://localhost:4242>",
});
return session;
};
module.exports = {
// ...
createBillingSession,
};
We are ready to test it out. Login, buy a plan, and then try to change the plan.
Updating subscription plan on Manage Billing screen The plan should be correctly changed on the Stripe Dashboard. Notice, however, the information in the database is now outdated.
When the customer updates or cancels their purchased subscription plan via the **Manage Billing **screen, Stripe sends a customer.subscription.updated
event to our webhook.
app.post("/webhook", async (req, res) => {
// ..
case "customer.subscription.updated":
//started trial
const user = await UserService.getUserByBillingID(data.customer)
if (data.plan.id == productToPriceMap.BASIC) {
user.plan = "basic"
} else if (data.plan.id == productToPriceMap.PRO) {
user.plan = "pro"
}
const isOnTrial = data.status === "trialing"
if (isOnTrial) {
user.hasTrial = true
user.endDate = new Date(data.current_period_end * 1000)
} else if (data.status === "active") {
user.hasTrial = false
user.endDate = new Date(data.current_period_end * 1000)
}
if (data.canceled_at) {
// cancelled
user.plan = "none"
user.hasTrial = false
user.endDate = null
}
await user.save()
break
default:
}
// ..
});
Let's test out our application. Go through the login flow with your email address and purchase a plan. Then go back to the login page, log in again and try to cancel it via the
Manage Billing
button.
Canceling subscription plan on Manage Billing screen Perfect! Not only can a customer now buy a subscription plan, but they have the option to update/cancel it as well if they wish to do so.
In this guide we learned how to:
Our customers can now correctly buy/update/cancel subscription plans but they don't have access to exclusive content yet. Presumably, they are buying a plan to consume some sort of premium content. We will look into how we can set up special pages that a customer can access based on the type of plan they are on.
I'm building a new SaaS to automate content marketing for your SaaS
Tools for SaaS Devs