#paulC.webhook-payloads
1 messages ยท Page 1 of 1 (latest)
Hey! Generally the event payload will contain the object it pertains to, as well as some other fields related to the event (timestamp, etc): https://stripe.com/docs/api/events/object
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
seems like the event is constructed , so a better questoni would be what does the req.body of the constructor req contain ?
Thanks so much , will look it up !
For example, checkout.session.completed event will included the Checkout Session object related to the event
I am asking because the req.body is empty in a webhook test mode , is it normal ?
Shouldn't be, no. Test event payloads are identical to live ones
Assuming this is Node, you'll likely need to parse req.body
Oh.. then could you please help me figure out what I am doing wrong ?
I am using app.use(express.urlencoded({extended: true}))
Yeah the event payloads are JSON so you'll need to parse it in your Express endpoint. See here: https://stripe.com/docs/webhooks/quickstart
Yeah I am following that
This is how I am doing
const webHookStripe = async (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
}
catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
//DB queries
res.send(paymentIntent)
break;
default:
console.log("payment was attempted")
}
console.log("BUZZINGA")
return res.json({ received: true });
}
router.post('/webhook', bodyParser.raw({type: 'application/json'}),webHookStripe)
Previously , I was parsing the req only with app.use(express.urlencoded({extended:true})) , but now I also tried like in your docs but bodyParse is deprecated and they encourage to use my initial method
bodyParser*
Can you try the example I linked verbatim? express.json etc
Are the events definitely being forwarded to the endpoint? Are you using the CLI?
Yes I am using it
Can you share an event ID (evt_xxx) and I'll have a quick peek
sure 1 sec let me trigger an event again
req_bp4vGyvj4ya3LQ
oh event
evt_3Juw7IA3jSMal6iv1PSfZXUH
Also , is super strange : sometimes the event triggers the webhook and subsequently I can see the console.log , but some other times it doesnt trigger.
in the terminal
Yes, but which log in your code. There's 2
A , none of them ๐
sometimes the event triggers the webhook and subsequently I can see the console.log
I can only see a log I put before the try catch and sometimes I can see that one , like this:
Sounds like it's tripping up somewhere then. Can you log out event before the switch statement?
Could well be the signature signing
const webHookStripe = async (req, res) => {
const sig = req.headers['stripe-signature'];
console.log("Here")
......
Sometimes I can see the Here log , but most of the time not
I have also addressed this issue with a colleague of your yesterday but still didnt find a solution that works all the time
yours*
Yeah unfortunately the CLI is sometimes sporadic with events
Yeah , because with cURL works all the time
There's an ongoing issue: https://github.com/stripe/stripe-cli/issues/600
Ah .. makes sense then
Could just be that if you can hit the endpoint ok with cURL
Maybe host your webhook somewhere and run test events to that URL
I'd try express.json() method instead of bodyParser
as mentioned before , using the example in the docs with bodyParser doesnt work (is deprecated) and I am using app.use(express.urlencoded({extended: true}))
Alright I will give it a try !
express.urlencoded() is for urlencoded payloads (which we do not use)
I have executed curl -X POST http://localhost:8000/webhook -d "hello" "test"
yet logging req.body gives only { hello: '' }
You need to format the -d parameters correctly:
curl -X POST http://localhost:8000/webhook -d '{"hello": "test"}'
I think
Hardly use cURL ๐
Its a nightmare , especially on windows
Use Postman or similar. We have a collection that is super useful too: https://github.com/stripe/stripe-postman
Regarding this , when the cli emits an event doesnt it also send some data that I cannot replicate with postman/curl ? How would I go around making a stripe-signature and all that stuff that should be in the body?
Yeah you can't really use Postman to replicate the events. Was more just a tip to interface with our API if you were messing about with cURL
Did the cURL JSON work as I suggested?
If so, I'd just deploy your handler somewhere and create a test webhook that points to it
I see, could you please give me 5 mins to make some more reuqests , see how it goes ?
Sure!
I am probably missing something , but for the webhook events , dont we need a POST route ?
You'd have to create that yourself. There's no default POST method for forwarding a fake event to your webhook
That's the job of the CLI, just frustrating that sometimes it's so sporadic
I keep getting Webhook Error: Unable to extract timestamp and signatures from header
but it does hit it
always
Ah, yeah so if you're using signature signing it'll be different. It expects the raw payload (not JSON), and will construct the event payload for you: https://stripe.com/docs/webhooks/signatures
Alright looking over it right now
router.post('/webhook', bodyParser.raw({type: 'application/json'}),webHookStripe)
Was correct
Then: event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
event variable is your event payload, assuming the signing signature is validated
SO you don't need to worry about req.body when you use constructEvent
(except for passing it as an argument) ๐
But it should be the raw body, not parsed as JSON or anything
Okay so postman also triggers the webhoook
Okay so I found something that seems to trigger the endpoint all the time
But it still throws the error that event is undefined
At which point/line?
Here
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
Even tough the req.body , signature and the secret are logged correctly
Eh, you declare event right above the try/catch block. Right?
yes
let event
const webHookStripe = async (req, res) => {
const sig = req.headers['stripe-signature'];
console.log(sig)
console.log(endpointSecret)
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
console.log(event)
}
catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
//DB queries
res.send(paymentIntent)
break;
default:
console.log("payment was attempted")
}
return res.json({ received: true });
}
My assumption here is that constructEvent is failing. How are you hitting this endpoint? Via Postman?
Like I'm not sure the signing secret will work that way as you don't have a generated secret per se
No , I got the cli to work . It seems like it always needs another terminal open to listen , with stripe listen --forward-to localhost:8000/webhook. Then , it reacts to every request
Yep, it does
And you're using the secret the CLI gives you?
yes exactly
I'd get it working without the signing stuff for now
Do you mean that I should not encounter this in production ?
To just forget about it ?
No, I'd just rip the constrcutEvent out and parse the JSON yourself. Get the webhook working as you need
Then reintroduce the signing secret
alright let me give this a try please
Finally works !!
This is how I did it :
const webHookStripe = async (req, res) => {
const event=req.body
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log("Payment Succeeded")
//DB queries
break;
default:
console.log("Payment was attempted")
}
return res.json({ received: true });
}
Thank you soo much ynnoj !