Skip to main content
RapidDev - Software Development Agency
stripe-guide

How to create a Checkout Session with Stripe

Create a Stripe Checkout Session by calling stripe.checkout.sessions.create() on your server with line_items, mode, and success/cancel URLs. Stripe hosts the entire payment page so you never handle card data directly. Use test mode with card 4242 4242 4242 4242 to verify before going live.

What you'll learn

  • How to install and configure the Stripe Node.js SDK
  • How to create a Checkout Session with line_items and redirect URLs
  • The difference between payment, subscription, and setup modes
  • How to test checkout with Stripe test cards
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner5 min read15 minutesStripe API v2024-12+, Node.js 18+, any frontend frameworkMarch 2026RapidDev Engineering Team
TL;DR

Create a Stripe Checkout Session by calling stripe.checkout.sessions.create() on your server with line_items, mode, and success/cancel URLs. Stripe hosts the entire payment page so you never handle card data directly. Use test mode with card 4242 4242 4242 4242 to verify before going live.

What Is Stripe Checkout and Why Use It?

Stripe Checkout is a prebuilt, hosted payment page that handles card collection, validation, 3D Secure, and compliance for you. Instead of building a custom payment form, you redirect users to a Stripe-hosted page. After payment, Stripe redirects them back to your success URL. This is the fastest way to accept payments — you only need a few lines of server-side code and zero frontend payment UI work.

Prerequisites

  • A Stripe account (free to create at dashboard.stripe.com)
  • Node.js 18 or newer installed
  • Your Stripe secret key (sk_test_...) from the Stripe Dashboard → Developers → API keys
  • A basic Express server or any Node.js HTTP framework

Step-by-step guide

1

Install the Stripe SDK

Install the official Stripe Node.js library. This SDK handles authentication, request signing, and API versioning for you.

typescript
1npm install stripe express

Expected result: stripe and express packages appear in your node_modules and package.json dependencies.

2

Initialize Stripe with your secret key

Import Stripe and initialize it with your secret key. NEVER use your secret key (sk_) on the frontend — it must stay on your server. Use environment variables to keep it out of source code.

typescript
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

Expected result: The stripe object is ready to make API calls.

3

Create the Checkout Session endpoint

Create a POST endpoint that builds a Checkout Session. Specify line_items with price_data (or an existing Price ID), the mode ('payment' for one-time), and success/cancel URLs. Stripe returns a session URL you redirect the customer to.

typescript
1const express = require('express');
2const app = express();
3
4app.post('/create-checkout-session', async (req, res) => {
5 try {
6 const session = await stripe.checkout.sessions.create({
7 mode: 'payment',
8 line_items: [
9 {
10 price_data: {
11 currency: 'usd',
12 product_data: {
13 name: 'Premium Widget',
14 description: 'A high-quality widget',
15 },
16 unit_amount: 2000, // $20.00 in cents
17 },
18 quantity: 1,
19 },
20 ],
21 success_url: 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}',
22 cancel_url: 'https://yoursite.com/cancel',
23 });
24
25 res.json({ url: session.url });
26 } catch (err) {
27 res.status(500).json({ error: err.message });
28 }
29});

Expected result: The endpoint returns a JSON object with a Stripe-hosted checkout URL.

4

Redirect the customer to Checkout

On your frontend, call your server endpoint and redirect the browser to the returned URL. This takes the customer to Stripe's hosted payment page.

typescript
1// Frontend JavaScript
2const response = await fetch('/create-checkout-session', {
3 method: 'POST',
4 headers: { 'Content-Type': 'application/json' },
5});
6const { url } = await response.json();
7window.location.href = url;

Expected result: The browser redirects to a Stripe-hosted checkout page showing the product, price, and payment form.

5

Test with a Stripe test card

Use Stripe's test card number to simulate a successful payment. No real money is charged in test mode.

typescript
1// Test card details:
2// Number: 4242 4242 4242 4242
3// Expiry: any future date (e.g., 12/34)
4// CVC: any 3 digits (e.g., 123)
5// ZIP: any 5 digits (e.g., 10001)

Expected result: After entering test card details and clicking Pay, Stripe redirects to your success_url with the session_id parameter appended.

Complete working example

