Stripe webhook 错误:未找到与有效负载的预期签名匹配的签名

Posted

技术标签:

【中文标题】Stripe webhook 错误:未找到与有效负载的预期签名匹配的签名【英文标题】:Stripe webhook error: No signatures found matching the expected signature for payload 【发布时间】:2019-11-10 23:02:26 【问题描述】:

我正在使用 Stripe 提供的代码来测试 webhook。 Stripe 密码和端点密码已经过三重检查。

条纹版本:6.19 正文解析器:1.19

当我在 Stripe 仪表板上测试 webhook 时,我得到了结果:(测试 webhook 错误:400)没有找到与有效负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求正文?

任何帮助将不胜感激。

var bodyParser - require('body-parser);


// Using Express
const app = require('express')();

app.use(bodyParser.urlencoded( extended: false ));
app.use(bodyParser.json());


// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
const stripe = require('stripe')('sk_test_VPw...');

// Find your endpoint's secret in your Dashboard's webhook settings
const endpointSecret = 'whsec_...';


// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw(type: 'application/json'), (request, response) => 
  const sig = request.headers['stripe-signature'];

  let event;

  try 
    event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret); //NOT WORKING!
   catch (err) 
    return response.status(400).send(`Webhook Error: $err.message`);
  

  // Handle the checkout.session.completed event
  if (event.type === 'checkout.session.completed') 
    const session = event.data.object;

    // Fulfill the purchase...
    handleCheckoutSession(session);
  

  // Return a response to acknowledge receipt of the event
  response.json(received: true);
);

【问题讨论】:

Stripe Error: No signatures found matching the expected signature for payload的可能重复 【参考方案1】:

这通常是由于您在检查签名之前解析或修改了原始请求字符串(因此签名是根据修改后的字符串计算的,而不是根据 Stripe 发送的确切字符串)。在这种情况下,看起来 JSON express 中间件正在这样做: app.use(express.json());.

Stripe 有 an example 在 webhook 端点上使用原始 bodyParser 中间件,以便您的代码获取所需的原始字符串:

// Use JSON parser for all non-webhook routes
app.use((req, res, next) => 
  if (req.originalUrl === '/webhook') 
    next();
   else 
    express.json()(req, res, next);
  
);

// Stripe requires the raw body to construct the event
app.post('/webhook', express.raw(type: 'application/json'), (req, res) => 
  const sig = req.headers['stripe-signature'];

  let event;

  try 
    event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
   catch (err) 
    // On error, log and return the error message
    console.log(`❌ Error message: $err.message`);
    return res.status(400).send(`Webhook Error: $err.message`);
  

  // Successfully constructed event
  console.log('✅ Success:', event.id);

  // Return a response to acknowledge receipt of the event
  res.json(received: true);
);

【讨论】:

谢谢!这就是给我的。我为 webhook 使用了相同的 express app,但该应用程序使用的是上述 json 中间件。【参考方案2】:

一个衬垫加上没有弃用的 bodyParser。确保在通用解析器 aka express.json() 之前定义端点解析器。

app.use('/stripe/webhook', express.raw(type: "*/*"))
app.use(express.json())

【讨论】:

挣扎了2天,你救了我。谢谢。 谢谢,这正是我所需要的。 (并且不使用已弃用的 bodyParser)【参考方案3】:

如何在 Express 中获取解析后的正文和原始正文:

app.use(bodyParser.json(
  verify: (req, res, buf) => 
    req.rawBody = buf
  
))

感谢: https://flaviocopes.com/express-get-raw-body/

【讨论】:

【参考方案4】:

对于那些使用 NextJS 的人。这是我在 Reddit 上遇到的一个解决方案 @ u/SiMFiCysed https://www.reddit.com/user/SiMFiCysed/

【讨论】:

以上是关于Stripe webhook 错误:未找到与有效负载的预期签名匹配的签名的主要内容,如果未能解决你的问题,请参考以下文章

无法将数据从 Stripe webhook 发送到 Firebase

NextJS Stripe Webhook 原始正文

Stripe webhook 测试在控制器中引发错误

条带错误:未找到与有效负载的预期签名匹配的签名

使用 Stripe Firebase 扩展 Webhook 运行订阅付款未触发

Firebase Cloud Functions - Stripe Connect Webhook 未触发