Skip to content

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

  1. Go to https://dashboard.stripe.com/apikeys
  2. Copy your keys:
    • Publishable key: pk_live_... (or pk_test_... for testing)
    • Secret key: sk_live_... (or sk_test_... for testing)

Add to Cloudflare Workers

Terminal window
# Production
wrangler 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

  1. Go to https://dashboard.stripe.com/webhooks

  2. Click Add endpoint

  3. Enter your endpoint URL:

    • Production: https://api.yourdomain.com/api/stripe/webhook
    • Test: https://your-worker.workers.dev/api/stripe/webhook
  4. 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 βœ“
  5. Click Add endpoint

  6. Copy the Signing secret (whsec_...)

Add Webhook Secret

Terminal window
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

  1. Go to https://dashboard.stripe.com/products
  2. Click Add product
  3. Create each credit package:
Product NamePriceMetadata
Starter - 50 Credits$9.99 one-timecredits: 50
Standard - 200 Credits$29.99 one-timecredits: 200
Professional - 500 Credits$59.99 one-timecredits: 500
Enterprise - 2000 Credits$199.99 one-timecredits: 2000
  1. Copy each Price ID (price_...)
  2. 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

  1. Use test API keys (sk_test_..., pk_test_...)
  2. Use test card numbers:
    • Success: 4242 4242 4242 4242
    • Decline: 4000 0000 0000 0002
    • Requires auth: 4000 0025 0000 3155

Test Webhook Locally

Terminal window
# Install Stripe CLI
brew install stripe/stripe-cli/stripe
# Login
stripe login
# Forward webhooks to local server
stripe listen --forward-to localhost:8787/api/stripe/webhook
# Copy the webhook signing secret it provides
# Add to .dev.vars as STRIPE_WEBHOOK_SECRET

Verify Credit Addition

  1. Make a test purchase
  2. Check Stripe Dashboard β†’ Payments
  3. Check webhook logs in Stripe Dashboard β†’ Webhooks β†’ Select endpoint β†’ Logs
  4. Verify credits in app: /settings β†’ Billing tab
  5. 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 credits
  • updated: Handle plan changes
  • deleted: Handle cancellation

invoice.paid / invoice.payment_failed (Future)

For recurring subscription payments.

6. Environment Variables Summary

VariableRequiredDescription
STRIPE_SECRET_KEYYesAPI secret key
STRIPE_WEBHOOK_SECRETYesWebhook signing secret
STRIPE_PUBLISHABLE_KEYNoFor 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

  1. Check endpoint URL is correct
  2. Verify endpoint is publicly accessible
  3. Check Stripe Dashboard β†’ Webhooks β†’ Logs for errors
  4. Ensure correct events are selected

Signature verification failing

  1. Verify STRIPE_WEBHOOK_SECRET matches the endpoint’s signing secret
  2. Check for trailing whitespace in secret
  3. Ensure raw request body is passed to verification (not parsed JSON)

Credits not added after payment

  1. Check webhook logs in Stripe Dashboard
  2. Look for errors in worker logs
  3. Verify checkout.session.completed event is enabled
  4. Check metadata includes user_id and credits

Test payments not working

  1. Confirm using test API keys
  2. Check card number is a valid test card
  3. 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_KEY secret
  • Update STRIPE_WEBHOOK_SECRET secret
  • Test with a real $1 charge (refund after)
  • Verify webhook logs show successful delivery
  • Confirm credits appear in user account