You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stripe Webhook签名验证失败问题求助

解决Stripe Webhook签名验证错误:No signatures found matching the expected signature for payload

核心问题分析

你的代码存在关键错误:路由已经通过express.raw({ type: "application/json" })保留了Stripe发送的原始请求体(格式为Buffer),但后续又执行了JSON.stringify(req.body),这会把原始Buffer转换成完全不符合预期的字符串(例如{"type":"Buffer","data":[...]}),导致Stripe无法匹配签名。

Stripe的签名是基于它发送的原始HTTP请求体生成的,任何对请求体的修改(包括重新序列化、转义字符变化)都会直接导致签名验证失败。

修正方案

直接使用express.raw解析后的原始请求体,无需额外序列化操作:

修正后的Webhook处理函数

export const sessionUpdate = async (req, res) => {
  const sig = req.headers['stripe-signature'];
  const stripeInstance = Stripe(process.env.STRIPE_SECRET_KEY);
  let event;

  // 直接使用express.raw返回的原始请求体(constructEvent支持Buffer或字符串格式)
  const rawBody = req.body;

  try {
    event = stripeInstance.webhooks.constructEvent(rawBody, sig, process.env.ENDPOINT_SECRET);
  } catch (err) {
    console.error('Webhook Error:', err.message);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  if (!event || !event.type) {
    console.error('Invalid event data:', event);
    return res.status(400).json({ error: 'Invalid event data' });
  }

  console.log('Received event:', event.type);
  switch (event.type) {
    case 'checkout.session.completed':
      try {
        const completedEvent = event.data.object;
        const { metadata } = completedEvent;
        const { post_id } = metadata;

        const updatedPost = await Post.findByIdAndUpdate(
          post_id,
          { paymentStatus: true },
          { new: true }
        );

        if (!updatedPost) {
          return res.status(404).json({ error: 'Post not found' });
        }

        return res.json({ message: 'Post status updated successfully', updatedPost });
      } catch (error) {
        console.error('Error updating post status:', error);
        return res.status(500).json({ error: 'Internal server error' });
      }

    default:
      console.log(`Unhandled event type ${event.type}`);
      return res.status(200).end();
  }
};

补充验证点

  • 确认process.env.ENDPOINT_SECRET是Stripe Dashboard中Webhook端点的签名密钥(以whsec_开头),而非普通API密钥。
  • 检查是否有其他中间件(如body-parser的其他实例)在express.raw之前修改了请求体,确保express.raw是该路由的第一个处理中间件。
  • 使用Stripe CLI测试时,确认转发的本地地址与代码路由完全匹配,且没有额外代理层修改请求体。

内容的提问来源于stack exchange,提问作者Youssef KH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:02:46