Stripe Setup Guide
This guide covers configuring Stripe for the credit system.
Prerequisites
- Stripe account (https://stripe.com)
- Access to Stripe Dashboard
- Cloudflare Workers deployment
1. Get API Keys
From Stripe Dashboard
- Go to https://dashboard.stripe.com/apikeys
- Copy your keys:
- Publishable key:
pk_live_...(orpk_test_...for testing) - Secret key:
sk_live_...(orsk_test_...for testing)
- Publishable key:
Add to Cloudflare Workers
# Productionwrangler secret put STRIPE_SECRET_KEY# Paste: sk_live_...
wrangler secret put STRIPE_PUBLISHABLE_KEY# Paste: pk_live_...
# For local development, add to .dev.vars:STRIPE_SECRET_KEY=sk_test_...STRIPE_PUBLISHABLE_KEY=pk_test_...2. Configure Webhooks
Create Webhook Endpoint
-
Click Add endpoint
-
Enter your endpoint URL:
- Production:
https://api.yourdomain.com/api/stripe/webhook - Test:
https://your-worker.workers.dev/api/stripe/webhook
- Production:
-
Select events to listen to:
checkout.session.completedβ (required)checkout.session.expiredβpayment_intent.succeededβpayment_intent.payment_failedβcustomer.subscription.createdβ (for future subscriptions)customer.subscription.updatedβcustomer.subscription.deletedβinvoice.paidβinvoice.payment_failedβ
-
Click Add endpoint
-
Copy the Signing secret (
whsec_...)
Add Webhook Secret
wrangler secret put STRIPE_WEBHOOK_SECRET# Paste: whsec_...3. Create Products (Optional)
If you want to use Stripe-managed products instead of dynamic pricing:
Create Products in Dashboard
- Go to https://dashboard.stripe.com/products
- Click Add product
- Create each credit package:
| Product Name | Price | Metadata |
|---|---|---|
| Starter - 50 Credits | $9.99 one-time | credits: 50 |
| Standard - 200 Credits | $29.99 one-time | credits: 200 |
| Professional - 500 Credits | $59.99 one-time | credits: 500 |
| Enterprise - 2000 Credits | $199.99 one-time | credits: 2000 |
- Copy each Price ID (
price_...) - Update database:
UPDATE credit_packages SET stripe_price_id = 'price_...' WHERE name = 'Starter';UPDATE credit_packages SET stripe_price_id = 'price_...' WHERE name = 'Standard';-- etc.Note: The system works without pre-created Stripe products. It creates ad-hoc prices during checkout using the package data from the database.
4. Test the Integration
Test Mode
- Use test API keys (
sk_test_...,pk_test_...) - Use test card numbers:
- Success:
4242 4242 4242 4242 - Decline:
4000 0000 0000 0002 - Requires auth:
4000 0025 0000 3155
- Success:
Test Webhook Locally
# Install Stripe CLIbrew install stripe/stripe-cli/stripe
# Loginstripe login
# Forward webhooks to local serverstripe listen --forward-to localhost:8787/api/stripe/webhook
# Copy the webhook signing secret it provides# Add to .dev.vars as STRIPE_WEBHOOK_SECRETVerify Credit Addition
- Make a test purchase
- Check Stripe Dashboard β Payments
- Check webhook logs in Stripe Dashboard β Webhooks β Select endpoint β Logs
- Verify credits in app: /settings β Billing tab
- Check database:
SELECT * FROM credit_transactions WHERE type = 'purchase' ORDER BY created_at DESC LIMIT 5;5. Webhook Events Reference
checkout.session.completed
Fired when a customer completes checkout. This is the primary event for adding credits.
Handled by: /api/stripe/webhook
Action: Calls add_credits() with amount from session metadata.
checkout.session.expired
Fired when a checkout session expires (24 hours by default).
Action: Log for analytics, no credit action needed.
payment_intent.payment_failed
Fired when a payment fails.
Action: Could trigger email notification to user.
customer.subscription.* (Future)
For subscription-based plans:
created: Initialize subscription creditsupdated: Handle plan changesdeleted: Handle cancellation
invoice.paid / invoice.payment_failed (Future)
For recurring subscription payments.
6. Environment Variables Summary
| Variable | Required | Description |
|---|---|---|
STRIPE_SECRET_KEY | Yes | API secret key |
STRIPE_WEBHOOK_SECRET | Yes | Webhook signing secret |
STRIPE_PUBLISHABLE_KEY | No | For frontend (if needed) |
7. Security Checklist
- Using live keys only in production
- Webhook secret configured and verified
- HTTPS only for webhook endpoint
- Webhook signature verification enabled (automatic in our code)
- Test mode disabled in production
- API keys rotated periodically
- Webhook endpoint not publicly documented
8. Troubleshooting
Webhooks not firing
- Check endpoint URL is correct
- Verify endpoint is publicly accessible
- Check Stripe Dashboard β Webhooks β Logs for errors
- Ensure correct events are selected
Signature verification failing
- Verify
STRIPE_WEBHOOK_SECRETmatches the endpointβs signing secret - Check for trailing whitespace in secret
- Ensure raw request body is passed to verification (not parsed JSON)
Credits not added after payment
- Check webhook logs in Stripe Dashboard
- Look for errors in worker logs
- Verify
checkout.session.completedevent is enabled - Check metadata includes
user_idandcredits
Test payments not working
- Confirm using test API keys
- Check card number is a valid test card
- Verify webhook forwarding is active (for local testing)
9. Going Live Checklist
- Switch to live API keys
- Create new webhook endpoint with live URL
- Update
STRIPE_SECRET_KEYsecret - Update
STRIPE_WEBHOOK_SECRETsecret - Test with a real $1 charge (refund after)
- Verify webhook logs show successful delivery
- Confirm credits appear in user account