I have an endpoint in my SvelteKit app which handles webhook requests from Stripe. Each request is signed so that it can be verified to come from Stripe.
The code I have to verify the event is from Stripe looks something like this:
import Stripe from "stripe";
const WEBHOOK_SECRET = process.env["STRIPE_WH_SECRET"];
const stripe = new Stripe(process.env["STRIPE_SECRET"], {
apiVersion: "2020-08-27",
});
export async function post({ headers, body }) {
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
headers["stripe-signature"],
WEBHOOK_SECRET
);
} catch (err) {
return {
status: 400,
body: err,
};
}
// Do stuff with the event
}
But when it receives an event from Stripe, I get this error:
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing
After some research, I found that the body is parsed into JSON by this function before even SvelteKit hooks are called, meaning there's no way to directly get the raw body, so I decided my best option was to try to reconstruct the original body:
event = stripe.webhooks.constructEvent(
JSON.stringify(body),
headers["stripe-signature"],
WH_SECRET
);
I'm not totally certain why this doesn't work, since after digging around in the relevant code in the Stripe library, it seems to handle strings fine. My best guess is that at some point the encoding gets messed up.
Any help with this would be greatly appreciated, as I'd really like to avoid switching away from SvelteKit, since I've already practically finished my project with it (wasn't a great idea, in retrospect).