Stripe Integration
Tiered subscription system with checkout, webhooks, and billing management.
Free
$0
Basic features
Pro
$20/mo
Advanced features
Ultra
$50/mo
Enterprise features
Setup
.env
# API KeysSTRIPE_SECRET_KEY="sk_test_..."NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."STRIPE_WEBHOOK_SECRET="whsec_..."# Price IDs (from Stripe Dashboard)STRIPE_PRICE_PRO_MONTHLY="price_..."STRIPE_PRICE_PRO_YEARLY="price_..."STRIPE_PRICE_ULTRA_MONTHLY="price_..."STRIPE_PRICE_ULTRA_YEARLY="price_..."
Create products and prices in Stripe Dashboard, then copy the price IDs.
Key Files
src/lib/subscriptions.tsPlan definitions, pricing, featuressrc/app/api/checkout/route.tsCreates checkout sessionssrc/app/api/webhooks/stripe/route.tsHandles Stripe eventssrc/server/actions/stripe.tsServer actions for billingCheckout Flow
1// Create checkout session2 const checkoutSession = await stripe.checkout.sessions.create({3 customer_email: session.user.email,4 line_items: [{ price: priceId, quantity: 1 }],5 mode: "subscription",6 success_url: `${origin}/account?success=true`,7 cancel_url: `${origin}/account?canceled=true`,8 metadata: { userId: session.user.id, plan },9});1011return NextResponse.json({ url: checkoutSession.url });
Webhooks
Configure webhook at https://yourdomain.com/api/webhooks/stripe
Required events:
- •
customer.subscription.created - •
customer.subscription.updated - •
customer.subscription.deleted
1// Verify webhook signature2 const event = stripe.webhooks.constructEvent(3 body,4 signature,5 env.STRIPE_WEBHOOK_SECRET6 );78 switch (event.type) {9 case "customer.subscription.created":10 await handleSubscriptionCreated(event.data.object);11 break;12 case "customer.subscription.updated":13 await handleSubscriptionUpdated(event.data.object);14 break;15 case "customer.subscription.deleted":16 await handleSubscriptionDeleted(event.data.object);17 break;18}
Customer Portal
1const portalSession = await stripe.billingPortal.sessions.create({2 customer: subscription.stripeCustomerId,3 return_url: `${process.env.NEXTAUTH_URL}/account`,4 });56return portalSession.url;
Allows users to update payment methods and download invoices.
Customizing Plans
Change Prices/Features
Edit the single source of truth:
1// src/lib/subscriptions.ts2export const SUBSCRIPTION_PLANS = {3 PRO_MONTHLY: {4 priceValue: 2000, // $20.00 in cents5 features: [6 "Unlimited rankings",7 "Advanced analytics",8 // Add/remove features9 ],10 },11};
Add New Tier
- 1. Add type to
prisma/schema.prismaenum - 2. Run
pnpm db:generate - 3. Add plan to
src/lib/subscriptions.ts - 4. Create product/prices in Stripe Dashboard
- 5. Add price IDs to .env and webhook mapping
Local Testing
Test Cards
4242424242424242— Success4000000000000002— Declined
Stripe CLI Setup
Install the Stripe CLI to test webhooks locally:
# macOSbrew install stripe/stripe-cli/stripe# Windows (scoop)scoop install stripe# Linux / WSLcurl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | sudo tee /usr/share/keyrings/stripe.gpgecho "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.listsudo apt update && sudo apt install stripe
Authenticate
Log in to your Stripe account (opens browser):
stripe login
Forward Webhooks
Run this in a separate terminal while developing:
stripe listen --forward-to localhost:3000/api/webhooks/stripe
Copy the webhook signing secret (whsec_...) and add it to your .env as STRIPE_WEBHOOK_SECRET.
Next: Email System
Transactional emails with Resend