Next.js 13 + Stripe 请求签名验证失败求助
Stripe Webhook签名验证失败求助
错误信息
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
环境信息
- Next.js 13.3.2
- Stripe SDK 12.4.0
复现步骤
- 创建端点
/pages/api/p/test,代码如下:
import Stripe from 'stripe'; import { NextApiRequest, NextApiResponse } from 'next'; import safe from 'colors/safe'; import { buffer } from 'micro'; const handler = async ( req: NextApiRequest, res: NextApiResponse ): Promise<void> => { const stripe = new Stripe(process.env.STRIPE_SECRET as string, { apiVersion: '2022-11-15', }); const webhookSecret: string = "whsec_33244...."; if (req.method === 'POST') { const sig = req.headers['stripe-signature'] as string; const buf = await buffer(req); const body = buf.toString(); let event: Stripe.Event; try { console.log(safe.bgGreen(body)) event = stripe.webhooks.constructEvent(body, sig, webhookSecret); } catch (err) { // On error, log and return the error message console.log(`❌ Error message: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); return; } // Successfully constructed event console.log('✅ Success:', event.id); // Cast event data to Stripe object if (event.type === 'payment_intent.succeeded') { const stripeObject: Stripe.PaymentIntent = event.data .object as Stripe.PaymentIntent; console.log(`💰 PaymentIntent status: ${stripeObject.status}`); } else if (event.type === 'charge.succeeded') { const charge = event.data.object as Stripe.Charge; console.log(`💵 Charge id: ${charge.id}`); } else { console.warn(`🤷♀️ Unhandled event type: ${event.type}`); } // Return a response to acknowledge receipt of the event res.json({ received: true }); } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } }; export const config = { api: { bodyParser: false, }, }; export default handler;
- 启动开发服务器和Stripe监听器:
stripe listen --forward-to localhost:3000/api/p/test
- 复制生成的webhook签名密钥并粘贴到代码中
- 触发模拟事件:
stripe trigger payment_intent.succeeded
已尝试的解决方案
- 使用micro包的
buffer获取原始请求体 - 手动验证HMAC签名
- 参照Stripe文档示例实现buffer函数
请求体解析情况
日志显示请求体解析正常,内容如下:
{ "id": "evt_3NIzhvEcQkKxoTiV1xjEMh02", "object": "event", "api_version": "2022-11-15", "created": 1686772219, "data": { "object": { "id": "pi_3NIzhvEcQkKxoTiV1kuXEmH6", "object": "payment_intent", "amount": 2000, "amount_capturable": 0, "amount_details": { "tip": { } }, "amount_received": 0, "application": null, "application_fee_amount": null, "automatic_payment_methods": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "client_secret": "pi_3NIzhvEcQkKxoTiV1kuXEmH6_secret_ZRnfaga3uRF5EhNXE0KwZpDpp", "confirmation_method": "automatic", "created": 1686772219, "currency": "usd", "customer": null, "description": "(created by Stripe CLI)", "invoice": null, "last_payment_error": null, "latest_charge": null, "livemode": false, "metadata": { }, "next_action": null, "on_behalf_of": null, "payment_method": null, "payment_method_options": { "card": { "installments": null, "mandate_options": null, "network": null, "request_three_d_secure": "automatic" } }, "payment_method_types": [ "card" ], "processing": null, "receipt_email": null, "review": null, "setup_future_usage": null, "shipping": { "address": { "city": "San Francisco", "country": "US", "line1": "510 Townsend St", "line2": null, "postal_code": "94103", "state": "CA" }, "carrier": null, "name": "Jenny Rosen", "phone": null, "tracking_number": null }, "source": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "requires_payment_method", "transfer_data": null, "transfer_group": null } }, "livemode": false, "pending_webhooks": 2, "request": { "id": "req_MfPOwrw4MZsykJ", "idempotency_key": "10108c32-75db-4e1e-abb3-b3b2673df025" }, "type": "payment_intent.created" }
求助
已查阅大量资料并尝试多种方法,仍无法解决签名验证失败问题,恳请提供排查思路。
内容的提问来源于stack exchange,提问作者Designly
相关产品推荐
相关产品推荐

