Skip to content

Commit 1cd7380

Browse files
committed
fix: return a 500 code on error in wh handler
1 parent eb0df27 commit 1cd7380

5 files changed

Lines changed: 171 additions & 2 deletions

File tree

firestore-stripe-payments/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
[docs] - update references from @stripe to @invertase in docs
1010

11+
[fix] - provide a 500 code to Stripe in the webhook handler response when appropriate
12+
1113
## Version 0.3.10 - 2025-03-24
1214

1315
[fix] - upgrade resources to node 20
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import * as logs from '../../../../src/logs';
2+
import { handleWebhookEvents } from '../../../../src/handlers/webhook-events';
3+
import * as httpMocks from 'node-mocks-http';
4+
5+
// Firebase functions will add rawBody to the request object before it reaches the handler
6+
declare module 'express' {
7+
interface Request {
8+
rawBody: Buffer;
9+
}
10+
}
11+
12+
jest.mock('../../../../src/logs', () => ({
13+
startWebhookEventProcessing: jest.fn(),
14+
webhookHandlerError: jest.fn(),
15+
webhookHandlerSucceeded: jest.fn(),
16+
badWebhookSecret: jest.fn(),
17+
}));
18+
19+
jest.mock('../../../../src/config', () => ({
20+
stripeWebhookSecret: 'test-webhook-secret',
21+
customersCollectionPath: 'customers',
22+
stripe: {
23+
webhooks: {
24+
constructEvent: jest.fn(),
25+
},
26+
paymentIntents: {
27+
retrieve: jest.fn(),
28+
},
29+
},
30+
eventChannel: null,
31+
}));
32+
33+
jest.mock('firebase-admin', () => ({
34+
initializeApp: jest.fn(),
35+
firestore: jest.fn(() => {
36+
throw new Error('Firestore operation failed');
37+
}),
38+
}));
39+
40+
describe('Webhook Events Handler', () => {
41+
beforeEach(() => {
42+
jest.clearAllMocks();
43+
44+
const config = require('../../../../src/config');
45+
config.stripe.webhooks.constructEvent.mockReturnValue({
46+
id: 'evt_123',
47+
type: 'product.created',
48+
data: {
49+
object: { id: 'prod_123' },
50+
},
51+
});
52+
});
53+
54+
it('should return 500 status when webhook handler fails', async () => {
55+
const mockRequest = httpMocks.createRequest({
56+
rawBody: Buffer.from('test-body'),
57+
headers: {
58+
'stripe-signature': 'test-signature',
59+
},
60+
});
61+
62+
const mockResponse = httpMocks.createResponse();
63+
64+
await handleWebhookEvents(mockRequest, mockResponse);
65+
66+
expect(logs.webhookHandlerError).toHaveBeenCalledWith(
67+
expect.any(Error),
68+
'evt_123',
69+
'product.created'
70+
);
71+
72+
expect(mockResponse.statusCode).toBe(500);
73+
74+
const responseData = JSON.parse(mockResponse._getData());
75+
expect(responseData).toEqual({
76+
error: 'Webhook handler failed. View function logs in Firebase.',
77+
});
78+
});
79+
});

firestore-stripe-payments/functions/package-lock.json

Lines changed: 87 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

firestore-stripe-payments/functions/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"firebase-functions-test": "^3.4.1",
3636
"jest": "^29.7.0",
3737
"mocked-env": "^1.3.5",
38+
"node-mocks-http": "^1.17.2",
3839
"playwright": "^1.52.0",
3940
"rimraf": "^6.0.1",
4041
"ts-jest": "^29.3.4",

firestore-stripe-payments/functions/src/handlers/webhook-events.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131

3232
export const handleWebhookEvents = async (
3333
req: functions.https.Request,
34-
resp
34+
resp: functions.Response
3535
) => {
3636
const relevantEvents = new Set([
3737
'product.created',
@@ -177,7 +177,7 @@ export const handleWebhookEvents = async (
177177
logs.webhookHandlerSucceeded(event.id, event.type);
178178
} catch (error) {
179179
logs.webhookHandlerError(error, event.id, event.type);
180-
resp.json({
180+
resp.status(500).json({
181181
error: 'Webhook handler failed. View function logs in Firebase.',
182182
});
183183
return;

0 commit comments

Comments
 (0)