Stripe Checkout is the fastest path from zero to a working payment flow. Today you wire up API keys, create a Product and Price in the dashboard, launch a hosted Checkout Session, and handle the success and cancel redirects — all in under 60 lines of server code.
By the end of this lesson you will have a working Stripe Checkout flow that accepts a test payment, redirects on success, and handles the cancel case cleanly.
Every SaaS product, marketplace, and digital store eventually needs to take money. Stripe is the dominant infrastructure layer for that job, and Checkout is its highest-leverage entry point. Instead of building your own payment form, handling card tokenization, and worrying about PCI compliance, you hand a user off to a Stripe-hosted page and receive a webhook when the money moves.
Stripe gives every account two key pairs: publishable and secret, each in test and live variants. The publishable key is safe to expose in client-side JavaScript. The secret key must never leave your server.
Retrieve both from the Stripe Dashboard → Developers → API Keys. Store the secret key in an environment variable — never hard-code it in source.
STRIPE_SECRET_KEY=sk_test_51... STRIPE_PUBLISHABLE_KEY=pk_test_51... STRIPE_WEBHOOK_SECRET=whsec_...
Install the SDK:
npm install stripe # Node.js pip install stripe # Python
sk_test_. Real card numbers are rejected; use Stripe's test card 4242 4242 4242 4242 with any future expiry and any CVC.A Checkout Session is a server-side object that represents a pending payment. You create it with the items, amounts, currency, and redirect URLs, then redirect the user to session.url. Stripe handles everything from there — card entry, 3D Secure, error messages.
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [{ price_data: { currency: 'usd', product_data: { name: 'Pro Plan' }, unit_amount: 4900, // cents }, quantity: 1, }], mode: 'payment', success_url: `\${YOUR_DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `\${YOUR_DOMAIN}/cancel`, }); res.redirect(303, session.url);
After payment, Stripe redirects back to your success_url with a session_id query parameter. Retrieve the session on your success page to confirm the payment status before granting access.
const sessionId = req.query.session_id; const session = await stripe.checkout.sessions.retrieve(sessionId); if (session.payment_status === 'paid') { // provision access, send receipt email, update DB }
Redirecting to /success only means the user finished the Checkout flow — not that payment succeeded. Always retrieve the session and check payment_status === 'paid'.
Fetch the session server-side by ID and inspect the payment status before granting any access or sending confirmation emails.
/success page. Always verify server-side.Before moving on, you should be able to answer these without looking:
unit_amount: 4900 represent in a Checkout Session for USD?mode: 'payment' and mode: 'subscription'?