I am trying to console a message when payment is success using stripe for that i am using webhooks.
const stripe = require('stripe')('sk_test_'); // Replace with your actual key
const handleWebhook = async (req, res) => {
let event;
try {
const sig = req.headers['stripe-signature'];
// Use req.body directly since it's raw
event = stripe.webhooks.constructEvent(req.body, sig, 'whsec_code');
} catch (err) {
console.error(`Webhook Error: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
console.log(event.type);
switch (event.type) {
case 'checkout.session.completed':
const session = event.data.object;
console.log('Checkout session completed:', session.id);
if (session.payment_status === 'paid') { alert("hii")
console.log('PaymentIntent was successful!');
const updatedValues = JSON.parse(session.metadata.updatedValues);
console.log("updatedValues is", updatedValues);
}
break;
And session.payment_status === 'paid' i need to test whether webhook is working or not.so i just alert a message.but i am getting
Webhook Error: Webhook payload must be 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.
my app.js
gsrApp.use((req, res, next) => {
console.log(`Incoming request size: ${JSON.stringify(req.body).length} bytes`);
next();
});
and router i have
routerV2.post('/webhook', express.raw({ type: 'application/json' }), handleWebhook);
Thanks in advance
It's because of app.use(express.json());
code.
So the simplest solution would be moving the webhook route before app.use(express.json());
If you can't do that then try this
app.js
app.use(
express.json({
verify(req, res, buf, encoding) {
if (req.path.includes('webhook')){
req.rawBody = buf.toString(); // sets raw string in req.rawBody variable
}
}
})
);
webhook handler
const handleWebhook = async (req, res) => {
let event;
try {
const sig = req.headers['stripe-signature'];
// USE req.rawBody which is created specifically for this route
event = stripe.webhooks.constructEvent(req.rawBody, sig, 'whsec_code');
} catch (err) {
console.error(`Webhook Error: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
console.log(event.type);
switch (event.type) {
case 'checkout.session.completed':
const session = event.data.object;
console.log('Checkout session completed:', session.id);
if (session.payment_status === 'paid') { alert("hii")
console.log('PaymentIntent was successful!');
const updatedValues = JSON.parse(session.metadata.updatedValues);
console.log("updatedValues is", updatedValues);
}
break;
Finally you don't need express.raw({ type: 'application/json' })
, since we are doing that
router
routerV2.post('/webhook', handleWebhook);