Files
bakery-ia/STRIPE_TESTING_GUIDE.md
2026-01-11 07:50:34 +01:00

22 KiB

Stripe Integration Testing Guide

Table of Contents

  1. Prerequisites
  2. Environment Setup
  3. Stripe Dashboard Configuration
  4. Test Card Numbers
  5. Testing Scenarios
  6. Webhook Testing
  7. Common Issues & Solutions
  8. Production Checklist

Prerequisites

Before you begin testing, ensure you have:

  • Stripe account created (sign up at stripe.com)
  • Node.js and Python environments set up
  • Frontend application running (React + Vite)
  • Backend API running (FastAPI)
  • Database configured and accessible
  • Redis instance running (for caching)

Environment Setup

Step 1: Access Stripe Test Mode

  1. Log in to your Stripe Dashboard: https://dashboard.stripe.com
  2. Click on your profile icon in the top right corner
  3. Ensure Test Mode is enabled (you'll see "TEST DATA" banner at the top)
  4. If not enabled, toggle to "Switch to test data"

Step 2: Retrieve API Keys

  1. Navigate to DevelopersAPI keys

  2. You'll see two types of keys:

    • Publishable key (starts with pk_test_...) - Used in frontend
    • Secret key (starts with sk_test_...) - Used in backend
  3. Click "Reveal test key" for the Secret key and copy both keys

Step 3: Configure Environment Variables

Frontend .env file:

# Create or update: /frontend/.env
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here

Backend .env file:

# Create or update: /services/tenant/.env
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here

Note: The webhook secret will be obtained in Step 4 when setting up webhooks.

Step 4: Install/Update Dependencies

Backend:

cd services/tenant
pip install -r requirements.txt
# This will install stripe==14.1.0

Frontend:

cd frontend
npm install
# Verifies @stripe/react-stripe-js and @stripe/stripe-js are installed

Stripe Dashboard Configuration

Step 1: Create Products and Prices

  1. In Stripe Dashboard (Test Mode), go to ProductsAdd product

  2. Create Starter Plan:

    • Product name: Starter Plan
    • Description: Basic subscription for small businesses
    • Pricing:
      • Price: $29.00
      • Billing period: Monthly
      • Currency: USD (or your preferred currency)
    • Click Save product
    • Copy the Price ID (starts with price_...) - you'll need this
  3. Create Professional Plan:

    • Product name: Professional Plan
    • Description: Advanced subscription for growing businesses
    • Pricing:
      • Price: $99.00
      • Billing period: Monthly
      • Currency: USD
    • Click Save product
    • Copy the Price ID
  4. Update your application configuration:

    • Store these Price IDs in your application settings
    • You'll use these when creating subscriptions

Step 2: Configure Webhooks

  1. Navigate to DevelopersWebhooks

  2. Click + Add endpoint

  3. For Local Development:

    • Endpoint URL: https://your-ngrok-url.ngrok.io/webhooks/stripe
    • (We'll set up ngrok later for local testing)
  4. Select events to listen to:

    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_succeeded
    • invoice.payment_failed
    • customer.subscription.trial_will_end
  5. Click Add endpoint

  6. Copy the Webhook Signing Secret:

    • Click on the newly created endpoint
    • Click Reveal next to "Signing secret"
    • Copy the secret (starts with whsec_...)
    • Add it to your backend .env file as STRIPE_WEBHOOK_SECRET

Test Card Numbers

Stripe provides test card numbers to simulate different scenarios. Never use real card details in test mode.

Basic Test Cards

Scenario Card Number CVC Expiry Date
Successful payment 4242 4242 4242 4242 Any 3 digits Any future date
Visa (debit) 4000 0566 5566 5556 Any 3 digits Any future date
Mastercard 5555 5555 5555 4444 Any 3 digits Any future date
American Express 3782 822463 10005 Any 4 digits Any future date

Authentication & Security

Scenario Card Number Notes
3D Secure authentication required 4000 0025 0000 3155 Triggers authentication modal
3D Secure 2 authentication 4000 0027 6000 3184 Requires SCA authentication

Declined Cards

Scenario Card Number Error Message
Generic decline 4000 0000 0000 0002 Card declined
Insufficient funds 4000 0000 0000 9995 Insufficient funds
Lost card 4000 0000 0000 9987 Lost card
Stolen card 4000 0000 0000 9979 Stolen card
Expired card 4000 0000 0000 0069 Expired card
Incorrect CVC 4000 0000 0000 0127 Incorrect CVC
Processing error 4000 0000 0000 0119 Processing error
Card declined (rate limit) 4000 0000 0000 9954 Exceeds velocity limit

Additional Scenarios

Scenario Card Number Notes
Charge succeeds, then fails 4000 0000 0000 0341 Attaches successfully but charge fails
Dispute (fraudulent) 4000 0000 0000 0259 Creates a fraudulent dispute
Dispute (warning) 4000 0000 0000 2685 Creates early fraud warning

Important Notes:

  • For expiry date: Use any future date (e.g., 12/30)
  • For CVC: Use any 3-digit number (e.g., 123) or 4-digit for Amex (e.g., 1234)
  • For postal code: Use any valid format (e.g., 12345)

Testing Scenarios

Scenario 1: Successful Registration with Payment

Objective: Test the complete registration flow with valid payment method.

Steps:

  1. Start your applications:

    # Terminal 1 - Backend
    cd services/tenant
    uvicorn app.main:app --reload --port 8000
    
    # Terminal 2 - Frontend
    cd frontend
    npm run dev
    
  2. Navigate to registration page:

    • Open browser: http://localhost:5173/register (or your frontend URL)
  3. Fill in user details:

    • Full Name: John Doe
    • Email: john.doe+test@example.com
    • Company: Test Company
    • Password: Create a test password
  4. Fill in payment details:

    • Card Number: 4242 4242 4242 4242
    • Expiry: 12/30
    • CVC: 123
    • Cardholder Name: John Doe
    • Email: john.doe+test@example.com
    • Address: 123 Test Street
    • City: Test City
    • State: CA
    • Postal Code: 12345
    • Country: US
  5. Select a plan:

    • Choose Starter Plan or Professional Plan
  6. Submit the form

Expected Results:

  • Payment method created successfully
  • User account created
  • Subscription created in Stripe
  • Database records created
  • User redirected to dashboard
  • No console errors

Verification:

  1. In Stripe Dashboard:

    • Go to Customers → Find "John Doe"
    • Go to Subscriptions → See active subscription
    • Status should be active
  2. In your database:

    SELECT * FROM subscriptions WHERE tenant_id = 'your-tenant-id';
    
    • Verify subscription record exists
    • Status should be active
    • Check stripe_customer_id is populated
  3. Check application logs:

    • Look for successful subscription creation messages
    • Verify no error logs

Scenario 2: Payment with 3D Secure Authentication

Objective: Test Strong Customer Authentication (SCA) flow.

Steps:

  1. Follow steps 1-3 from Scenario 1

  2. Fill in payment details with 3DS card:

    • Card Number: 4000 0025 0000 3155
    • Expiry: 12/30
    • CVC: 123
    • Fill remaining details as before
  3. Submit the form

  4. Complete authentication:

    • Stripe will display an authentication modal
    • Click "Complete" (in test mode, no real auth needed)

Expected Results:

  • Authentication modal appears
  • After clicking "Complete", payment succeeds
  • Subscription created successfully
  • User redirected to dashboard

Note: This simulates European and other markets requiring SCA.


Scenario 3: Declined Payment

Objective: Test error handling for declined cards.

Steps:

  1. Follow steps 1-3 from Scenario 1

  2. Use a declined test card:

    • Card Number: 4000 0000 0000 0002
    • Fill remaining details as before
  3. Submit the form

Expected Results:

  • Payment fails with error message
  • Error displayed to user: "Your card was declined"
  • No customer created in Stripe
  • No subscription created
  • No database records created
  • User remains on payment form
  • Can retry with different card

Verification:

  • Check Stripe Dashboard → Customers (should not see new customer)
  • Check application logs for error handling
  • Verify user-friendly error message displayed

Scenario 4: Insufficient Funds

Objective: Test specific decline reason handling.

Steps:

  1. Use card number: 4000 0000 0000 9995
  2. Follow same process as Scenario 3

Expected Results:

  • Payment fails
  • Error message: "Your card has insufficient funds"
  • Proper error handling and logging

Scenario 5: Subscription Cancellation

Objective: Test subscription cancellation flow.

Steps:

  1. Create an active subscription (use Scenario 1)

  2. Cancel the subscription:

    • Method 1: Through your application UI (if implemented)
    • Method 2: API call:
    curl -X POST http://localhost:8000/api/v1/subscriptions/cancel \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
      -d '{
        "tenant_id": "your-tenant-id",
        "reason": "Testing cancellation"
      }'
    

Expected Results:

  • Subscription status changes to pending_cancellation
  • cancellation_effective_date is set
  • User retains access until end of billing period
  • Response includes days remaining
  • Subscription cache invalidated

Verification:

  1. Check database:

    SELECT status, cancellation_effective_date, cancelled_at
    FROM subscriptions
    WHERE tenant_id = 'your-tenant-id';
    
  2. Verify API response:

    {
      "success": true,
      "message": "Subscription cancelled successfully...",
      "status": "pending_cancellation",
      "cancellation_effective_date": "2026-02-10T...",
      "days_remaining": 30
    }
    

Scenario 6: Subscription Reactivation

Objective: Test reactivating a cancelled subscription.

Steps:

  1. Cancel a subscription (use Scenario 5)

  2. Reactivate the subscription:

    curl -X POST http://localhost:8000/api/v1/subscriptions/reactivate \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
      -d '{
        "tenant_id": "your-tenant-id",
        "plan": "starter"
      }'
    

