docs
One Time or Recurring Payment

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 -

src/config.site.ts
// 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 -

src/config/site.ts
// 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";

Price Card for one_time product

Price Card for recurring product

Update Stripe Environment variables in NextSaaS

.env
# 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 ❤️.