NextJS Stripe Webhook 原始正文
Posted
技术标签:
【中文标题】NextJS Stripe Webhook 原始正文【英文标题】:NextJS Stripe Webhook Raw Body 【发布时间】: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);
【问题讨论】:
【参考方案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 为未定义。其他一切都很好。以上是关于NextJS Stripe Webhook 原始正文的主要内容,如果未能解决你的问题,请参考以下文章
Stripe Connect Express Webhook - 如何在用户完成 Stripe Connect Express 表单并被重定向后触发 Stripe Webhook