Expected Results:

  • Subscription status changes back to active
  • cancelled_at and cancellation_effective_date cleared
  • Next billing date set
  • Subscription cache invalidated

Scenario 7: Retrieve Invoices

Objective: Test invoice retrieval from Stripe.

Steps:

  1. Create subscription with successful payment (Scenario 1)

  2. Retrieve invoices:

    curl -X GET http://localhost:8000/api/v1/subscriptions/{tenant_id}/invoices \
      -H "Authorization: Bearer YOUR_AUTH_TOKEN"
    

Expected Results:

  • List of invoices returned
  • Each invoice contains:
    • id
    • date
    • amount
    • currency
    • status
    • invoice_pdf URL
    • hosted_invoice_url URL

Verification:

  • Click on hosted_invoice_url to view invoice in browser
  • Download PDF from invoice_pdf URL

Webhook Testing

Webhooks are critical for handling asynchronous events from Stripe. Test them thoroughly.

Step 1: Install Stripe CLI

macOS:

brew install stripe/stripe-cli/stripe

Windows: Download from: https://github.com/stripe/stripe-cli/releases

Linux:

wget https://github.com/stripe/stripe-cli/releases/latest/download/stripe_linux_x86_64.tar.gz
tar -xvf stripe_linux_x86_64.tar.gz
sudo mv stripe /usr/local/bin/

