summaryrefslogtreecommitdiff
path: root/Biz/PodcastItLater/STRIPE_TESTING.md
blob: 00910ecd5ed4917bb722cc9c8517f483d1129128 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# Stripe Testing Guide for PodcastItLater

This guide covers end-to-end Stripe billing integration testing.

## Prerequisites

1. Stripe account (sign up at stripe.com)
2. Stripe CLI installed (`brew install stripe/stripe-cli/stripe` or download from stripe.com/docs/stripe-cli)

## Setup Steps

### 1. Get Stripe Test Mode API Keys

1. Go to https://dashboard.stripe.com/test/apikeys
2. Copy your test mode keys:
   - **Publishable key** (starts with `pk_test_`)
   - **Secret key** (starts with `sk_test_`)

### 2. Create Products and Prices in Stripe Dashboard

#### Personal Plan ($9/month)
1. Go to https://dashboard.stripe.com/test/products
2. Click "+ Add product"
3. Fill in:
   - Name: `PodcastItLater Personal`
   - Description: `50 articles per month`
   - Pricing model: `Standard pricing`
   - Price: `$9.00`
   - Billing period: `Monthly`
   - Payment type: `Recurring`
4. Click "Save product"
5. **Copy the Price ID** (starts with `price_`) - you'll need this for `STRIPE_PRICE_ID_PERSONAL`

#### Pro Plan ($29/month)
1. Repeat above steps with:
   - Name: `PodcastItLater Pro`
   - Description: `Unlimited articles`
   - Price: `$29.00`
   - Billing period: `Monthly`
2. **Copy the Price ID** - you'll need this for `STRIPE_PRICE_ID_PRO`

### 3. Configure Environment Variables

Create or update your `.envrc.local` file:

```bash
# Stripe Test Mode Keys
export STRIPE_SECRET_KEY="sk_test_YOUR_SECRET_KEY_HERE"

# Price IDs from Stripe dashboard
export STRIPE_PRICE_ID_PERSONAL="price_YOUR_PERSONAL_PRICE_ID"
export STRIPE_PRICE_ID_PRO="price_YOUR_PRO_PRICE_ID"

# Other required vars (if not already set)
export BASE_URL="http://localhost:8000"
export SESSION_SECRET="dev-secret-key-for-testing"
export SECRET_KEY="dev-secret-key-for-magic-links"
export AREA="Test"  # Important for test mode behavior
```

Reload environment:
```bash
direnv allow
```

### 4. Set Up Webhook Testing

#### Option A: Stripe CLI (Recommended for local testing)

1. Login to Stripe CLI:
   ```bash
   stripe login
   ```

2. Start webhook forwarding:
   ```bash
   stripe listen --forward-to http://localhost:8000/stripe/webhook
   ```

3. **Copy the webhook signing secret** shown in the output (starts with `whsec_`)

4. Add to `.envrc.local`:
   ```bash
   export STRIPE_WEBHOOK_SECRET="whsec_YOUR_WEBHOOK_SECRET"
   ```

5. Reload environment:
   ```bash
   direnv allow
   ```

#### Option B: Deploy and Use Stripe Dashboard Webhooks

1. Deploy to production or staging environment
2. Go to https://dashboard.stripe.com/test/webhooks
3. Click "+ Add endpoint"
4. Enter your webhook URL: `https://your-domain.com/stripe/webhook`
5. Select events to listen for:
   - `checkout.session.completed`
   - `customer.subscription.created`
   - `customer.subscription.updated`
   - `customer.subscription.deleted`
   - `invoice.payment_failed`
6. Copy the signing secret and add to your environment

### 5. Initialize Database

```bash
# Make sure DATA_DIR is set (defaults to _/var/podcastitlater/)
export DATA_DIR="_/var/podcastitlater/"
mkdir -p $DATA_DIR

# Start the web server to initialize database
bild --time 0 Biz/PodcastItLater/Web.py
python Biz/PodcastItLater/Web.py
```

## Testing the Complete Flow

### Test 1: User Registration and Free Tier

1. Start the web server:
   ```bash
   python Biz/PodcastItLater/Web.py
   ```

2. Open http://localhost:8000 in your browser

3. Login with `demo@example.com` (auto-approved in test mode)

4. Verify:
   - ✓ Logged in as demo@example.com
   - ✓ Plan shows "Free"
   - ✓ Billing button visible

5. Click "Billing" button

6. Verify billing page shows:
   - ✓ Current Plan: Free
   - ✓ Usage: 0 / 10 articles
   - ✓ Period dates (current month)
   - ✓ Three pricing cards (Free, Personal, Pro)
   - ✓ "Upgrade" buttons on Personal and Pro plans

### Test 2: Stripe Checkout Flow (Personal Plan)

1. On billing page, click "Upgrade" button under Personal plan

2. Verify redirected to Stripe Checkout page:
   - ✓ Shows "PodcastItLater Personal"
   - ✓ Shows $9.00/month
   - ✓ Can enter test card details

3. Use Stripe test card:
   - Card number: `4242 4242 4242 4242`
   - Expiry: Any future date (e.g., `12/34`)
   - CVC: Any 3 digits (e.g., `123`)
   - Email: Use same email as logged in user

4. Complete checkout

5. Verify:
   - ✓ Redirected back to `/billing?status=success`
   - ✓ Success message shown
   - ✓ Plan updated to "Personal" (may take a few moments)
   - ✓ Usage shows "0 / 50 articles"
   - ✓ "Manage Subscription" button appears
   - ✓ "Current Plan" badge on Personal plan

