如何从环回自定义方法中检索原始正文缓冲区以验证来自 webhook POST 的条带签名?

How can I retrieve raw body buffer from loopback custom method to verify stripe signature from webhook POST?

按照指南进行操作:https://stripe.com/docs/webhooks/signatures#verify-official-libraries

我已经在环回自定义方法中尝试过这段代码:

    "use strict";
module.exports = function(Webhook) {
  Webhook.stripe = function(req, data, cb) {
    const stripe = require("stripe")("sk_test_xxxxxxxxxxxxx");
    const endpointSecret = "whsec_xxxxxxxxxxxxxxxxxxxxxxxxx";

    const sig = req.headers["stripe-signature"];

    let event;

    try {
      event = stripe.webhooks.constructEvent(data, sig, endpointSecret);
      Webhook.create({
        data: data
      }); 
      console.log("Success");
      cb(null, "OK");
    } catch (err) {
      console.log(err);
      Webhook.create({
        data: err 
      }); 
      cb(err);
    }   
  };  

  Webhook.remoteMethod("stripe", {
    accepts: [
      { arg: "req", type: "object", http: { source: "req" } },
      { arg: "data", type: "object", http: { source: "body" } } 

    ],  
    returns: [{ arg: "response", type: "any", root: true }]
  }); 
};

但是在stripe.webhooks.constructEvent中验证签名时,传入正文的数据对象是行不通的,因为它不需要对象,它想要原始的未编辑的正文。 (JSON.Stringify() 也不起作用,因为这会改变正文并且验证失败)我怎样才能从回送中获取未经编辑的原始正文以传递到条带库中进行签名验证?

感谢来自 https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/loopbackjs/I2LK5gOkP_4/rn73-B0ABwAJ 的 Felipe Figueroa 的回答。

body-parser 将根据内容类型根据正文解析器类型(在本例中为 json 或原始)解析传入请求。您不能将原始解析器和 json 解析器都设置为按顺序应用

为了解决这个问题,我们可以从中间件中删除 bodyParser.json 并在 server.js

中手动配置它

由于我们需要原始主体但也需要转换后的 JSON,我们可以在 JSON 解析器激活之前向请求对象添加一个额外的 属性,如下所示:

在 middleware.json:

"parse": {
    "body-parser#json": {"params": {"limit": "10mb", "strict": false}}, // remove this line
    "body-parser#urlencoded": {
      "params": {
        "extended": true,
        "limit": "5mb"
      }
    }

在server.js中:

function rawBodySaver(req, res, buf, encoding) {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || 'utf8'); // additional property set on req object
  }
}

const bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '10mb', strict: false, verify: rawBodySaver}));

然后在上面的代码中我们将使用:

event = stripe.webhooks.constructEvent(req["rawBody"], sig, endpointSecret);

然后签名验证正确。