Imporve UI and token
This commit is contained in:
828
STRIPE_TESTING_GUIDE.md
Normal file
828
STRIPE_TESTING_GUIDE.md
Normal file
@@ -0,0 +1,828 @@
|
||||
# Stripe Integration Testing Guide
|
||||
|
||||
## Table of Contents
|
||||
1. [Prerequisites](#prerequisites)
|
||||
2. [Environment Setup](#environment-setup)
|
||||
3. [Stripe Dashboard Configuration](#stripe-dashboard-configuration)
|
||||
4. [Test Card Numbers](#test-card-numbers)
|
||||
5. [Testing Scenarios](#testing-scenarios)
|
||||
6. [Webhook Testing](#webhook-testing)
|
||||
7. [Common Issues & Solutions](#common-issues--solutions)
|
||||
8. [Production Checklist](#production-checklist)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin testing, ensure you have:
|
||||
|
||||
- ✅ Stripe account created (sign up at [stripe.com](https://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](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 **Developers** → **API 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:
|
||||
```bash
|
||||
# Create or update: /frontend/.env
|
||||
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
|
||||
```
|
||||
|
||||
#### Backend `.env` file:
|
||||
```bash
|
||||
# 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:
|
||||
```bash
|
||||
cd services/tenant
|
||||
pip install -r requirements.txt
|
||||
# This will install stripe==14.1.0
|
||||
```
|
||||
|
||||
#### Frontend:
|
||||
```bash
|
||||
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 **Products** → **Add 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 **Developers** → **Webhooks**
|
||||
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:**
|
||||
```bash
|
||||
# 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:**
|
||||
```sql
|
||||
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:
|
||||
```bash
|
||||
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:
|
||||
```sql
|
||||
SELECT status, cancellation_effective_date, cancelled_at
|
||||
FROM subscriptions
|
||||
WHERE tenant_id = 'your-tenant-id';
|
||||
```
|
||||
|
||||
2. Verify API response:
|
||||
```json
|
||||
{
|
||||
"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:**
|
||||
```bash
|
||||
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:**
|
||||
```bash
|
||||
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.
|
||||
|
||||
### Option 1: Using Stripe CLI (Recommended for Local Development)
|
||||
|
||||
#### Step 1: Install Stripe CLI
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
brew install stripe/stripe-cli/stripe
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
Download from: https://github.com/stripe/stripe-cli/releases
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
stripe login
|
||||
```
|
||||
|
||||
This opens a browser to authorize the CLI.
|
||||
|
||||
#### Step 3: Forward Webhooks to Local Server
|
||||
|
||||
```bash
|
||||
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`:
|
||||
```bash
|
||||
STRIPE_WEBHOOK_SECRET=whsec_abc123...
|
||||
```
|
||||
|
||||
#### Step 4: Trigger Test Events
|
||||
|
||||
Open a new terminal and run:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
```python
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
- **Stripe Documentation:** https://stripe.com/docs
|
||||
- **Stripe API Reference:** https://stripe.com/docs/api
|
||||
- **Stripe Testing Guide:** https://stripe.com/docs/testing
|
||||
- **Stripe Webhooks Guide:** https://stripe.com/docs/webhooks
|
||||
- **Stripe CLI Documentation:** https://stripe.com/docs/stripe-cli
|
||||
- **React Stripe.js Docs:** https://stripe.com/docs/stripe-js/react
|
||||
- **Stripe Support:** https://support.stripe.com
|
||||
|
||||
---
|
||||
|
||||
## 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:**
|
||||
- Live chat available in Stripe Dashboard
|
||||
- Email support: support@stripe.com
|
||||
- Community forum: https://stripe.com/community
|
||||
|
||||
---
|
||||
|
||||
**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`
|
||||
Reference in New Issue
Block a user