Home > Web Front-end > JS Tutorial > body text

Stripe Subscription Integration in Node.js [ltimate Guide]

Barbara Streisand
Release: 2024-11-22 15:57:37
Original
614 people have browsed it

Stripe Subscription Integration in Node.js [ltimate Guide]

Getting Stripe subscriptions working with backend services can be tricky and often leads to what developers call the dreaded “brain split” - managing both Stripe's logic and your own backend data in sync.

At Vratix, we’ve tackled this problem head-on while building our Open Source Stripe Subscriptions API Module. Here's how we approach Stripe subscription billing in Node.js to keep things simple, scalable, and developer-friendly.

Core Principle: Let Stripe Be the Source of Truth

The key is to shift as much of the logic to Stripe while keeping your database minimal. We only store:

  • Customer ID
  • Subscription ID
  • Plan

This way, we avoid:

  • Overcomplicated backend logic
  • Error-prone webhook implementations for syncing dashboard changes
  • Data redundancy

With this approach, you still have a fully functional subscription billing system while relying on Stripe as the single source of truth.

Features of Our Implementation

By the end of this guide, you’ll have a subscription-based app supporting:

  • User subscription plans
  • Checkout sessions
  • Subscription upsells
  • Available plan listing

Tech Stack

  • PostgreSQL
  • Node.js Express.js
  • TypeScript

Step 1: Database Design

We start by designing a clean, minimal database table:

CREATE TABLE user_subscriptions (  
    "id" SERIAL PRIMARY KEY,  
    "plan" VARCHAR NOT NULL,  
    "user_id" INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,  
    "customer_id" VARCHAR,  
    "subscription_id" VARCHAR NOT NULL,  
    "is_owner" BOOLEAN NOT NULL DEFAULT TRUE,  
    "created_at" TIMESTAMP NOT NULL DEFAULT NOW(),  
    UNIQUE (user_id, subscription_id)  
);
Copy after login
Copy after login

Key points:

  • user_id: References your internal user table
  • plan: Tracks the subscription plan
  • subscription_id: The Stripe subscription ID
  • is_owner: Flags the primary subscription holder

Step 2: Controllers

We use a factory function to keep the business logic modular and testable. Here's a snippet from our Stripe Subscription Controller:

async getSubscriptions() {  
  const stripePrices = await stripe.prices.list({  
    active: true,  
    type: "recurring",  
    expand: ["data.product"],  
  });  

  return stripePrices.data.map((price) => {  
    const product = price.product as Stripe.Product;  
    return {  
      plan: price.lookup_key || product.name.toLowerCase().replaceAll(" ", "_"),  
      name: product.name,  
      priceId: price.id,  
      interval: price.recurring!.interval,  
      price: { currency: price.currency, amount: price.unit_amount },  
    };  
  });  
}  
Copy after login

Key highlights:

  • Custom subscription keys: Derived from the product name or lookup_key for clean plan checks (user.plan === 'pro_plan').
  • Stripe-first approach: We fetch subscription data directly from Stripe, avoiding the “brain split.”

Step 3: Streamlined Stripe Checkout

Our createCheckout function sets up a subscription checkout session:

const checkout = await stripe.checkout.sessions.create({  
  line_items: [  
    {  
      price: priceId,  
      adjustable_quantity: { enabled: true },  
      quantity: seats || 1,  
    },  
  ],  
  mode: "subscription",  
  subscription_data: { metadata: { userId } },  
  success_url: CHECKOUT_SUCCESS_URL,  
  cancel_url: CHECKOUT_CANCEL_URL,  
});  

return { url: checkout.url! };  
Copy after login

Want to Skip All This?

We’ve packaged everything into a ready-to-go Open Source module. In less than 30 seconds, you can set up:

  • Stripe integration
  • Authentication
  • Database configuration
  • Prebuilt routes and SQL queries

Run this:

CREATE TABLE user_subscriptions (  
    "id" SERIAL PRIMARY KEY,  
    "plan" VARCHAR NOT NULL,  
    "user_id" INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,  
    "customer_id" VARCHAR,  
    "subscription_id" VARCHAR NOT NULL,  
    "is_owner" BOOLEAN NOT NULL DEFAULT TRUE,  
    "created_at" TIMESTAMP NOT NULL DEFAULT NOW(),  
    UNIQUE (user_id, subscription_id)  
);
Copy after login
Copy after login

Check out our Stripe Subscriptions Module Docs for more details.

The full code is available on our GitHub repo.

See a demo video how to do all of this with a working UI here.

I’d love to hear your thoughts - does this make building subscription APIs easier? Let us know what features you’d like to see next!

The above is the detailed content of Stripe Subscription Integration in Node.js [ltimate Guide]. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template