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

时间:2018-12-22 21:17:44

标签: google-cloud-platform google-cloud-functions stripe-payments

我有一个调用Firebase函数的条纹Webhook。在此功能中,我需要验证此请求是否来自Stripe服务器。这是代码:

-module(collatzMaps).

-export([start/2, s/4]).

collatz(0, Map) -> 
    {0, Map};
collatz(M, Map) ->

    Exists = maps:is_key(M, Map),
    case Exists of    
        false ->

            case M rem 2 == 0 of
                true ->
                    Result = collatz(M div 2, Map),
                    Val = (1 + element(1, Result)),
                    Map1 = maps:put(M, Val, element(2, Result)),
                    {maps:get(M, Map1), Map1};

                false ->
                    Result = collatz((3 * M + 1), Map),
                    Val = (1 + element(1, Result)),
                    Map2 = maps:put(M, Val, element(2, Result)),
                    {maps:get(M, Map2), Map2}
            end;
        true ->

            {maps:get(M, Map), Map}
    end.

s(N, M, Max, Map) ->

    if
        N =< M ->

            Result = collatz(N, Map),
            if
                element(1, Result) > Max ->
                    NextMax = element(1, Result),
                    MapNext = element(2, Result),
                    s(N + 1, M, NextMax, MapNext);
                true ->
                    MapNext = element(2, Result),
                    s(N + 1, M, Max, MapNext)
            end;
        true ->
            Max
    end.

start(N, M)->

    statistics(runtime),
    statistics(wall_clock),
    Map = maps:new(),
    Map1 = maps:put(1, 1, Map),
    G = s(N, M, 0, Map1),
    {_, Time2} = statistics(wall_clock),
    U2 = Time2 / 1000,
    io:format("~p seconds~n", [U2]),
    G.

Stripe Documentation中所述,我必须使用原始主体来执行此安全检查。

我尝试使用当前代码和:

const functions = require('firebase-functions');
const bodyParser = require('body-parser');
const stripe = require("stripe")("sk_test_****");
const endpointSecret = 'whsec_****';
const app = require('express')();

app.use(bodyParser.json({
    verify: function (req, res, buf) {
        var url = req.originalUrl;
        if (url.startsWith('/webhook')) {
            req.rawBody = buf.toString()
        }
    }
}));

app.post('/webhook/example', (req, res) => {
    let sig = req.headers["stripe-signature"];

    try {
        console.log(req.bodyRaw)
        let event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
        console.log(event);
        res.status(200).end()

        // Do something with event
    }
    catch (err) {
        console.log(err);
        res.status(400).end()
    }
});

exports.app = functions.https.onRequest(app);

但是我总是会收到此错误:

app.use(require('body-parser').raw({type: '*/*'}));

8 个答案:

答案 0 :(得分:5)

这是对我有用的东西

添加此行:

app.use('/api/subs/stripe-webhook', bodyParser.raw({type: "*/*"}))

在此行之前:

app.use(bodyParser.json());

(这不会影响您的所有操作,只是这样:'/ api / subs / stripe-webhook')

然后:

const endpointSecret = 'whsec_........'

const stripeWebhook = async (req, res) => {
    const sig = req.headers['stripe-signature'];

    let eventSecure = {}
    try {
        eventSecure = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
        //console.log('eventSecure :', eventSecure);
    }
    catch (err) {
        console.log('err.message :', err.message);
        res.status(400).send(`Webhook Secure Error: ${err.message}`)
        return
    }
    res.status(200).send({ received: true });
}

答案 1 :(得分:3)

云功能自动parses body content of known types。如果您要获取JSON,则说明它已经解析并且可以在req.body中使用。您不需要添加其他主体解析中间件。

如果您需要处理原始数据,则应使用req.rawBody,但我认为您不需要在此处进行处理。

答案 2 :(得分:2)

2021 - 解决方案

我遇到了那个错误,经过大量研究后,我无法轻松找出问题所在,但最终我可以根据以下架构来解决:

//App.js

this.server.use((req, res, next) => {
  if (req.originalUrl.startsWith('/webhook')) {
    next();
  } else {
    express.json()(req, res, next);
  }
});
//routes.js

routes.post(
  '/webhook-payment-intent-update',
  bodyParser.raw({ type: 'application/json' }),

  //your stripe logic (Im using a controller, but wherever)
  (req, res) => {
    stripe.webhooks.constructEvent(...)
  }
)

需要注意的两大警告:

  • 确保发送 req.headers['stripe-signature']
  • 确保您的 endpointSecret 是正确的,否则它仍然会报同样的错误

提示:

  • 通过安装 Stripe CLI 在本地进行测试:https://stripe.com/docs/webhooks/test

  • 在条带控制面板上验证您的密钥,或者您也可以通过验证条带日志来确定您是否拥有正确的密钥,如下所示:

webhook secret key example

希望对你有帮助。 :)

答案 3 :(得分:1)

以下是对我有用的代码:

    app.use(bodyParser.json({
    verify: function (req, res, buf) {
      var url = req.originalUrl;
      if (url.startsWith('/stripe'))
        req.rawBody = buf.toString();
    }
  }));

然后通过req.rawBody进行验证

stripe.checkWebHook(req.rawBody, signature);

引用:https://github.com/stripe/stripe-node/issues/341

答案 4 :(得分:1)

我能够从一个Webhook中获取数据,但不能从另一个Webhook中获取数据:问题是我使用的密钥与用于第一个Webhook的密钥相同,但是我发现每个Webhook都有不同的信息密钥,这就是我收到相同消息的方式。

答案 5 :(得分:0)

在我将Firebase云功能重命名后,从Stripe仪表板发送测试Webhook时,这发生了。我的所有其他功能都工作正常。通过在终端中重新设置解决 firebase函数:config:set stripe.webhook_signature =“您的Webhook签名机密” (如果您正在使用的话)并重新部署功能 firebase deploy --only功能

第二次,我通过在条纹仪表板中滚动条纹签名解决了该问题。

答案 6 :(得分:0)

// Use JSON parser for all non-webhook routes
app.use(
  bodyParser.json({
    verify: (req, res, buf) => {
      const url = req.originalUrl;
      if (url.startsWith('/api/stripe/webhook')) {
        req.rawBody = buf.toString();
      }
    }
  })
);

上面的代码对于上面的答案看起来很好。但即使是我也犯了一个错误。放同样的东西后,我得到了同样的错误。

最后,我发现如果您在 rawBody 代码下方配置了 body-parser,它就会起作用。

像这样

// Use JSON parser for all non-webhook routes
app.use(
  bodyParser.json({
    verify: (req, res, buf) => {
      const url = req.originalUrl;
      if (url.startsWith('/api/stripe/webhook')) {
        req.rawBody = buf.toString();
      }
    }
  })
);
// Setup express response and body parser configurations
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

希望对某人有所帮助。

答案 7 :(得分:0)

请使用此脚本

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