Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

705
Views
Getting the raw body of a request to a SvelteKit endpoint

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).

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

The payload accepted by stripe.webhooks.constructEvent(payload, signature, secret) must be of type string | Buffer, but the rawBody received in the SvelteKit request is of type Uint8Array.

Passing the Uint8Array rawBody or a JSON.stringify'd rawBody as the payload results in the error below from Stripe. Refer: https://github.com/stripe/stripe-node#webhook-signing

Error message: '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'

We need to convert the rawBody into a string or Buffer without altering the contents. To achieve this we can use: Buffer.from(rawBody).

So your endpoint would look something like:

...
const stripeWebhookSecret = process.env['STRIPE_WEBHOOK_SECRET'];

export const post: RequestHandler = async (request) => {
  const rawBody = Buffer.from(request.rawBody);
  const signature = request.headers['stripe-signature'];

  try {
    event = stripe.webhooks.constructEvent(
      rawBody,
      signature,
      stripeWebhookSecret
    );
...
over 4 years ago · Santiago Trujillo Report

0

The request now comes with an arrayBuffer the can be converted into raw body like this:

function toBuffer(ab: any) {
  const buf = Buffer.alloc(ab.byteLength);
  const view = new Uint8Array(ab);
  for (let i = 0; i < buf.length; ++i) {
    buf[i] = view[i];
  }
  return buf;
}

export async function post(event: RequestEvent<Record<string, string>>) {
   ...
  const preRawBody = await event.request.arrayBuffer();
  const rawBody = toBuffer(preRawBody);
  
  try {
    stripeEvent = stripe.webhooks.constructEvent(
      rawBody,
      stripeSignature,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } ...
 }
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!