Stripe integration: from setup to first payment
Getting paid is the hard-easy part.
Stripe is the standard for SaaS subscriptions. It's powerful and secure, but the setup has fine details. This guide walks through the essentials and the pitfalls.
- 6
- Parts, end to end
- 2
- Keys, one of them secret
- 1
- Webhook you cannot skip
- $0
- Until you charge someone
Part 1: create a Stripe account and get your keys
Go to stripe.com and sign up. You'll get two API keys: the publishable key (safe to expose in frontend code) and the secret key (never expose it; keep it in .env only).
Stripe also gives you a webhook signing secret (used to verify that webhook events are genuinely from Stripe).
Keep these in a .env.local file:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...Part 2: create your products and prices in Stripe
In the Stripe dashboard, create a product ("Pro Plan") and add a price ($99/month or $990/year).
You'll get a price ID (price_1A2b3c4d...). This ID goes into your database and your code.
Best practice: keep the price ID in your database alongside your plan definition. Don't hardcode Stripe IDs in your code. Always look them up from a safe source (the database or config).
Part 3: create a subscription session
When the user clicks "Subscribe," you create a Stripe Checkout session. This session is a URL you redirect the user to. They enter their payment details on Stripe (secure) and return to your site.
Server-side code (a Next.js API route) creates a session with the customer's email, the requested items (price ID), the mode (subscription), and success and cancel URLs.
Part 4: handle webhook events
When a user completes payment, Stripe sends a webhook event (checkout.session.completed). This event triggers your server to: (1) verify the subscription succeeded. (2) create a subscription record in your database. (3) activate the user's account.
Without webhooks, you might miss subscription starts (the user completes payment but your server crashes before saving). Webhooks are the reliable way.
Part 5: handle failure and retries
Users will fail to pay for reasons: an invalid card, an expired card, insufficient funds. Stripe retries automatically (3 times over 5 days). But you need to handle the payment-failed event.
Listen for invoice.payment_failed and email the user: "Your payment failed. Update your payment method here: [link]."
Always give users a way to update their payment method (the Stripe customer portal).
Part 6: test before launch
Use Stripe test mode (keys start with pk_test_ and sk_test_). In test mode, you can subscribe without a real credit card.
Test card numbers (from the Stripe docs):
- Success: 4242 4242 4242 4242 (any future expiry, any CVC)
- Declined: 4000 0000 0000 0002 (declined for insufficient funds)
- Requires authentication: 4000 0000 0000 3220 (requires 3D Secure)
Test the full flow: subscribe → payment success → database update → verify the subscription was created.
Common mistakes
Mistake one: exposing the secret key in frontend code. Never. Keep it in .env.local (server only).
Mistake two: not verifying webhook signatures. Always call stripe.webhooks.constructEvent() to verify.
Mistake three: relying only on client-side success confirmation. Always confirm via webhook.
Mistake four: not handling payment failure. The user's card is declined, no reminder is sent, the subscription goes dark.
Mistake five: hardcoding price IDs. Keep them in the database so you can change pricing without deploying.
The integration is not the hard part. The failure paths after the first charge are.
Start building your productMore guides
- Hire an engineer or work with a studio?The right choice depends on your stage, budget, and needs.7 min read
- SEO for a brand-new site: the first 90 daysA new domain has no authority. That changes the order of everything.10 min read
- The checkout audit: 12 places sales quietly leakMost conversion problems are not persuasion problems. Something is in the way.9 min read
- Where AI actually pays off in a small business (and where it doesn't)The question is not what AI can do. It is which job you own that it does cheaper than you.8 min read
- Your first 100 customers with no ad budgetThe first 100 customers are earned by hand. That is not a failure of strategy.9 min read
- Validate a micro-SaaS idea in 7 days (without building it)Most micro-SaaS ideas die from no demand, not bad code.8 min read