Step 2: Login to Stripe

stripe login

This opens a browser to authorize the CLI.

Step 3: Forward Webhooks to Local Server

stripe listen --forward-to localhost:8000/webhooks/stripe

Expected Output:

> Ready! Your webhook signing secret is whsec_abc123... (^C to quit)

Important: Copy this webhook signing secret and add it to your backend .env:

STRIPE_WEBHOOK_SECRET=whsec_abc123...

Step 4: Trigger Test Events

Open a new terminal and run:

# Test subscription created
stripe trigger customer.subscription.created

# Test payment succeeded
stripe trigger invoice.payment_succeeded

# Test payment failed
stripe trigger invoice.payment_failed

# Test subscription updated
stripe trigger customer.subscription.updated

# Test subscription deleted
stripe trigger customer.subscription.deleted

# Test trial ending
stripe trigger customer.subscription.trial_will_end

Step 5: Verify Webhook Processing

Check your application logs for:

  • "Processing Stripe webhook event"
  • Event type logged
  • Database updates (check subscription status)
  • No signature verification errors

Example log output:

INFO Processing Stripe webhook event event_type=customer.subscription.updated
INFO Subscription updated in database subscription_id=sub_123 tenant_id=tenant-id

Option 2: Using ngrok (For Public URL Testing)

