#ague_webhooks-go
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1215428816076283985
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
๐
Hi there! Note that webhook signatures for use with the CLI and on the Dashboard are different
I know. I realized that and moved from CLI to Dashboard so I didn't have to keep updating my secret in AWS Secrets
but nevertheless, the problem persists. I've revealed the secret in the dashboard, verified that I am using the correct secret. In a last ditch effort, I dumped all variables involved to logs and thats when I saw that I'm only receiving [INFO]: t=1709849877 when calling
sigHeader := r.Header.Get("Stripe-Signature")
log.Infoln(sigHeader)
Based on everything I have read and recall from last time I setup v72, I'm supposed to get a hash in a v0 and v1 portions of the header. Which I'm not receiving
Can you share your handler code, specifically how you're constructing the event?
sure. one sec
func HandleWebhook(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodOptions {
return
}
w.Header().Set("Content-Type", "application/json")
const MaxBodyBytes = int64(65536)
r.Body = http.MaxBytesReader(w, r.Body, MaxBodyBytes)
body, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte{})
return
}
sigHeader := r.Header.Get("Stripe-Signature")
//sigSplit := strings.Split(sigHeader, ",")
// Secret is pulling correctly from AWS secrets
event, err := webhook.ConstructEvent(body, r.Header.Get("Stripe-Signature"), Secret)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte{}) // TODO: More informative HTTP responses
return
}
// process wh event
w.WriteHeader(http.StatusOK)
}
it's mostly just copied from the docs
I also removed my log lines for brevity
I'll run this by a teammate who's more well versed with Go but I suspect it may have to do with this line:
r.Body = http.MaxBytesReader(w, r.Body, MaxBodyBytes)
that's copied from the docs verbatim from https://docs.stripe.com/webhooks/quickstart
no worries, I'll be here
๐
ague_webhooks-go
๐ Sorry I know basic go myself but not much more. Happy to help though
sure
Step 1: you mentioned the secret, which one are you using? The CLI has its own secret so they work completely differently
the last secret I used was a dashboard secret with a dashboard fired test event
assuming you can see things on my account, it's the one attached to the wh endpoint listed in my original request
Okay so right now the CLI is fully off and you have a real public API endpoint that is receiving that specific Event?
yes, I still have a prod endpoint that receives webhooks properly from v72. I'm working on upgrading to the latest sdk across the board
and the endpoint receiving my test webhooks now is a lambda function
is this brand new code that lambda function? Or is it exactly what you have set up in the past on v72?
it's the same. I noticed things didn't seem to have changed all that much between versions when I was going over the latest docs
Okay so you created a brand new WebhookEndpoint, pinned to the latest API version, then you deployed code that received the Event the exact same way your existing production endpoint works and you're getting a signature mismatch?
I'm getting webhook had no valid signature specifically
but, yes, everything else is as you said. I'm receiving the webhook into my lambda function, but signature validation fails
Cool, can you do this again but log the exact signature and exact webhook secret first? Share the last 4 characters of both so I can confirm they match
fire a new event or resend a previous one?
Event: evt_1Orq7GGniDWbO48M5OcRHptf
Secret last 4: 3r06
Signature v1: df30
Signature v0: 398a
Okay so you have all the right values
which makes me even more confused
So the problem has to be with the code itself and how you extract the "raw body" from the incoming request. Something, somewhere, no idea what yet, is likely extracting the info incorrectly which prevents us from verifying the signature since we have a different body/payload
Can you log the raw data you are receiving to a file and then share it so I can have a look?
raw data from the incoming webhook?
also, I'm using go 1.22. I saw that the sdk is using 1.13. perhaps it's a language version issue?
unlikely but possible yes
how easy is it for you to switch to v72 on that exact code and see if the signature matches?
um, not terribly difficult. will take me a few minutes
that'd help understand if it's the SDK or your environment
I want to believe it's something in the way you configured the lambda
hum you have no "indentation" here which surprises me and is likely the issue
like there's no "space" before properties
that looks like something is changing the content of what we send to you
sorry, had to hand copy it from Coudwatch... AWS does evil things to Go logs in CloudWatch
Ah yeah. Hum verifying the signature is extremely tricky. It has to match exactly what we sent you, up to any space and comma
So you need to find a way to log the exact raw text otherwise we can't make progress. What I do is write it to a file when I debug this
the headers is a raw header dump
ok, gimme a couple minutes.. I'll add some extra code to dump to a file
sounds good
ok, before I go the route of hacking out a file, I reverted with the exact same code to v72 and still receiving the same error. but I think the dashboard still sent me a v76 webhook. I don't know how to fire a webhook off for a specific api version from the dashboard
that's mostly impossible
but you'd get a different error if the issue was the API version
https://github.com/stripe/stripe-go/blob/5272a5c8c1a3790368da5dc520d54c868ceab801/webhook/client.go#L207 that's where the API version error is raised
okay so at least this seems to confirm this isn't an SDK issue and it's something in your own environment that's causing it
I assume you have some kind of CDN for example that is in front of your endpoint and it's doing "something" to the raw body. And your production environment must have a specific configuation
it's being proxied through aws api gateway. guess I'll have to take a closer look at what's going on there even though proxying the way I am is supposed to just pass through the body as is
yeah my understanding is that some gateways will parse the JSON to be helpful
A few years ago some developers said they had to write a custom "Body Mapping Template" that looked like this { "method": "$context.httpMethod", "body": $input.json('$'), "rawBody": "$util.escapeJavaScript($input.body).replaceAll("\\'", "'")", "headers": { #foreach($param in $input.params().header.keySet()) "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end #end } }
my guess is you have something like that in prod