### Test 3: Webhook Events

Check your terminal running `stripe listen` to verify webhook events received:

```
✓ checkout.session.completed [evt_xxx]
✓ customer.subscription.created [evt_xxx]
✓ customer.subscription.updated [evt_xxx]
```

Check database to verify subscription data:

```bash
sqlite3 _/var/podcastitlater/podcast.db
```

```sql
-- Check user subscription details
SELECT id, email, plan_tier, subscription_status, 
       stripe_customer_id, stripe_subscription_id 
FROM users WHERE email = 'demo@example.com';

-- Should show:
-- plan_tier: personal
-- subscription_status: active
-- stripe_customer_id: cus_xxx
-- stripe_subscription_id: sub_xxx
```

### Test 4: Billing Portal (Manage Subscription)

1. On billing page (now showing Personal plan), click "Manage Subscription"

2. Verify redirected to Stripe Billing Portal:
   - ✓ Shows current subscription: PodcastItLater Personal
   - ✓ Can update payment method
   - ✓ Can cancel subscription
   - ✓ Can view invoices

3. Test cancellation:
   - Click "Cancel plan"
   - Select cancellation option (e.g., "Cancel at end of period")
   - Confirm

4. Return to billing page

5. Verify:
   - ✓ Subscription shows as active but set to cancel
   - ✓ Still can use service until period ends

### Test 5: Usage Limits Enforcement

1. Login as a free user (or create new user)

2. Try to submit more than 10 articles in the current month

3. On the 11th submission, verify:
   - ✓ Error message shown: "You've reached your limit of 10 articles per period. Upgrade to continue."
   - ✓ Submit button disabled or shows error
   - ✓ Upgrade prompt shown

4. Upgrade to Personal or Pro plan

5. Verify:
   - ✓ Can submit articles again
   - ✓ New usage limit applies

### Test 6: Subscription Upgrade Flow

1. Start with Personal plan

2. Go to billing page

3. Click "Upgrade" on Pro plan

4. Complete checkout with test card

5. Verify:
   - ✓ Plan upgraded to Pro
   - ✓ Usage shows "0 / ∞ articles"
   - ✓ Billing reflects pro-rated charges

### Test 7: Payment Failure Handling

1. Use Stripe test card that triggers payment failure:
   - Card number: `4000 0000 0000 0341` (charge fails)

2. After first payment succeeds, wait for next billing cycle or trigger failure manually

3. Verify:
   - ✓ Subscription status updates to "past_due"
   - ✓ User still has access during grace period
   - ✓ Webhook event processed: `invoice.payment_failed`

### Test 8: Subscription Cancellation

1. Cancel subscription from Billing Portal

2. Wait for end of billing period OR manually expire in Stripe dashboard

3. Verify:
   - ✓ Webhook event: `customer.subscription.deleted`
   - ✓ User downgraded to free tier
   - ✓ Usage limit reset to 10 articles/month
   - ✓ Stripe subscription data cleared

## Common Test Cards

| Card Number | Scenario |
|-------------|----------|
| 4242 4242 4242 4242 | Successful payment |
| 4000 0000 0000 0341 | Charge fails |
| 4000 0000 0000 9995 | Card declined |
| 4000 0025 0000 3155 | Requires authentication (3D Secure) |

Full list: https://stripe.com/docs/testing#cards

## Troubleshooting

### Webhooks not received

- Check Stripe CLI is running: `stripe listen --forward-to ...`
- Verify webhook secret matches in environment
- Check web server logs for webhook processing errors
- Verify web server is accessible at the forwarding URL

### Database not updating

- Check web server logs for errors
- Verify webhook events are being processed (check stripe_events table)
- Check database schema is up to date (run Web.py to trigger migrations)

### Checkout session not creating

- Verify STRIPE_SECRET_KEY is set and valid
- Check STRIPE_PRICE_ID_PERSONAL and STRIPE_PRICE_ID_PRO are correct
- Look for errors in web server logs
- Verify price IDs exist in Stripe dashboard

### User not upgrading after checkout

- Verify webhooks are being received and processed
- Check that customer email in checkout matches user email in database
- Look for errors in webhook processing logs
- Check stripe_events table for duplicate processing

## Production Deployment

Before going to production:

1. Switch to live mode keys (remove `_test_` from keys)
2. Create products/prices in live mode Stripe dashboard
3. Set up live webhook endpoint in Stripe dashboard
4. Update STRIPE_WEBHOOK_SECRET to live mode secret
5. Set AREA=Live in production environment
6. Test with real payment methods (or use test mode in production at first)
7. Monitor webhook events and logs closely

## Monitoring

### Check Webhook Events in Database

```sql
SELECT * FROM stripe_events 
ORDER BY created_at DESC 
LIMIT 10;
```

### Check Subscription States

```sql
SELECT email, plan_tier, subscription_status, 
       current_period_start, current_period_end
FROM users 
WHERE plan_tier != 'free';
```

### Check Usage Stats

```sql
SELECT u.email, u.plan_tier, COUNT(e.id) as articles_this_month
FROM users u
LEFT JOIN episodes e ON e.user_id = u.id 
  AND e.created_at >= date('now', 'start of month')
GROUP BY u.id, u.email, u.plan_tier;
```

## Next Steps

After successful testing:

1. Mark task t-1pIV0ZF as done
2. Update AGENTS.md with Stripe setup documentation
3. Create production deployment checklist
4. Set up error monitoring (Sentry)
5. Configure email notifications for payment failures
6. Add analytics for conversion tracking