【问题标题】:NextJS Stripe Webhook Raw BodyNextJS Stripe Webhook 原始正文
【发布时间】:2021-12-26 07:25:54
【问题描述】:

为了在 NextJS 上为 Stripe webhook 传递一个原始的身体,我扯了扯头发!

到处尝试了很多解决方案,但我似乎无法成功。

让开发者拥有超能力(我仍在获得)。

条纹测试错误:

未找到与负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求正文

我的 NextJS webhook 端点测试:

import { buffer } from 'micro';
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

export default async function handler(req, res) {

    console.log("Payment intent")

    const event = req.body

    console.log(event)

    if (process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET) {
        // Get the signature sent by Stripe
        const signature = req.headers['stripe-signature'];
        console.log(signature)
        try {
          event = stripe.webhooks.constructEvent(
            req.body,
            signature,
            process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET
          );
        } catch (err) {
          console.log(`⚠️  Webhook signature verification failed.`, err.message);
          return res.sendStatus(400);
        }
      }

    console.log(event.type)

    // Handle the event
    switch (event.type) {
        case 'payment_intent.succeeded':
            console.log("Success!")
            break;
        default:
            console.log(`Unhandled event type ${event.type}`);
    }



}

也试过了:

import { buffer } from 'micro';
import Cors from 'micro-cors';

const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);

const webhookSecret = process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET_NEW;

// Stripe requires the raw body to construct the event.
export const config = {
  api: {
    bodyParser: false,
  },
};

const cors = Cors({
  allowMethods: ['POST', 'HEAD'],
});

const webhookHandler = async (req, res) => {

  if (req.method === 'POST') {
    const buf = await buffer(req);
    console.log(buf.toString())
    const sig = req.headers['stripe-signature'];
    console.log(process.env.STRIPE_SECRET_KEY)
    console.log(webhookSecret)
    console.log(sig)
    let event;

    try {
      event = stripe.webhooks.constructEvent(
        buf.toString(),
        sig,
        webhookSecret
      );
    } catch (err) {
      console.log(`❌ Error message: ${err.message}`);
      res.status(400).send(`Webhook Error: ${err.message}`);
      return;
    }


    if (event.type === 'payment_intent.succeeded') {
      const paymentIntent = event.data.object;
      console.log(`???? PaymentIntent status: ${paymentIntent.status}`);
    } else if (event.type === 'payment_intent.payment_failed') {
      const paymentIntent = event.data.object;
      console.log(
        `❌ Payment failed: ${paymentIntent.last_payment_error?.message}`
      );
    } else if (event.type === 'charge.succeeded') {
      const charge = event.data.object;
      console.log(`???? Charge id: ${charge.id}`);
    } else {
      console.warn(`????‍♀️ Unhandled event type: ${event.type}`);
    }

    res.json({ received: true });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
};

export default cors(webhookHandler);

【问题讨论】:

    标签: api next.js stripe-payments webhooks serverless-framework


    【解决方案1】:

    默认情况下,NextJS 根据标头中传入的 Content-Type 解析请求正文。您可能希望禁用此 [0],然后使用 buffer 将其作为流使用。

    下面的代码对我有用:

    export const config = {
      api: {
        bodyParser: false,
      },
    };
    
    import { buffer } from 'micro';
    const stripe = require('stripe')(process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET);
    
    
    export default async function handler(req, res) {
    
        let event;
    
        if (process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET) {
            // Get the signature sent by Stripe
            const signature = req.headers['stripe-signature'];
            const buf = await buffer(req);
    
            try {
              event = stripe.webhooks.constructEvent(
                buf,
                signature,
                process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET
              );
    ...
    

    [0]https://nextjs.org/docs/api-routes/api-middlewares#custom-config

    【讨论】:

    • 对不起。我实际上将 bodyParser 设置为 false。不在我提供的代码中。而且我也尝试过使用微缓冲区。结果还是一样。
    • 所以我在 Stripe 仪表板中创建了 webhook。它达到了我的 API 点。我点击 webhook 中的“Signing Secret”来获取秘密“whsec_...”,这一切都是在 Stripe 测试下完成的。不直播。所以 req.body 位于端点,标头中的条带签名和我的 webhook 秘密但我无法通过 stripe.webhooks.constructEvent()
    • 用我正在尝试的新代码更新问题。结果相同。
    • 我已尝试运行您拥有的第二个示例,它适用于我。您可能要检查的下一件事是您的密钥和 webhook。我建议在运行 stripe.webhooks.constructEvent 方法之前将它们记录到您的控制台中,以确保它们匹配。即密钥应该看起来像 sk_test_.... 并且应该来自与您检索 webhook 密钥相同的 Stripe 帐户
    • 我重新创建了我的钩子,我得到 req.body 为未定义。其他一切都很好。
    猜你喜欢
    • 1970-01-01
    • 2019-06-18
    • 2022-01-18
    • 2015-04-18
    • 1970-01-01
    • 2017-10-03
    • 2021-01-14
    • 2018-09-18
    • 2021-11-28
    相关资源
    最近更新 更多