我能够通过内置 Stripe 页面成功结帐我的购物车,并且我会被重定向到我的 successUrl 路线。我的本地测试 webhook 正在按预期被调用。但是,当我包含代码来验证请求是否来自 Stripe 时,我收到一些错误。
这是我在 NextJS 中的 webhook
import { stripe } from "@/lib/stripe"
export async function POST(req: Request){
const payload = await req.json()
const sig = req.headers.get('stripe-signature') as string
console.log("sig: ", sig)
let event;
const endpointSecret = process.env.WEBHOOK_SECRET_LOCAL as string
try {
console.log("constructing event...")
event = stripe.webhooks.constructEvent(payload, sig, endpointSecret)
} catch (error) {
console.error(error)
return new Response(`Webhook error: ${error}`, {
status: 400,
})
}
return new Response("payment confirmation route received", {
status: 200,
})
}
我正在使用 Stripe CLI 监听成功事件stripe listen --forward-to localhost:3000/api/checkout/payment-confirmation
检查完我的购物车后,我发现...
2023-03-23 15:51:28 --> checkout.session.completed [evt_1MowyjE7TMviQOgJNbXch10w] 2023-03-23 15:51:28 --> charge.succeeded [evt_3MowyhE7TMviQOgJ09e3Q7Hu] 2023-03-23 15:51:29 --> payment_intent.succeeded [evt_3MowyhE7TMviQOgJ0OIjeNoH] 2023-03-23 15:51:29 --> payment_intent.created [evt_3MowyhE7TMviQOgJ0ovhouJM] 2023-03-23 15:51:32 <-- [400] POST http://localhost:3000/api/checkout/payment-confirmation [evt_3MowyhE7TMviQOgJ09e3Q7Hu] 2023-03-23 15:51:32 <-- [400] POST http://localhost:3000/api/checkout/payment-confirmation [evt_3MowyhE7TMviQOgJ0OIjeNoH] 2023-03-23 15:51:32 <-- [400] POST http://localhost:3000/api/checkout/payment-confirmation [evt_1MowyjE7TMviQOgJNbXch10w] 2023-03-23 15:51:32 <-- [400] POST http://localhost:3000/api/checkout/payment-confirmation [evt_3MowyhE7TMviQOgJ0ovhouJM]
从 NextJS 中我看到......
StripeSignatureVerificationError: Webhook payload must be provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead. Signature verification is impossible without access to the original signed material. Learn more about webhook signing and explore webhook integration examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing
我认为这意味着我需要以某种方式修改有效负载参数。我试过payload.toString()
, JSON.stringify(payload)
, using const buf = Buffer.from(payload)
以及其他各种事情,认为我需要以某种方式将该对象转换为字符串或缓冲区,但我不理解这个问题。非常感谢帮助!
- 更新 -
现在我已经更新了代码,但我仍然收到一般错误......
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
我对 Stripe 的回应:“我的意思是,我认为是这样?!?”
我还尝试导入“micro”或“raw-body”,正如我看到其他人使用的那样,但它们会给我带来各种错误,这就是为什么我使用来自 node.js 的错误。 req.body 是一个 ReadableStream,
类型为“ReadableStream |”的参数null' 不可分配给'string | 类型的参数缓冲'
???? 如果我尝试将其作为构造事件中的第一个参数传递。
import { stripe } from "@/lib/stripe"
import { NextRequest } from "next/server";
import { Buffer } from "node:buffer";
export async function POST(req: NextRequest){
const buf = Buffer.from(req.toString())
// <Buffer 5b 6f 62 6a 65 63 74 20 52 65 71 75 65 73 74 5d>
const headers = req.headers
const sig = req.headers.get("stripe-signature") as string | string[]
// t=1679...,v1=888050e17...,v0=cc9b94a...
let event;
const endpointSecret = process.env.WEBHOOK_SECRET_LOCAL as string
// whsec_...
try {
console.log("constructing event...")
event = stripe.webhooks.constructEvent(buf, sig, endpointSecret)
} catch (error) {
console.error(error)
return new Response(`Webhook error: ${error}`, {
status: 400,
})
}
return new Response("payment confirmation route received", {
status: 200,
})
}
export const config = {
api: {
bodyParser: false,
},
};