In this guide, we will explore how to integrate Stripe payments into a Node.js and Express application. From setting up the Stripe SDK to implementing subscription management, this blog will walk you through the key components.

In this guide, we will explore how to integrate Stripe payments into a Node.js and Express application. From setting up the Stripe SDK to implementing subscription management, this blog will walk you through the key components.
To begin, install the Stripe Node.js SDK:
npm install stripeNext, create a Stripe configuration file to initialize the Stripe SDK with your secret key.
const stripeKey = process.env.STRIPE_SECRET_KEY;
if (!stripeKey) {
throw new Error("STRIPE_SECRET_KEY environment variable is not set");
}
const stripe = new Stripe(stripeKey as string, {
apiVersion: "2024-06-20",
});STRIPE_SECRET_KEY is loaded from environment variables for security. Make sure to have the dotenv package installed in your project.To allow users to cancel their subscription, use the following function:
export const cancelSubscription = async (req: Request, res: Response) => {
const { userId } = (req as ExtendedRequest).user;
try {
const user = await UserModel.findById(userId);
if (!user) return res.status(404).json({ error: "User not found" });
if (!user.subscription || !user.subscription.customer_id) {
return res.status(400).json({ error: "No active subscription found" });
}
const subscriptions = await stripe.subscriptions.list({
customer: user.subscription.customer_id,
});
if (subscriptions.data.length === 0) {
return res.status(400).json({ error: "No active subscriptions found" });
}
const subscription = subscriptions.data[0];
await stripe.subscriptions.update(subscription.id, { cancel_at_period_end: true });
res.status(200).json({
message: "Subscription cancellation scheduled successfully",
subscription,
});
} catch (error) {
res.status(500).json({ error: error.message });
}
};To allow users to view their subscription details:
export const checkSubscription = async (req: Request, res: Response) => {
const { userId } = (req as ExtendedRequest).user;
try {
const user = await UserModel.findById(userId);
if (!user) return res.status(404).json({ error: "User not found" });
const subscriptions = await stripe.subscriptions.list({
customer: user.subscription.customer_id,
});
if (subscriptions.data.length === 0) {
return res.status(403).json({ error: "No active subscriptions" });
}
const subscription = subscriptions.data[0];
const productId = subscription.plan.product;
const product = await getProductDetailsFromProductId(productId);
const subscriptionData = {
productName: product.name,
price: subscription.plan.amount / 100,
currency: subscription.plan.currency,
cycle: subscription.plan.interval,
status: subscription.status,
};
res.status(200).json({ subscription: subscriptionData });
} catch (error) {
res.status(500).json({ error: error.message });
}
};To enable free trials:
export const startTrial = async (req: Request, res: Response) => {
const { planId } = req.body;
const { userId } = (req as ExtendedRequest).user;
if (!planId) return res.status(400).json({ error: "Missing required fields" });
try {
const prices = await stripe.prices.list({ product: planId });
if (prices.data.length === 0) return res.status(400).json({ error: "No prices found for this product" });
const priceId = prices.data[0].id;
const user = await UserModel.findById(userId);
if (!user || !user.email_verified) {
return res.status(400).json({ error: "Email verification is required to start a trial." });
}
const session = await stripe.checkout.sessions.create({
customer: user.subscription.customer_id,
payment_method_types: ["card"],
mode: "subscription",
line_items: [{ price: priceId, quantity: 1 }],
subscription_data: {
trial_period_days: 7,
},
success_url: `${process.env.CLIENT_BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.CLIENT_BASE_URL}/cancel`,
});
res.status(200).json({ url: session.url });
} catch (error) {
res.status(500).json({ error: error.message });
}
};For users to purchase a subscription:
export const subscribeUser = async (req: Request, res: Response) => {
const { planId } = req.body;
const { userId } = (req as ExtendedRequest).user;
if (!planId) return res.status(400).json({ error: "Subscription Plan is Required" });
try {
const user = await UserModel.findById(userId);
if (!user || !user.email_verified) {
return res.status(403).json({ error: "Email verification is required to start a subscription." });
}
const prices = await stripe.prices.list({ product: planId });
if (prices.data.length === 0) return res.status(400).json({ error: "No prices found for this product" });
const session = await stripe.checkout.sessions.create({
customer: user.subscription.customer_id,
payment_method_types: ["card"],
mode: "subscription",
line_items: [{ price: prices.data[0].id, quantity: 1 }],
success_url: `${process.env.CLIENT_BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.CLIENT_BASE_URL}/cancel`,
});
res.status(200).json({ url: session.url });
} catch (error) {
res.status(500).json({ error: error.message });
}
};With this setup, you can seamlessly integrate Stripe payments into your Node.js and Express application. Whether it's initiating trials, managing subscriptions, or processing payments, Stripe offers the flexibility to suit various use cases.
That's it for today. See ya 👋
New tutorials, book updates, and behind-the-scenes notes from the studio. No schedule, no spam.