Billing is optional. If Stripe is not configured, payment features will be disabled.
Overview
The Stripe integration supports:- One-time payments (Stripe Checkout in
paymentmode) - Recurring subscriptions (Stripe Checkout in
subscriptionmode) - Customer portal for subscription management
- Webhook handling for payment events
- Tax ID collection
- Promotional codes
Environment Variables
Add Stripe credentials topackages/landing/.env.local:
string
required
Stripe secret key for API authentication.Test mode:
sk_test_...Live mode: sk_live_...Get from: Stripe Dashboard → Developers → API keysstring
required
Webhook signing secret for verifying Stripe webhook events.Format:
whsec_...Get from: Stripe Dashboard → Developers → WebhooksExample Configuration
packages/landing/.env.local
Stripe Setup
1
Create Stripe Account
Sign up at stripe.com if you don’t have an account.
2
Get API Keys
- Navigate to Developers → API keys
- Copy the Secret key (starts with
sk_test_orsk_live_) - Add to
.env.localasSTRIPE_SECRET_KEY
3
Create Products & Prices
- Navigate to Products
- Click “Add product”
- Set name, description, and pricing
- Copy the Price ID (starts with
price_)
4
Configure Webhooks
- Navigate to Developers → Webhooks
- Click “Add endpoint”
- Set endpoint URL:
- Local: Use Stripe CLI
- Production:
https://yourdomain.com/api/stripe/webhook
- Select events to listen for
- Copy the Signing secret (starts with
whsec_) - Add to
.env.localasSTRIPE_WEBHOOK_SECRET
API Implementation
The Stripe integration is implemented inpackages/landing/libs/stripe.ts and used by Next.js API routes.
Stripe Client
packages/landing/libs/stripe.ts
Checkout Session
Create a checkout session for payment or subscription:packages/landing/libs/stripe.ts
Customer Portal
Create a customer portal session for subscription management:packages/landing/libs/stripe.ts
API Routes
The landing package includes API routes for Stripe operations.Create Checkout Route
Endpoint:POST /api/stripe/create-checkout
Location: packages/landing/app/api/stripe/create-checkout/route.ts
Request body:
packages/landing/app/api/stripe/create-checkout/route.ts
Create Portal Route
Endpoint:POST /api/stripe/create-portal
Location: packages/landing/app/api/stripe/create-portal/route.ts
Request body:
The portal route currently returns an error if no
customerId is found. You’ll need to implement customer lookup from your database.packages/landing/app/api/stripe/create-portal/route.ts
Customer Data Storage
Recommended Schema
Add a table to store Stripe customer data:Update Customer Portal
Modify the portal route to look up the customer ID:Webhook Handling
Webhooks notify your application of Stripe events (payment success, subscription canceled, etc.).Webhook Route
Createpackages/landing/app/api/stripe/webhook/route.ts:
Important Webhook Events
Local Testing with Stripe CLI
Test webhooks locally using the Stripe CLI.1
Install Stripe CLI
2
Authenticate
3
Forward Webhooks
whsec_) and add to .env.local:4
Trigger Test Events
Testing Payments
Test Cards
Stripe provides test cards for different scenarios:
Use any future expiry date and any 3-digit CVC.
Test Checkout Flow
- One-time Payment
- Subscription
Production Checklist
1
Switch to Live Mode
- Get live API keys from Stripe Dashboard
- Update
STRIPE_SECRET_KEYwithsk_live_... - Update webhook secret with live endpoint secret
2
Configure Webhook Endpoint
- Add production URL to Stripe Dashboard
- Select events to listen for
- Test webhook delivery
3
Test Payment Flow
- Use real credit cards in test mode first
- Verify webhooks are received
- Check customer data is saved
4
Security Review
- Verify webhook signature validation
- Ensure secrets are not committed
- Enable HTTPS only
- Review Stripe security best practices
Troubleshooting
Webhook signature verification failed
Webhook signature verification failed
- Verify
STRIPE_WEBHOOK_SECRETmatches the endpoint secret - For local testing, use Stripe CLI’s secret (starts with
whsec_) - Check that you’re passing the raw request body to
constructEvent
Customer portal returns 'No billing account'
Customer portal returns 'No billing account'
Implement customer ID storage:
- Create
stripe_customerstable - Save customer ID on checkout completion
- Update portal route to look up customer ID
Checkout session creation fails
Checkout session creation fails
- Verify
STRIPE_SECRET_KEYis set correctly - Check that Price ID exists in Stripe Dashboard
- Ensure
modematches price type (paymentfor one-time,subscriptionfor recurring)
Next Steps
Environment Variables
Configure all required Stripe variables
Database Setup
Add customer table for Stripe IDs