Step 1: Install ngrok

Download from: https://ngrok.com/download

Step 2: Start ngrok

ngrok http 8000

Output:

Forwarding https://abc123.ngrok.io -> http://localhost:8000

Step 3: Update Stripe Webhook Endpoint

  1. Go to Stripe Dashboard → Developers → Webhooks
  2. Click on your endpoint
  3. Update URL to: https://abc123.ngrok.io/webhooks/stripe
  4. Save changes

Step 4: Test by Creating Real Events

Create a test subscription through your app, and webhooks will be sent to your ngrok URL.

Option 3: Testing Webhook Handlers Directly

You can also test webhook handlers by sending test payloads:

curl -X POST http://localhost:8000/webhooks/stripe \
  -H "Content-Type: application/json" \
  -H "stripe-signature: test-signature" \
  -d @webhook-test-payload.json

Note: This will fail signature verification unless you disable it temporarily for testing.


Common Issues & Solutions

Issue 1: "Stripe.js has not loaded correctly"

Symptoms:

  • Error when submitting payment form
  • Console error about Stripe not being loaded

Solutions:

  1. Check internet connection (Stripe.js loads from CDN)
  2. Verify VITE_STRIPE_PUBLISHABLE_KEY is set correctly
  3. Check browser console for loading errors
  4. Ensure no ad blockers blocking Stripe.js

Issue 2: "Invalid signature" on Webhook

Symptoms:

  • Webhook endpoint returns 400 error
  • Log shows "Invalid webhook signature"

Solutions:

  1. Verify STRIPE_WEBHOOK_SECRET matches Stripe Dashboard
  2. For Stripe CLI, use the secret from stripe listen output
  3. Ensure you're using the test mode secret, not live mode
  4. Check that you're not modifying the request body before verification

Issue 3: Payment Method Not Attaching

Symptoms:

  • PaymentMethod created but subscription fails
  • Error about payment method not found

Solutions:

  1. Verify you're passing paymentMethod.id to backend
  2. Check that payment method is being attached to customer
  3. Ensure customer_id exists before creating subscription
  4. Review backend logs for detailed error messages

Issue 4: Test Mode vs Live Mode Confusion

Symptoms:

  • Keys not working
  • Data not appearing in dashboard

Solutions:

  1. Always check the mode indicator in Stripe Dashboard
  2. Test keys start with pk_test_ and sk_test_
  3. Live keys start with pk_live_ and sk_live_
  4. Never mix test and live keys
  5. Use separate databases for test and live environments

Issue 5: CORS Errors

Symptoms:

  • Browser console shows CORS errors
  • Requests to backend failing

