Configuring Stripe Webhook for Direct API Integration
New in v2.2! SaaSavant now uses Direct Stripe API integration instead of Firebase extensions. This means no Cloud Functions, no extensions, and full control over your payment flow!
Why Direct API Integration?
Before (v1.x):
- ❌ Required Firebase Stripe Extension
- ❌ Needed Cloud Functions
- ❌ Complex setup
- ❌ Limited control
Now (v2.2):
- ✅ Direct Stripe API calls
- ✅ Custom Next.js webhook handler
- ✅ No Firebase extensions needed
- ✅ Full TypeScript support
- ✅ Complete control over payment flow
Step 1: Add Stripe API Keys to .env.local
- Go to your Stripe Dashboard (opens in a new tab)
- Click Developers → API Keys
- Copy your Publishable key and Secret key
- Add them to your
.env.localfile:
# Stripe Configuration
NEXT_PUBLIC_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
STRIPE_SECRET_KEY=sk_test_your_secret_key_hereImportant: The STRIPE_SECRET_KEY should NOT have the NEXT_PUBLIC_ prefix. This keeps it server-side only for security.
Step 2: Configure Webhook for Development
Install Stripe CLI
macOS:
brew install stripe/stripe-cli/stripeWindows: Download from https://stripe.com/docs/stripe-cli (opens in a new tab)
Login to Stripe
stripe loginForward Webhooks to Local Server
stripe listen --forward-to localhost:3000/api/stripe/webhookThis will output a webhook signing secret (starts with whsec_). Copy it and add to .env.local:
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_hereKeep this terminal running while developing. It will show you webhook events in real-time!
Step 3: Configure Webhook for Production
Create Production Webhook Endpoint
- Go to Stripe Dashboard (opens in a new tab) → Developers → Webhooks
- Click Add endpoint
- Enter your production URL:
https://yourdomain.com/api/stripe/webhook
Select Events to Listen For
Select these essential events:
Required Events:
- ✅
checkout.session.completed - ✅
customer.subscription.created - ✅
customer.subscription.updated - ✅
customer.subscription.deleted - ✅
invoice.payment_succeeded - ✅
invoice.payment_failed
Optional Events:
customer.createdcustomer.updatedinvoice.upcoming
Copy Webhook Signing Secret
- After creating the endpoint, click on it
- Click Reveal under "Signing secret"
- Copy the secret (starts with
whsec_) - Add it to your production environment variables
Step 4: Test Your Webhook
Start Development Server
# Terminal 1: Start Next.js
npm run dev
# Terminal 2: Start Stripe webhook forwarding
stripe listen --forward-to localhost:3000/api/stripe/webhookTest Checkout Flow
- Go to
http://localhost:3000/Signupand create an account - Navigate to
http://localhost:3000/Dashboard/subscribe - Select a subscription plan
- Use Stripe test card:
4242 4242 4242 4242- Expiry: Any future date
- CVC: Any 3 digits
- ZIP: Any 5 digits
- Complete checkout
Verify Webhook Events
In Terminal 2 (where stripe listen is running), you should see:
✔ Received event: checkout.session.completed
✔ Received event: customer.subscription.created
✔ Received event: invoice.payment_succeededCheck Firestore
- Go to Firebase Console → Firestore Database
- Navigate to
customers/{userId}/subscriptions - You should see the subscription data
How It Works
SaaSavant uses a custom webhook handler at /api/stripe/webhook that:
- ✅ Verifies webhook signature for security
- ✅ Handles subscription events in real-time
- ✅ Updates Firestore with subscription data
- ✅ Manages customer records automatically
- ✅ Provides full TypeScript type safety
No Firebase extensions or Cloud Functions required!
Troubleshooting
Webhook Not Receiving Events
Development:
- ✅ Check
stripe listenis running - ✅ Verify webhook secret in
.env.local - ✅ Ensure dev server is running on port 3000
Production:
- ✅ Verify webhook endpoint URL is correct
- ✅ Check webhook secret matches production environment
- ✅ Review Stripe Dashboard → Webhooks for error logs
Subscription Not Updating
- Check webhook events in Stripe Dashboard
- Verify Firestore security rules allow writes
- Check server logs for errors
- Ensure customer document exists in Firestore
Test Cards
- Success:
4242 4242 4242 4242 - Decline:
4000 0000 0000 0002 - 3D Secure:
4000 0025 0000 3155
You're all set! Your Stripe integration is configured with direct API access and custom webhook handling.