Payments
NextSaaS uses Stripe as the payment engine, but it can be easily adapted to other payment providers. In this tutorial, we will focus on integrating Stripe with NextSaaS.
Setup Stripe
Register with Stripe
Sign Up and Create a Stripe Account (opens in a new tab)
Register Webhook Endpoints with Stripe
For the complete tutorial, refer to Register webhook endpoints with Stripe (opens in a new tab)
NextSaaS Webhook URL
console https://<your-website>/api/subscriptions/webhook
Ensure your webhook listens to checkout.session.completed
and invoice.payment_succeeded
Setup Products and Prices in Stripe
Create Products and Prices in Live or Test Mode
Refer to Create Products and Prices (opens in a new tab)
Create Products and Prices in Test Mode with Stripe CLI (Optional, only works in Test Mode)
Install Stripe CLI
For simplicity, we use Stripe CLI
to create Products and Prices.
Get started with the Stripe CLI (opens in a new tab)
Log in to your Stripe account
stripe login --project-name="{your_project_name_in_stripe}"
Create Product
If you plan to sell more products, run this command for each product. See the full params from Create a product (opens in a new tab)
stripe products create --name="{your_product_name}" --description="{your_product_description}"
Stripe will return the newly created product as below
{
"id": "{your_product_id}", # Note down this product id.
"object": "product",
"active": true,
...
}
Create Prices
You can create multiple prices per product, see the full params from Create a price (opens in a new tab)
# Creates a price for a one-time payment of $179 USD
stripe prices create \
-d product="{your_product_id}" \
-d unit_amount=17900 \
-d currency=usd
Stripe will return the newly created price as below
{
"id": "{your_price_id}", # Note down this price id.
"object": "price",
"active": true,
...
}
Congrats, you have completed the Stripe setup. Now you should have your product_id, price_id, unit_amount, and currency ready to set up NextSaaS.
Connect Stripe to NextSaaS
Setup Products and Prices in NextSaaS
NextSaaS is completely config-driven, and all you need to do is modify allSKUs
.
Properties product
and price
follow the same schema as the Stripe product/price object; just fill out the object info with the Stripe objects you created from the last step.
Additionally, if you have a recurring product, simply add one price object for monthly and another for yearly, and NextSaaS will handle everything else.
Here is an example configuration:
Configuration for one time product -
// one_time product -
const allSKUs: SKU[] = [
{
id: "Launch",
for: "Pay once, use for unlimited projects!",
name: "Launch",
features: [
"Next.js starter",
"Account management (Including transactional emails)",
"Social logins (Including email login)",
"Stripe payments (Recurring/One-time product)",
"Subscription management",
"Internationalization",
"SEO optimized",
"Admin UI",
"Themes",
],
type: "PLAN",
product: {
id: "prod_PTPECAFKpFHNUt", // Stripe Product ID
description: "Launch plan",
},
prices: [
{
id: "price_1OeShiFKiptxqV9W7YI4cwYx", // Stripe Price ID
discounted_unit_amount: 7900, // Discounted amount to display.
unit_amount: 17900,
currency: "usd",
type: "one_time",
},
],
},
// Add more SKUs as needed
];
export const DEFAULT_PRICE_TYPE: PriceType = "recurring";
Configuration for recurring product -
// recurring product -
const allSKUs: SKU[] = [
{
id: "Launch",
for: "Pay once, use for unlimited projects!",
name: "Launch plan",
features: [
"Next.js boilerplate",
"Animated components",
"Account management",
"Social logins (including email and passwordless login)",
"Stripe payments (recurring or one-time product)",
"Subscription management",
"Internationalization",
"Transactional emails",
"Docs/Wiki pages",
"Preview emails",
"SEO optimized",
"Admin UI",
"Themes",
],
type: "PLAN",
product: {
id: "prod_PTPECAFKpFHNUt", // Stripe Product ID
description: "Launch plan",
},
prices: [
{
id: "price_1OeShiFKiptxqV9W7YI4cwYx", // Stripe Price ID
discounted_unit_amount: 7900, // Discounted amount to display.
unit_amount: 17900,
currency: "usd",
recurring: {
interval: "month",
},
type: "recurring",
},
{
id: "price_1OeShiFKiptxqV9W7YI4cw12",
discounted_unit_amount: 7900,
unit_amount: 17900,
currency: "usd",
recurring: {
interval: "year",
},
type: "recurring",
},
],
},
{
id: "Boost",
for: "Pay once, use for unlimited projects, lifetime updates!",
name: "Boost plan",
features: [
"Everything in Launch Plan",
<span key={0}>
Lifetime updates (Last updated:{" "}
<span className="highlight-underline font-medium">2 DAYS AGO</span>)
</span>,
"Access to the GitHub repository",
"One year Premium Support via email",
"A full-featured build-in CMS",
],
type: "PLAN",
product: {
id: "prod_PTPPo4IQadSnO4",
description: "Boost plan",
},
prices: [
{
id: "price_1OeSiSFKiptxqV9WTusvU8Ke",
discounted_unit_amount: 9900,
unit_amount: 19900,
currency: "usd",
recurring: {
interval: "month",
},
type: "recurring",
},
{
id: "price_1OeSiSFKiptxqV9WTusvU812",
discounted_unit_amount: 9900,
unit_amount: 19900,
currency: "usd",
recurring: {
interval: "year",
},
type: "recurring",
},
],
},
];
export const DEFAULT_PRICE_TYPE: PriceType = "recurring";
Update Stripe Environment variables in NextSaaS
# Stripe Credentials
# The Stripe API secret key
STRIPE_API_SECRET_KEY="{stripe_api_secret_key}"
# The Stripe webhook signing key, typically starts with whsec_*
STRIPE_WEBHOOK_SIGNING_KEY="{stripe_webhook_signing_key}"
Subscription management
NextSaaS shadows subscription events from Stripe. Refer to src/app/api/subscriptions/webhook/route.ts
for the implementation.
By default, NextSaaS update subscription based on Stripe's invoice.payment_succeeded
and checkout.session.completed
events.
This will take care of new purchases and renewals but not cancellations and trials.
As your business grows you might want to handle more events from Stripe such as subscription_created
, subscription_updated
, subscription_deleted
, etc.
Refer to Subscription management (opens in a new tab)
One-time product
As mentioned previously, NextSaaS supports one-time products. Since one-time products don't have recurring billing, Stripe doesn't create a subscription for one time payment.
NextSaaS creates a fake subscription id with prefix sub_onetime_
for one-time products. This enables us to use the same subscription interface for one-time products.
By default, changing plan is disabled for one-time products.
We made all of these configurable in src/config/site.ts
You can change the one-time subscription prefix in src/config/site.ts
by setting ONE_TIME_SUBSCRIPTION_PREFIX
to a different string.
You can disable creating subscription for one-time products by setting CREATE_SUBSCRIPTION_FOR_ONETIME_PRODUCT
to false
.
You can also change the behavior of allowing changing plan for one-time products by setting ALLOW_CHANGE_PLAN_FOR_ONETIME_PRODUCT
in src/config/site.ts
.
Testing (Optional)
Refer to Payments Testing (opens in a new tab)
Wrap Up
That's it! You are ready to sell the product with Stripe and NextSaaS ❤️.