I’m stuck on this, could someone help me?
I put it in postman: https://my-server/api/webhook
and i receive this:
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.Learn more about webhook signing and explore webhook integration
examples for various frameworks at
https://github.com/stripe/stripe-node#webhook-signing
i’m using ReactJS and Node
index.js
const express = require('express');
const Stripe = require('stripe');
const bodyParser = require('body-parser');
const cors = require('cors');
const webhookRoutes = require('./routes/webhook');
const app = express();
const stripe = Stripe(
'sk_test',
);
app.use(cors());
app.use(express.json());
app.use('/webhook', express.raw({ type: 'application/json' }));
app.use('/api', webhookRoutes);
app.post('/create-checkout-session', async (req, res) => {
try {
console.log('Received request to create checkout session');
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'usd',
product_data: {
name: 'Nome do Produto',
},
unit_amount: 2000,
},
quantity: 1,
},
],
mode: 'payment',
success_url: 'http://localhost:5173/success',
cancel_url: 'http://localhost:5173/cancel',
});
console.log('Checkout session created successfully:', session);
res.json({ id: session.id });
} catch (error) {
console.error('Error creating checkout session:', error.message);
res.status(500).json({
error: 'Failed to create checkout session',
});
}
});
const PORT = process.env.PORT || 4242;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
webhook.js
const express = require('express');
const Stripe = require('stripe');
const router = express.Router();
const stripe = Stripe('sk_test');
router.post('/webhook', async (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, 'whsec_');
} catch (err) {
console.log(`Webhook Error: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
console.log('Pagamento confirmado:', session);
}
res.json({ received: true });
});
module.exports = router;
2
Answers
The problem is…
This parses all
application/json
request bodies into a JavaScript data structure (usingJSON.parse()
) whereas Stripe wants you to forward the raw request body.You should simply register your webhook route handler before
express.json()
. You’ll also need theraw()
middleware set for those webhook routes as well.See also https://docs.stripe.com/identity/handle-verification-outcomes#create-webhook
It’s because of
app.use(express.json());
code.So the simplest solution would be moving the webhook route before
app.use(express.json());
Or You can try this.
index.js
webhook handler
Finally you don’t need
express.raw({ type: 'application/json' })
, since we are doing thatrouter
Note: I’ve modified the api path for webhook