#rhuzaifa_code
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/1329908462704136242
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- rhuzaifa_error, 4 hours ago, 38 messages
- rhuzaifa_code, 8 hours ago, 18 messages
- rhuzaifa_docs, 2 days ago, 6 messages
- rhuzaifa_docs, 3 days ago, 19 messages
- rhuzaifa_webhooks, 4 days ago, 27 messages
- rhuzaifa_webhooks, 4 days ago, 23 messages
this is what i tried, i am using jest for testing
import { createMocks } from "node-mocks-http";
const stripeEvents = await stripe.events.list({
limit: 10,
types: ['checkout.session.completed', /* more events */],
created: {
gte: Math.floor(new Date(new Date().getTime() - 8 * 60 * 60 * 1000).getTime() / 1000) // 8 hours ago - random
}
});
const rawBody = JSON.stringify(stripeEvents.data[0])
const timestamp = Math.floor(Date.now() / 1000);
const payloadToSign = `${timestamp}:${rawBody}`;
const signature = stripe.webhooks.generateTestHeaderString({
payload: rawBody,
secret: process.env.STRIPE_WEBHOOK_SECRET,
timestamp,
});
const { req, res } = createMocks({
method: 'POST',
url: "/api/webhooks/stripe",
headers: {
...headers,
'stripe-signature': signature,
'content-type': 'application/json',
},
body: rawBody as any,
});
await stripeWebhook(req as any, res as any); // this is my webhook endpoint
and i am building with nextjs, so the request signtaure verification is same as this https://github.com/stripe/stripe-node/blob/master/examples/webhook-signing/nextjs/pages/api/webhooks.ts
the request goes through to my webhook endpoint but hangs on payload verification.
These are the lines of code where we calculate the expected signature given the request body and time. I think you can do this to calculate your header and then provide that.
Another option that might be easier is you can use the exact event and headers that you got the first time, by default we error if the event was older than 5 minutes, but you can override that with constructEvent's tolerance parameter. So you can calculate the number of seconds between now and when the event was created and then pass tolerance= that number + some extra time for padding.
i can't access the link
Another option that might be easier is you can use the exact event and headers that you got the first time
this could work, but i would be dealing with 7-8 events so not sure if it would work for all of those, since signatures could change per event type?
Ok, from a quick look, seems like a lot happens for creating the signature. The main doubts/confusions I have are
- is req body the event payload? If yes is it the stringified or the json object?
- is stripe-signature header the combination of current timestamp + raw body or event timestamp + raw body?
- do i need to stream the payload as buffer or a normal http call would do?
If you could answer 1-3 it would be great, else no worries i can dig into the implementation in the link.
Looking in to this
So for 1, we pass the event Payload that you pass to constructEvent directly to VerifyHeader which in turn passes it to this code:
https://stripe.sourcegraphcloud.com/stripe/stripe-node/-/blob/src/Webhooks.ts?L284-288
That decodedPayload variable is what becomes the payload that gets passed into the code that I linked before
Payload is just the body of the event request that we sent represented as a UTF-8 string. If you interpret it as json, that can actually mess with ordering an spacing and throw off the calculation
In another thread, will get back to 2 and 3 in a minute
ok so I updated the way raw body is received in my endpoint: its same as https://github.com/stripe/stripe-node/blob/055bfff12e859aa98d00ddea72fcf60da8ec1a40/examples/webhook-signing/nextjs/pages/api/webhooks.ts#L18-L19
and in test mode i just directly use the body ex:
const rawBody = process.env.NODE_ENV === 'test' ? req.body : await buffer(req);
const event = stripe.webhooks.constructEvent(rawBody, signature, process.env.STRIPE_WEBHOOK_SECRET);
this works. So prob the issue is in my test suite for sending correct buffer. I think this env check (for test env) is fine and will work in my case.
TYSM for the help!
For 2, this is what the header typically looks like. t is the unix timestamp of right now, v1 and v0 are different calculations of the webhook signature and I am having trouble remembering which one you will want to use here. Figuring that out
Stripe-Signature: t=1737144421,v1=4d6cc2683dc605bca102607e6e26f7e6e02347c13630966dc9a4f2e4b603de32,v0=6a6c02d7ea77b1f58d6abd7438f173eaad88f3b04f63463e4eccb368debc1a20
And for #3, I think we allow Buffer or UTF8 Array, can find the typescript definition in a second
It looks like v1 is where you'll want to put that computed header. I don't think we check v0 unless the check on v1 fails