Solutions:

  1. Ensure FastAPI CORS middleware is configured:
    from fastapi.middleware.cors import CORSMiddleware
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["http://localhost:5173"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    

Issue 6: Webhook Events Not Processing

Symptoms:

  • Webhooks received but database not updating
  • Events logged but handlers not executing

Solutions:

  1. Check event type matches handler (case-sensitive)
  2. Verify database session is committed
  3. Check for exceptions in handler functions
  4. Review logs for specific error messages
  5. Ensure subscription exists in database before update

Issue 7: Card Element vs Payment Element Confusion

Symptoms:

  • TypeError when calling stripe.createPaymentMethod()
  • Elements not rendering correctly

Solutions:

  • Use PaymentElement (modern, recommended)
  • Call elements.submit() before creating payment method
  • Pass elements object to createPaymentMethod({ elements })
  • Our implementation now uses the correct PaymentElement API

Production Checklist

Before going live with Stripe payments:

Security

  • All API keys stored in environment variables (never in code)
  • Webhook signature verification enabled and working
  • HTTPS enabled on all endpoints
  • Rate limiting implemented on payment endpoints
  • Input validation on all payment-related forms
  • SQL injection prevention (using parameterized queries)
  • XSS protection enabled
  • CSRF tokens implemented where needed

Stripe Configuration

  • Live mode API keys obtained from Stripe Dashboard
  • Live mode webhook endpoints configured
  • Webhook signing secret updated for live mode
  • Products and prices created in live mode
  • Business information completed in Stripe Dashboard
  • Bank account added for payouts
  • Tax settings configured (if applicable)
  • Stripe account activated and verified

Application Configuration

  • Environment variables updated for production
  • Database migrations run on production database
  • Redis cache configured and accessible
  • Error monitoring/logging configured (e.g., Sentry)
  • Payment failure notifications set up
  • Trial ending notifications configured
  • Invoice email delivery tested

Testing

  • All test scenarios passed (see above)
  • Webhook handling verified for all event types
  • 3D Secure authentication tested
  • Subscription lifecycle tested (create, update, cancel, reactivate)
  • Error handling tested for all failure scenarios
  • Invoice retrieval tested
  • Load testing completed
  • Security audit performed

Monitoring

  • Stripe Dashboard monitoring set up
  • Application logs reviewed regularly
  • Webhook delivery monitoring configured
  • Payment success/failure metrics tracked
  • Alert thresholds configured
  • Failed payment retry logic implemented

Compliance

  • Terms of Service updated to mention subscriptions
  • Privacy Policy updated for payment data handling
  • GDPR compliance verified (if applicable)
  • PCI compliance requirements reviewed
  • Customer data retention policy defined
  • Refund policy documented

Documentation

  • API documentation updated
  • Internal team trained on Stripe integration
  • Customer support documentation created
  • Troubleshooting guide prepared
  • Subscription management procedures documented

Quick Reference Commands

Stripe CLI Commands

# Login to Stripe
stripe login

# Listen for webhooks (local development)
stripe listen --forward-to localhost:8000/webhooks/stripe

# Trigger test events
stripe trigger customer.subscription.created
stripe trigger invoice.payment_succeeded
stripe trigger invoice.payment_failed

# View recent events
stripe events list

# Get specific event
stripe events retrieve evt_abc123

# Test webhook endpoint
stripe webhooks test --endpoint-secret whsec_abc123

Testing Shortcuts

# Start backend (from project root)
cd services/tenant && uvicorn app.main:app --reload --port 8000

# Start frontend (from project root)
cd frontend && npm run dev

# Update backend dependencies
cd services/tenant && pip install -r requirements.txt

# Run database migrations (if using Alembic)
cd services/tenant && alembic upgrade head

Additional Resources


Support

If you encounter issues not covered in this guide:

  1. Check Stripe Dashboard Logs:

    • Developers → Logs
    • View detailed request/response information
  2. Review Application Logs:

    • Check backend logs for detailed error messages
    • Look for structured log output from structlog
  3. Test in Isolation:

    • Test frontend separately
    • Test backend API with cURL
    • Verify webhook handling with Stripe CLI
  4. Contact Stripe Support:


Last Updated: January 2026 Stripe Library Versions:

  • Frontend: @stripe/stripe-js@4.0.0, @stripe/react-stripe-js@3.0.0
  • Backend: stripe@14.1.0