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
Install the Stripe SDK
Install the Stripe SDK
Install the official Stripe Node.js library. This SDK handles authentication, request signing, and API versioning for you.
1npm install stripe expressExpected result: stripe and express packages appear in your node_modules and package.json dependencies.
Initialize Stripe with your secret key
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.
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);Expected result: The stripe object is ready to make API calls.
Create the Checkout Session endpoint
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.
1const express = require('express');2const app = express();34app.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 cents17 },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 });2425 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.
Redirect the customer to Checkout
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.
1// Frontend JavaScript2const 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.
Test with a Stripe test card
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.
1// Test card details:2// Number: 4242 4242 4242 42423// 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
1const express = require('express');2const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);34const app = express();5app.use(express.static('public'));6app.use(express.json());78// Create a Checkout Session9app.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 cents22 },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 });2930 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});3637// 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});4950const 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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation