Remix.run集成Stripe Webhook遇签名验证错误,求助
解决Remix.run中Stripe Webhook签名验证失败问题
问题根源
你碰到的No signatures found matching the expected signature for payload错误,核心原因是直接把Remix的request.body(ReadableStream类型)传给了Stripe的constructEvent方法。Stripe的签名验证依赖原始未修改的请求体字符串/Buffer——签名是基于Stripe发送的原生HTTP请求体计算的,流类型无法被正确用于验证逻辑。
解决方案
修改代码,先读取原始请求体文本,再传递给Stripe进行签名验证:
修正后的完整代码
import type { ActionFunction } from "@remix-run/node"; import Stripe from "stripe"; // 初始化Stripe实例(替换为你的密钥和对应API版本) const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: "2024-06-20", }); export const action: ActionFunction = async ({ request }) => { switch (request.method) { case "POST": { const endpointSecret = "whsec_abxxxxaf67fxxxa955"; // 确保是Stripe控制台的Webhook签名密钥 const sig = request.headers.get("stripe-signature"); if (!sig) { console.log("缺少Stripe签名请求头"); return new Response("Missing signature", { status: 400 }); } try { // 关键步骤:读取原始请求体文本 const rawBody = await request.text(); const event = stripe.webhooks.constructEvent( rawBody, sig, endpointSecret ); console.log("签名验证成功,事件内容:", event); // 在这里添加你的Webhook业务逻辑,比如根据event.type处理不同事件 return new Response("Success", { status: 200 }); } catch (err) { console.error("签名验证失败:", err); return new Response(`Webhook Error: ${(err as Error).message}`, { status: 400 }); } } default: return new Response("Method Not Allowed", { status: 405 }); } }; export default () => { return <p>Webhook Endpoint</p>; };
关键细节说明
- 读取原始请求体:必须用
request.text()获取Stripe发送的原生文本内容,绝对不能用request.json()——后者会解析请求体,破坏原始格式,直接导致签名验证失败。 - Stripe实例初始化:确保正确传入你的API密钥和对应版本,避免因版本不兼容引发其他问题。
- 签名头校验:增加对
stripe-signature头的存在性检查,提前拦截无效请求。
额外排查点
- 确认
endpointSecret是Stripe控制台中对应Webhook端点的签名密钥(不是API密钥),二者完全不同。 - 检查是否有自定义中间件提前解析了请求体,若有则需要跳过对该Webhook端点的body解析。
内容的提问来源于stack exchange,提问作者mrWiga
相关产品推荐
相关产品推荐

