stripe-paymentssupabaseedge-function

Receiving 'No signatures found matching expected signature' error when processing Stripe webhook"


I am developing a webhook to process events from Stripe using Deno and the Stripe library. Recently, when trying to validate the webhook signature, I am receiving the following error:

Webhook Error: No signatures found matching the expected signature for payload.

details

API Keys: I have verified that the Stripe API keys are correct and are the same ones I use in my application. Webhook Configuration: The webhook is correctly set up in the Stripe dashboard, and I am receiving events as expected. Webhook Code: I am using the following code to process the webhook:

import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import Stripe from 'https://esm.sh/stripe@11.1.0?target=deno';
import { config } from "https://deno.land/x/dotenv/mod.ts";

// Load environment variables from .env file
const env = config();
const stripeApiKey = env.STRIPE_API_KEY;
const stripeWebhookSecret = env.STRIPE_WEBHOOK_SIGNING_SECRET;

// Configure the Stripe client
const stripe = new Stripe(stripeApiKey as string, {
  apiVersion: '2022-11-15',
  httpClient: Stripe.createFetchHttpClient(),
});

// Start the Deno server
Deno.serve(async (request) => {
  const webhookStripeSignatureHeader = request.headers.get('Stripe-Signature');
  if (!webhookStripeSignatureHeader) {
    return new Response('Missing Stripe signature', { status: 400 });
  }

  const webhookRawBody = await request.arrayBuffer();
  const requestBody = new TextDecoder().decode(webhookRawBody);
  const signature = webhookStripeSignatureHeader;

  let event;

  try {
    // Construct the event from Stripe using the raw body and the signature header
    event = stripe.webhooks.constructEvent(requestBody, signature, stripeWebhookSecret);
  } catch (err) {
    console.error(`Webhook Error: ${err.message}`);
    return new Response(err.message, { status: 400 });
  }

  console.log(`🔔 Event received: ${event.id}`);
  return new Response(JSON.stringify({ ok: true }), { status: 200 });
});

What could be causing the error "No signatures found matching the expected signature for payload" even with the correct API keys? Is there anything I can do to ensure that the request body is being passed correctly to the constructEvent function?

I have checked the environment variables, and they are loading correctly. I have tried debugging the application and verified that the request body is correct.


Solution

  • The common cause of this issue that request body is no longer in raw form, especially when a decoder or transform function is used.

    I'd recommend using following function (reference) to retrieve the raw request body:

    // First step is to verify the event. The .text() method must be used as the
    // verification relies on the raw request body rather than the parsed JSON.
    const body = await request.text();