NodeJS 获取对SvelteKit端点的请求的原始主体

z4iuyo4d  于 2023-08-04  发布在  Node.js
关注(0)|答案(3)|浏览(97)

我在SvelteKit应用程序中有一个端点,它处理来自Stripe的webhook请求。每个请求都经过签名,以便可以验证它是否来自Stripe。
我必须验证事件是否来自Stripe的代码如下所示:

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
}

字符串
但是当它从Stripe接收到一个事件时,我得到了这个错误:

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


经过一些研究,我发现在调用SvelteKit钩子之前,这个函数会将body解析为JSON,这意味着没有办法直接获得原始body,所以我决定最好的选择是尝试重建原始body:

event = stripe.webhooks.constructEvent(
  JSON.stringify(body),
  headers["stripe-signature"],
  WH_SECRET
);


我不完全确定为什么这不起作用,因为在the relevant code in the Stripe library中挖掘之后,它似乎可以很好地处理字符串。我最好的猜测是,在某个时候,编码变得混乱。
任何帮助都会非常感谢,因为我真的很想避免从SvelteKit切换,因为我已经用它完成了我的项目(回想起来不是一个好主意)。

jpfvwuh4

jpfvwuh41#

这是如何在Svelte Kit中获取请求的原始主体:

// routeName/+server.js
export async function POST({ request }) {
    const rawBody = await request.text()
    ...
}

字符串
我在处理条纹和苗条套件时也发现了这一点。

ccrfmcuu

ccrfmcuu2#

stripe.webhooks.constructEvent(payload, signature, secret)接受的payload必须是string | Buffer类型,但SvelteKit请求中接收到的rawBody是Uint8Array类型。
将Uint8Array rawBody或JSON.stringify'd rawBody作为有效负载传递会导致Stripe出现以下错误。参考:https://github.com/stripe/stripe-node#webhook-signing
错误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'
我们需要在不改变内容的情况下将rawBody转换为stringBuffer。要实现这一点,我们可以用途:Buffer.from(rawBody)
所以你的端点看起来像这样:

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

字符串

irtuqstp

irtuqstp3#

我发现下面的代码对我很有效

const body = await request.text();
 const signature = request.headers.get('stripe-signature')|| "";
 const event = stripe.webhooks.constructEvent(
     body,
     signature,
     secret,
 );

字符串
这最初确实给予了我一个TypeError: Body is unusable错误,但那是因为我在调用await request.text()之前调用了await request.json()

相关问题