I am trying to code a subscription system with stripe. My following code is mostly copied from the stripe docs, but it always shows me this error:
Webhook signature verification failed. Webhook payload must b
e provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead.
Signature verification is impossible without access to the original signed material.
Learn more about webhook signing and explore webhook integration
examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing
This is my code written in javascript:
app.post(
'/webhook',
express.raw({ type: 'application/json' }),
(request, response) => {
let event = request.body;
const endpointSecret = 'whsec_.....';
if (endpointSecret) {
const signature = request.headers['stripe-signature'];
try {
event = stripe.webhooks.constructEvent(
request.body,
signature,
endpointSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return response.sendStatus(400);
}
}
let subscription;
let status;
switch (event.type) {
case 'customer.subscription.created':
subscription = event.data.object;
status = subscription.status;
console.log(`Subscription status is ${status}.`);
break;
default:
console.log(`Unhandled event type ${event.type}.`);
}
response.send();
}
);
Does anyone know what I am doing wrong? I have literally been searching the internet for an hour now and cant find anything. Thanks in advance!
It's because app.use(express.json());
code. Try to move webhook route before app.use(express.json());
.
// webhook route
app.post(
'/webhook',
express.raw({ type: 'application/json' }),
(request, response) => {
let event = request.body;
const endpointSecret = 'whsec_.....';
if (endpointSecret) {
const signature = request.headers['stripe-signature'];
try {
event = stripe.webhooks.constructEvent(
request.body,
signature,
endpointSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return response.sendStatus(400);
}
}
let subscription;
let status;
switch (event.type) {
case 'customer.subscription.created':
subscription = event.data.object;
status = subscription.status;
console.log(`Subscription status is ${status}.`);
break;
default:
console.log(`Unhandled event type ${event.type}.`);
}
response.send();
}
);
app.use(express.json());
Referencing the Stripe quickstart server.js code (https://stripe.com/docs/billing/quickstart#provision-access-webhooks), adding the following simple line, placed before app.use(express.json());
solved the issue for me.
app.use('/webhook', express.raw({ type: 'application/json' }));
This is telling Express to do something different specifically for the 'webhook' endpoint. And the given 'express.raw...' parameter is what Stripe was already calling as part of their route method for /webhook
.
You won't need to rearrange the ordering of your routes/endpoint code or anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With