@xenterprises/fastify-xstripe 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/TESTING.md DELETED
@@ -1,357 +0,0 @@
1
- # Testing Guide for xStripe
2
-
3
- This guide shows how to test your Stripe webhook handlers locally and in production.
4
-
5
- ## Local Testing with Stripe CLI
6
-
7
- ### 1. Install Stripe CLI
8
-
9
- **macOS:**
10
- ```bash
11
- brew install stripe/stripe-cli/stripe
12
- ```
13
-
14
- **Other platforms:**
15
- Download from https://stripe.com/docs/stripe-cli
16
-
17
- ### 2. Login to Stripe
18
-
19
- ```bash
20
- stripe login
21
- ```
22
-
23
- This will open your browser for authentication.
24
-
25
- ### 3. Forward Webhooks to Local Server
26
-
27
- Start your local server first:
28
- ```bash
29
- npm run dev
30
- ```
31
-
32
- Then forward webhooks:
33
- ```bash
34
- stripe listen --forward-to localhost:3000/stripe/webhook
35
- ```
36
-
37
- This will output a webhook signing secret. Copy it to your `.env` file:
38
- ```
39
- STRIPE_WEBHOOK_SECRET=whsec_...
40
- ```
41
-
42
- ### 4. Trigger Test Events
43
-
44
- In a new terminal, trigger specific events:
45
-
46
- ```bash
47
- # Test subscription creation
48
- stripe trigger customer.subscription.created
49
-
50
- # Test payment failure
51
- stripe trigger invoice.payment_failed
52
-
53
- # Test subscription cancellation
54
- stripe trigger customer.subscription.deleted
55
-
56
- # Test trial ending
57
- stripe trigger customer.subscription.trial_will_end
58
- ```
59
-
60
- ## Testing Specific Scenarios
61
-
62
- ### Subscription Lifecycle
63
-
64
- ```bash
65
- # 1. Create subscription
66
- stripe trigger customer.subscription.created
67
-
68
- # 2. Update subscription (plan change)
69
- stripe trigger customer.subscription.updated
70
-
71
- # 3. Trial ending soon
72
- stripe trigger customer.subscription.trial_will_end
73
-
74
- # 4. Cancel subscription
75
- stripe trigger customer.subscription.deleted
76
- ```
77
-
78
- ### Payment Scenarios
79
-
80
- ```bash
81
- # Successful payment
82
- stripe trigger invoice.paid
83
-
84
- # Failed payment
85
- stripe trigger invoice.payment_failed
86
-
87
- # Upcoming payment reminder
88
- stripe trigger invoice.upcoming
89
- ```
90
-
91
- ### Customer Events
92
-
93
- ```bash
94
- # New customer
95
- stripe trigger customer.created
96
-
97
- # Customer updated
98
- stripe trigger customer.updated
99
-
100
- # Payment method attached
101
- stripe trigger payment_method.attached
102
- ```
103
-
104
- ## Testing Handlers Directly
105
-
106
- Since handlers are pure functions, you can test them in isolation:
107
-
108
- ### Example Test File
109
-
110
- ```javascript
111
- // test/handlers.test.js
112
- import { test } from 'node:test';
113
- import assert from 'node:assert';
114
-
115
- test('subscription created handler updates database', async () => {
116
- const mockEvent = {
117
- type: 'customer.subscription.created',
118
- data: {
119
- object: {
120
- id: 'sub_123',
121
- customer: 'cus_123',
122
- status: 'active',
123
- items: {
124
- data: [{
125
- price: {
126
- id: 'price_123',
127
- product: 'prod_123',
128
- },
129
- }],
130
- },
131
- },
132
- },
133
- };
134
-
135
- let updatedUser = null;
136
-
137
- const mockFastify = {
138
- log: {
139
- info: () => {},
140
- error: () => {},
141
- warn: () => {},
142
- },
143
- prisma: {
144
- user: {
145
- update: async (data) => {
146
- updatedUser = data;
147
- return { id: 1 };
148
- },
149
- },
150
- },
151
- };
152
-
153
- const mockStripe = {};
154
-
155
- // Import your handler
156
- const handler = customHandlers['customer.subscription.created'];
157
- await handler(mockEvent, mockFastify, mockStripe);
158
-
159
- // Assert database was updated
160
- assert.equal(updatedUser.where.stripeCustomerId, 'cus_123');
161
- assert.equal(updatedUser.data.subscriptionId, 'sub_123');
162
- });
163
-
164
- test('payment failure handler sends notification', async () => {
165
- const mockEvent = {
166
- type: 'invoice.payment_failed',
167
- data: {
168
- object: {
169
- id: 'in_123',
170
- customer: 'cus_123',
171
- subscription: 'sub_123',
172
- attempt_count: 2,
173
- amount_due: 2000,
174
- },
175
- },
176
- };
177
-
178
- let emailSent = false;
179
-
180
- const mockFastify = {
181
- log: {
182
- info: () => {},
183
- error: () => {},
184
- warn: () => {},
185
- },
186
- email: {
187
- send: async (to, subject, body) => {
188
- emailSent = true;
189
- assert.equal(subject, 'Payment Failed');
190
- return { success: true };
191
- },
192
- },
193
- };
194
-
195
- const mockStripe = {
196
- customers: {
197
- retrieve: async (id) => ({
198
- id,
199
- email: 'test@example.com',
200
- }),
201
- },
202
- };
203
-
204
- const handler = customHandlers['invoice.payment_failed'];
205
- await handler(mockEvent, mockFastify, mockStripe);
206
-
207
- assert.equal(emailSent, true);
208
- });
209
- ```
210
-
211
- Run tests:
212
- ```bash
213
- node --test test/**/*.test.js
214
- ```
215
-
216
- ## Manual Testing with cURL
217
-
218
- You can also send webhook events manually (useful for CI/CD):
219
-
220
- ```bash
221
- # Get a test event from Stripe
222
- stripe events list --limit 1
223
-
224
- # Send it to your local server
225
- curl -X POST http://localhost:3000/stripe/webhook \
226
- -H "Content-Type: application/json" \
227
- -H "Stripe-Signature: YOUR_SIGNATURE" \
228
- -d @test-event.json
229
- ```
230
-
231
- ## Testing in Production
232
-
233
- ### 1. Configure Webhook Endpoint
234
-
235
- In your Stripe Dashboard:
236
- 1. Go to Developers → Webhooks
237
- 2. Click "Add endpoint"
238
- 3. Enter your production URL: `https://yourdomain.com/stripe/webhook`
239
- 4. Select events to listen for (or select "Select all events")
240
- 5. Copy the signing secret to your production environment
241
-
242
- ### 2. Monitor Webhook Deliveries
243
-
244
- In Stripe Dashboard:
245
- - View webhook delivery attempts
246
- - See request/response details
247
- - Retry failed deliveries
248
-
249
- ### 3. Set Up Alerts
250
-
251
- Monitor for:
252
- - Failed webhook deliveries
253
- - Handler errors in your logs
254
- - Unusual event patterns
255
-
256
- ## Common Test Scenarios
257
-
258
- ### Test New Subscriber Flow
259
-
260
- 1. Create customer
261
- 2. Create checkout session
262
- 3. Complete checkout (use test card `4242 4242 4242 4242`)
263
- 4. Verify `customer.subscription.created` handler runs
264
- 5. Verify `invoice.paid` handler runs
265
- 6. Check database for new subscription
266
-
267
- ### Test Failed Payment Flow
268
-
269
- 1. Update payment method to failing card (`4000 0000 0000 0341`)
270
- 2. Wait for billing date or trigger manually
271
- 3. Verify `invoice.payment_failed` handler runs
272
- 4. Check email notifications sent
273
- 5. Verify retry logic
274
-
275
- ### Test Subscription Cancellation
276
-
277
- 1. Cancel subscription via API
278
- 2. Verify `customer.subscription.updated` handler runs
279
- 3. If `cancel_at_period_end=false`, verify `customer.subscription.deleted` runs
280
- 4. Check access revoked in database
281
-
282
- ## Debugging Tips
283
-
284
- ### Enable Verbose Logging
285
-
286
- ```javascript
287
- const fastify = Fastify({
288
- logger: {
289
- level: 'debug',
290
- transport: {
291
- target: 'pino-pretty',
292
- },
293
- },
294
- });
295
- ```
296
-
297
- ### Log All Webhook Events
298
-
299
- Add this to see raw events:
300
-
301
- ```javascript
302
- handlers: {
303
- '*': async (event, fastify, stripe) => {
304
- fastify.log.debug({
305
- event: event.type,
306
- data: event.data.object,
307
- });
308
- },
309
- }
310
- ```
311
-
312
- ### Check Webhook Signatures
313
-
314
- If signatures fail:
315
- 1. Verify webhook secret matches Stripe Dashboard
316
- 2. Check raw body is being used (not parsed JSON)
317
- 3. Verify headers are forwarded correctly (if using proxy)
318
-
319
- ### Test Mode vs Live Mode
320
-
321
- - Use `sk_test_` keys for development
322
- - Use `sk_live_` keys for production
323
- - Test and live webhooks are separate endpoints
324
- - Events don't cross between modes
325
-
326
- ## Best Practices
327
-
328
- 1. **Test all critical paths** - Subscription creation, payment failures, cancellations
329
- 2. **Use idempotency** - Handlers should be safe to run multiple times
330
- 3. **Log everything** - You can't debug what you can't see
331
- 4. **Monitor production** - Set up alerts for failed handlers
332
- 5. **Test error cases** - What happens if database is down?
333
- 6. **Verify async operations** - Do emails actually send?
334
- 7. **Check edge cases** - What if customer has no email?
335
-
336
- ## Troubleshooting
337
-
338
- ### Webhooks Not Received
339
-
340
- - Check webhook endpoint is accessible publicly
341
- - Verify webhook secret is correct
342
- - Check firewall/security group allows Stripe IPs
343
- - Review Stripe Dashboard for delivery attempts
344
-
345
- ### Handler Errors
346
-
347
- - Check logs for error messages
348
- - Verify database connections
349
- - Test handler functions in isolation
350
- - Ensure all required services are available
351
-
352
- ### Signature Verification Fails
353
-
354
- - Verify using raw body, not parsed JSON
355
- - Check webhook secret matches exactly
356
- - Ensure no middleware modifies the body
357
- - Verify Content-Type header is correct