#kevin-webhook-signature
1 messages ยท Page 1 of 1 (latest)
kevin-webhook-signature
Hey @noble wagon ! Usual disclaimer: please don't share pictures of code here ๐
Hey @tepid remnant got it
what the error means is that request.body is likely empty in your code. The first step is to debug this and log it to a file or your error handler or something to make sure it's not null
webhook signature verification with node can be really finicky depending on your environment
https://github.com/stripe/stripe-node/issues/341 has dozens of potential solutions and is usually a good start
but yeah really the error right now seems to be that request.body is null/empty in that code you shared a picture of so that's the first thing to debug
Thanks, that's the testing code from my webhook setup page, can I clarify if this testing flow is correct?
- I use stripe CLI forward the webhook request to my localhost with command : stripe listen --forward-to localhost:3000/api/stripeWebhook
- In CLI, trigger an event: stripe trigger payment_intent.succeeded
- at this point, my local webhook should have a request coming in, that's the request body I need to debug?
When I triggered the event, I didn't even receive any request at all...
terminal yeah
do I need to use sudo ?
[ 2:42PM] stripe trigger payment_intent.succeeded
Setting up fixture for: payment_intent
Running fixture for: payment_intent
Trigger succeeded! Check dashboard for event details.
I says trigger succeeded but there is no event in the log on stripe's website, and no request coming in
I'm using Next JS btw, it's the native Next JS parser
I tried console log request, nothing shows up
oh, wait a sec
yeah I know nothing about that unfortunately but I want to show you something simple
it logs out the quest
Basically your server-side code is running a request. It's not something you see in a browser or anything
What you can do is ignore the CLI and Stripe for a sec and just hit your server first
curl --header "Content-Type: application/json" --request POST --data '{id: "evt_123", object: "event", type: "customer.created"}' http://localhost:3000/api/stripeWebhook
if you do ^ it's going to send a POST request to that endpoint you have with the JSON body I put inside --data
what you can do then is before you look at the signature or anything, log a clear "I am in this code" and then log the req.body
and then debug that first. Once that works you can go back to trying the CLI
that's why I didn't want a picture earlier, because I could edit your code :p
Not sure how you can, but got it ๐
mostly you can just paste text here and wrap it between three ` before and after
that renders like my curl example above
Got it, will do, thanks
let me know what you find
Webhook signature verification issue: No stripe-signature header value was provided.%
It says above
yeah that's normal if you use the curl part
it's really just a basic step to make sure you server-side code in Node.js gets the request
I logged out signature from request.headers["stripe-signature"] , it is undefined
after triggered an event
Got the request.body, but no request.headers["stripe-signature"]
logged out request.headers, and there is no stripe-signature there
can you share your real/exact code?
'''javascript
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
export default async function handler(request, response) {
const endpointSecret =
"whse";
let event = request.body;
console.log(event) <---------log out request body
if (endpointSecret) {
const sig = request.headers["stripe-signature"]; <------undefined!!!
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
response
.status(400)
.send(`Webhook signature verification issue: ${err.message}`);
return;
}
}
......
(you're not supposed to share that secret)
That's a test secret
still
ok
that code is quite different from what you had earlier so I'm confused now
where do you log the request.body?
I removed the console log part as it is too long
Gotcha so you're certain it works?
yes, I logged out the request.body as well as request.headers
the body is long and looks ok, but there is no "stripe-signature" in the header
Okay so try the curl approach again and add --header "Stripe-Signature: 'my signature'" at the end
that should force the header and see if your code gets it
Webhook signature verification issue: Unable to extract timestamp and signatures from header%
ignore that sorry, ignore anything Stripe right now
You're debugging your route handler right now
your code should log req.headers and req.body and confirm you get what you are exactly sending in that curl request
~ handler ~ event: { id: 'evt_123', object: 'event', type: 'customer.created' }
~ handler ~ sig: 'my signature'
it works
if this is the case, I guess the testing mode event trigger didn't send out sig in request.headers ?
that feels weird to me though, it definitely should "just work" with the CLI. Trying to think what it could be
ah
so you're saying that with the CLI, the whole request.headers is completely empty?
it is not empty, just doesn't have signature
request.headers: {
host: 'localhost:3000',
connection: 'keep-alive',
'cache-control': 'max-age=0',
'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
referer: 'http://localhost:3000/api/stripeWebhook',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
cookie: 'next
these are all the items in headers
okay haven't tested this specific part in a while, give me a few minutes
ok, thanks
okay I just tried locally and I definitely get the signature
can you try console.log("request headers: ", JSON.stringify(request.headers)); in case this is truncated?
I wonder if it's Stripe-Signature, versus stripe-signature or something
request headers: {"host":"localhost:3000","connection":"keep-alive","cache-control":"max-age=0","sec-ch-ua":"\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"macOS\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","sec-fetch-site":"same-origin","sec-fetch-mode":"navigate","sec-fetch-user":"?1","sec-fetch-dest":"document","referer":"http://localhost:3000/api/stripeWebhook","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"csrf-c18b04ec4c5698413395dfb274abb8a930b29d15c42a1c; __stripe_mid=76da3216-658f-4f80-a9a6-43d7feb750a4bc883c"}
not there
and that comes from the CLI making that request?
I could get the sig from your curl, but not from the CLI
Can you give me an example Event id evt_123?
yes,
request headers: {"host":"localhost:3000","user-agent":"curl/7.88.1","accept":"*/*","content-type":"application/json","stripe-signature":"'my signature'","content-length":"64"}
that's just my fake request
I mean a real Event you got from the CLI to your endpoint so that I can look at our own network requestand see if a signature was sent
Where do I find this Event id
It says no event forwarded to me successfully
evt_1NOTIAKAjj6I40xpCX1JgNiV
You are running the command stripe trigger payment_intent.succeeded. What this does is run some real requests on your account to cause that Event to happen. All those Events are then sent to the CLI locally where you do stripe listen --forward-to xxxxx and you should see the requests come in straight there ```xxxx:~ $ stripe listen --forward-to 127.0.0.1:8888/webhook.php
A newer version of the Stripe CLI is available, please update to: v1.15.0
Ready! You are using Stripe API Version [2015-02-16]. Your webhook signing secret is whsec_123 (^C to quit)
2023-06-29 15:45:32 --> customer.created [evt_ABCDE]
2023-06-29 15:45:32 <-- [200] POST http://127.0.0.1:8888/webhook.php [evt_ABCDE]```
that's what I see locally, that's how I know a real Event is received by the CLI from my stripe trigger and then send to my local code
Setting up fixture for: payment_intent
Running fixture for: payment_intent
Trigger succeeded! Check dashboard for event details.```
this is what I see locally
ID
DATE
A Checkout Session expired
evt_1NOTIAKAjj6I40xpCX1JgNiV
6/29/23, 3:26:22 PM
A Checkout Session expired
evt_1NOTEeKAjj6I40xpMVkagJD2
6/29/23, 3:22:44 PM
A Checkout Session expired
evt_1NOT9QKAjj6I40xp9Bsp2RPk
6/29/23, 3:17:20 PM
A Checkout Session expired
evt_1NOT7CKAjj6I40xpDwcJkaz9
6/29/23, 3:15:02 PM
A Checkout Session expired
evt_1NOT6qKAjj6I40xpTpMFT8rc
6/29/23, 3:14:40 PM
A Checkout Session expired
evt_1NOT6iKAjj6I40xpZ7a3TNRS
6/29/23, 3:14:32 PM
A Checkout Session expired
evt_1NOT6YKAjj6I40xpsOHQ6emj
6/29/23, 3:14:22 PM
A Checkout Session expired
evt_1NOT5rKAjj6I40xpNtSALEuB
6/29/23, 3:13:39 PM
A Checkout Session expired
evt_1NOSoRKAjj6I40xp3fgJSeKl
6/29/23, 2:55:39 PM
A Checkout Session expired
evt_1NOSnnKAjj6I40xp9Q6w76cN
6/29/23, 2:54:59 PM```
found these from the Developer tab
yeah but that's not what I need
I'm sorry, I'm confused how you are doing/using this.
Don't you see anything in the terminal where you do stripe listen xxxx?
T7 [ 4:09PM] stripe listen --forward-to localhost:3000/api/stripeWebhook
> Ready! You are using Stripe API Version [2022-11-15]. Your webhook signing secret is whsec_2 (^C to quit)```
That's all, it just stops here
It shouldn't, it should show real events on that terminal right as they are being received by the CLI
Can you log req.body again in your code to find that evt_123?
nothing, it just freezes here
the samething happened yesterday when I tried it too
I thought this is normal behavor
it isn't no. It's supposed to tell you when it receives events and such
oh, then, there must be something wrong with this CLI
I also upgraded to v.15 too, even in v.14, it was the same
no event body now...
yeah, I can't even get the event body now...
not sure what happened
maybe reboot and start fresh
ok, is there any config prevent Mac shell incoming request btw?
the outbound traffic looks good
I don't know what that means, but I'm on a mac and it works totally fine
perfect okay so that Event was sent to your CLI and it has a real signature header on our end at least so I'm a bit baffled
which version of the CLI are you using?
stripe version 1.15.0
can stripe completion setup possibly cause issue? I did the stripe completion setup
Detected `zsh`, generating zsh completion file: stripe-completion.zsh
Suggested next steps:
---------------------
1. Move `stripe-completion.zsh` to the correct location:
mkdir -p ~/.stripe
mv stripe-completion.zsh ~/.stripe
2. Add the following lines to your `.zshrc` enabling shell completion for Stripe:
fpath=(~/.stripe $fpath)
autoload -Uz compinit && compinit -i
3. Source your `.zshrc` or open a new terminal session:
source ~/.zshrc
no I don't think it could be it
I'm sorry I'm running out of ideas here. Have you heard of ngrok before? https://ngrok.com
you could try that tool quickly to try and send Events to your local endpoint and see if you get the signature
alright, let me try it
thanks man
btw, if the fake curl post works, it should work on my end right
seems just the CLI issue
it says it is listening on the website
yeah I think so and ngrok will help with that
it's basically like our CLI, it "tunnels" requests to your local code
Got you, thank you very much
sure thing
Hi @noble wagon I'm taking over this thread
Can you copy and paste the event ID here?
I can log out all request.body, request.signature
evt_1NOUqyKAjj6I40xpm2AsrDjQ
Hey @rancid hound hope all is well!
Is this the correct event ID? Based on the log, this event was sent to your endpoint successfully https://dashboard.stripe.com/test/events/evt_1NOUqyKAjj6I40xpm2AsrDjQ
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Send me one of them that your endpoint responded with 400.
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 saw this error message, can you show me your code?
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
export default async function handler(request, response) {
const endpointSecret =
"whsec_";
let event = request.body;
console.log(" event:", event);
if (endpointSecret) {
const sig = request.headers["stripe-signature"];
console.log(
"request.headers:",
sig
);
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
response
.status(400)
.send(`Webhook signature verification issue: ${err.message}`);
return;
}
}
I'm using Next JS btw
it is the native Next JS request parser
I'm not familiar with NextJS, but it looks like the request.body is not a raw request body (i.e., string or buffer). Can you check if you can get a raw request body and pass it to constructEvent ?
ok, give me a sec
evt_3NOVOsKAjj6I40xp1fnA6rj3
I remove the default parser and it should be raw body now
but still got 400
here is the event id
Can you log request.body's type and check it's a string or buffer?
evt_3NOVbvKAjj6I40xp0drU41sw
I got error saying no signature value is provided, but I can log the value out
It's the same error, have you checked the type of request.body ?
It's object
const typeofrequestbody = typeof request;
request.body is undefined
well, if there is a good request parser from stripe packages, to do raw or buffer, that would be great, now, I need to find out what parser is needed ๐
Then you might want to check why request.body is undefined, or maybe there's a different property you should use to retrieve the request body.
yeah, give me a sec
I'm sure that I'm not the first guy who faces this issue, do you have any suggestions btw
or directions
I'm just here trying to figure out how to get raw request body
in Next JS
I'll suggest you to consult Next.js document and see how to get a request body and make it raw.
As you said earlier, the request.body is undefined, and I think you solve this problem first.
I checked the request object, and there is no tag named body there
great, it is 200 now
evt_3NOWHLKAjj6I40xp02clk1UR
but on the front end, http://localhost:3000/api/stripeWebhook, I still get 400, saying
Webhook signature verification issue: No stripe-signature header value was provided.
Thanks
huh?
does it need raw request or raw request.body
because once the parser is turned off, request.body becomes undefined
It needs raw request body.
since there is no body defined after disable parser, it has to be the request I guess
request body just doesnt work, but request works
all the working examples I saw are using request directly
but there is an issue, on the front end, it still gives me 400 error saying signature value is not provided
is this normal?
Webhook signature verification issue: No stripe-signature header value was provided.
In console it gives me
Unhandled event type charge.succeeded
and in the stripe listener it gives me green 200
so why do I still get 400 on the end point?
I can console log the signature value and see it too
What's the new event ID?
I don't see errors in Dashboard https://dashboard.stripe.com/test/events/evt_3NOWh1KAjj6I40xp1Gp7aWj1
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Where do you get this error Webhook signature verification issue: No stripe-signature header value was provided. ?
Why you render localhost:3000/api/stripeWebhook in browser?