server.js
1const express = require('express');
2const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
3
4const app = express();
5app.use(express.static('public'));
6app.use(express.json());
7
8// Create a Checkout Session
9app.post('/create-checkout-session', async (req, res) => {
10 try {
11 const session = await stripe.checkout.sessions.create({
12 mode: 'payment',
13 line_items: [
14 {
15 price_data: {
16 currency: 'usd',
17 product_data: {
18 name: 'Premium Widget',
19 description: 'A high-quality widget',
20 },
21 unit_amount: 2000, // $20.00 in cents
22 },
23 quantity: 1,
24 },
25 ],
26 success_url: `${req.headers.origin}/success?session_id={CHECKOUT_SESSION_ID}`,
27 cancel_url: `${req.headers.origin}/cancel`,
28 });
29
30 res.json({ url: session.url });
31 } catch (err) {
32 console.error('Checkout session error:', err.message);
33 res.status(500).json({ error: err.message });
34 }
35});
36
37// Verify session after payment (optional but recommended)
38app.get('/session-status', async (req, res) => {
39 try {
40 const session = await stripe.checkout.sessions.retrieve(req.query.session_id);
41 res.json({
42 status: session.payment_status,
43 customer_email: session.customer_details?.email,
44 });
45 } catch (err) {
46 res.status(500).json({ error: err.message });
47 }
48});
49
50const PORT = process.env.PORT || 3000;
51app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Common mistakes when creating a Checkout Session with Stripe

Why it's a problem: Using the secret key (sk_) on the frontend

How to avoid: Secret keys must only be used on your server. On the frontend, use the publishable key (pk_) for Stripe.js. Checkout Sessions are created server-side.

Why it's a problem: Passing amounts in dollars instead of cents

How to avoid: Stripe expects amounts in the smallest currency unit. For USD, pass 2000 for $20.00, not 20.

Why it's a problem: Hardcoding success_url without {CHECKOUT_SESSION_ID}

How to avoid: Include {CHECKOUT_SESSION_ID} in your success_url as a template variable so you can verify the session on your success page.

Why it's a problem: Not handling the cancel URL

How to avoid: Always provide a cancel_url. Users who click back or close the page land here. Show a friendly message, not a 404.

Best practices

  • Always use environment variables for your Stripe secret key — never commit it to source control
  • Use test mode (sk_test_) during development and test with card 4242 4242 4242 4242
  • Include {CHECKOUT_SESSION_ID} in your success_url to verify payment completion server-side
  • Set up a webhook for checkout.session.completed instead of relying solely on the success redirect
  • Specify amounts in the smallest currency unit (cents for USD, pence for GBP)
  • Use price_data for dynamic pricing or pre-created Price IDs from the Dashboard for fixed catalog items
  • Add metadata to your Checkout Session to link payments to your internal records

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Write a Node.js Express endpoint that creates a Stripe Checkout Session for a one-time $25 payment. Include line_items with price_data, success and cancel URLs, and return the session URL. Use the stripe npm package.

Stripe Prompt

Create a Stripe Checkout integration for my app. Add a POST /create-checkout-session endpoint that accepts a product name and price, creates a Stripe Checkout Session in payment mode, and returns the checkout URL. Use environment variable STRIPE_SECRET_KEY.

Frequently asked questions

Can I customize the look of Stripe Checkout?

Yes. In the Stripe Dashboard under Settings → Branding, you can set your logo, brand color, accent color, and icon. Checkout automatically uses these. For deeper customization, consider Stripe Elements instead.

Do I need HTTPS for Stripe Checkout?

Stripe Checkout itself is always HTTPS since it's hosted by Stripe. Your success and cancel URLs should use HTTPS in production. In local development, localhost works fine.

How do I know if the payment actually succeeded?

Do not rely solely on the success_url redirect — users can navigate there manually. Set up a webhook listener for the checkout.session.completed event to confirm payment server-side.

Can I accept multiple items in one Checkout Session?

Yes. Add multiple objects to the line_items array. Each can have its own price_data, quantity, and product details. Stripe displays all items on the checkout page.

What if I need help integrating Stripe into a larger application?

For complex payment flows — multi-vendor marketplaces, usage-based billing, or enterprise SaaS — the RapidDev team can help you architect and implement a production-ready Stripe integration.

Does Stripe Checkout support Apple Pay and Google Pay?

Yes. Stripe Checkout automatically enables Apple Pay, Google Pay, and Link (Stripe's one-click checkout) when available. No extra configuration is needed.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.