简体   繁体   中英

Stripe webhook nodejs remix.run Stripe webhook - No signatures found matching the expected signature for payload

Could someone help me please. Do I need to convert the request body into raw json type? I'm using remix.run to create an endpoint for the stripe webhook. I'm getting an 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 - but I don't know how to convert the req.body into raw?

import type { ActionFunction } from "@remix-run/node";
import stripe from "stripe";

export const action: ActionFunction = async ({ request }) => {
  switch (request.method) {
    case "POST": {
      const endpointSecret =
        "whsec_abxxxxaf67fxxxa955";
      console.log("Header", request.headers.get("stripe-signature"));
      const sig: any = request.headers.get("stripe-signature");
      console.log("--sig", sig);

      let event;
      try {
        event = stripe.webhooks.constructEvent(
          request.body,
          sig,
          endpointSecret
        );
        console.log("event", event);
        return null;
      } catch (err) {
        console.log("err", err);
        return null;
      }
    }
  }
  return null;
};

export default () => {
  return <p>FAILED</p>;
};

And the error that I'm getting.

{
  type: 'StripeSignatureVerificationError',
  raw: {
    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'
  },
  rawType: undefined,
  code: undefined,
  doc_url: undefined,
  param: undefined,
  detail: undefined,
  headers: undefined,
  requestId: undefined,
  statusCode: undefined,
  charge: undefined,
  decline_code: undefined,
  payment_intent: undefined,
  payment_method: undefined,
  payment_method_type: undefined,
  setup_intent: undefined,
  source: undefined,
  header: 't=1669990993,v1=026c8a0xxxxxxxfc1048d1abc07,v0=85099acc2420c06bxxx22dd8553e60681befd59d238b4514cbdd',
  payload: <ref *1> ReadableStream3 [ReadableStream] 

My printed header is show the correct key, i think.

t=1669990993,v1=026c8a00b366cd657a2xxxxxxf5b003fc1048d1abc07,v0=85099acc2420c06bc0d2dxxx3e60681befd59d238b4514cbdd

It looks like you can get the raw request body with request.text() then use that in constructEvent .

const payload = await request.text()
...
event = stripe.webhooks.constructEvent(payload, sig, secret)

You can see this here , an example shared by a Stripe Developer Advocate here .

My working codes

import Stripe from "stripe";
import { insertIntoStripe } from "~/models/stripe.server";
import cuid from "cuid";
import { updatePaymentStatus } from "~/models/order.server";
import Plunk from "@plunk/node";

const stripe = new Stripe(process.env.STRIPE_API, {});

export const action = async ({ request }) => {
  const sig = request.headers.get("stripe-signature");
  let event;
  const payload = await request.text();

  try {
    event = stripe.webhooks.constructEvent(
      payload,
      sig,
      process.env.STRIPE_WEBHOOK_KEY
    );
  } catch (err) {
    return new Response(err.message, {
      status: 400,
    });
  }

  if (event.type == "payment_intent.succeeded") {
    const paymentIntentJson: any = event.data.object;
    const paymentIntentID: any = paymentIntentJson.id;
    const email: any = paymentIntentJson.charges.data[0].billing_details.email;
    const name: any = paymentIntentJson.charges.data[0].billing_details.name;
    const amount: any = paymentIntentJson.amount;

    const sessionList = await stripe.checkout.sessions.list();
    sessionList.data.map(async (session) => {
      if (session.payment_intent == paymentIntentID) {
        const client_reference_id: any = session.client_reference_id;
        await insertIntoStripe(
          cuid(),
          paymentIntentID,
          name,
          email,
          amount,
          client_reference_id,
          paymentIntentJson
        );
        await updatePaymentStatus(client_reference_id, "SUCCESS");
        const plunk = new Plunk(process.env.USEPLUNK_EMAIL_API);
        //send email
        await plunk.events.publish({
          email: email,
          event: "send-completed-order-email",
          data: {
            orderId: client_reference_id,
          },
        });
      }
      return null;
    });
    console.log("💰 payment success!");
    return new Response("Success", {
      status: 200,
    });
  }

  return new Response("Success", {
    status: 200,
  });
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM