php 在Node.JS上匹配WooCommerce WebHook签名的问题

3ks5zfa0  于 2023-09-29  发布在  PHP
关注(0)|答案(2)|浏览(145)

我试图在我的Node.js网站上验证WooCommerce的webhook交易。但是,我不能让两个字符串匹配。
我可以看到php签名是用下面的代码生成的,源代码可以在这里查看WooCommerce Source。

base64_encode( hash_hmac( $hash_algo, $payload, $this->get_secret(), true ) ));

我注意到,如果我在hash_hmac上关闭true,我可以让两个系统创建一个匹配,但是我宁愿不编辑WooCommerce的核心,所以我想知道是否有什么我错过了这里?
对于我的例子,我没有编辑核心,并迫使有效载荷如下,只是这样我就可以很容易地尝试和匹配2个系统

payload = '{"id":1,"etc":2,"host":"http:/\/localhost\/view-order\/8"}'
secret = 'welcome'

我在Node.js中的代码如下。

var crypto = require('crypto');    

hmac = crypto.createHmac('sha256', secret);
hmac.setEncoding('binary');
hmac.write(payload);
hmac.end();
hash = hmac.read();

result = base64.encode(hash);

console.log(result);

如果我从“主机”JSON中删除URL,那么它就可以工作,这与它被转义的方式有关吗?我认为这可能是PHP和node执行SHA256哈希的方式的问题。我真的不知道该怎么解决这个问题。

任何帮助都会很好,
谢谢

jbose2ul

jbose2ul1#

我也遇到过类似的问题,使用这里建议的代码:SHA256 webhook signature from WooCommerce never verifies

var processWebHookSignature = function (secret, body, signature) {
  signatureComputed = crypto.createHmac('SHA256', secret)
  .update(new Buffer(JSON.stringify(body), 'utf8'))
  .digest('base64');

  return ( signatureComputed === signature ) ? true : false;
}

(其中主体来自请求主体)。
当我改变了我获得原始身体的方式时,这才开始对我起作用。我使用bodyParser中间件得到了它:
app.use(bodyParser.json({verify:function(req,res,buf){req.rawBody=buf}}))
(As解释在:https://github.com/expressjs/body-parser/issues/83#issuecomment-80784100)
所以现在不用new Buffer(JSON.stringify(body), 'utf8'),而用req.rawBody
我希望这也能解决你的问题。

epfja78i

epfja78i2#

延伸@genau的回答:

**你可能会问,为什么会出现这种情况!?**几乎所有人都在我们的express应用程序中添加了以下代码,该代码操作了实际的req.body,导致在验证哈希签名时出现问题。

app.use(express.json());

如何处理这个问题?

将原始req.body添加到新字段(例如:req.rawBody),并在验证签名时使用此字段而不是req.body

// This code will copy the req.body data to req.rawBody
app.use(
  express.json({
    verify: function (req, res, buf) {
      req.rawBody = buf;
    },
  })
);

稍后,您可以验证签名,如下所示:

function requestHandler (req, res) {
    const incomingSignature = req.headers["x-wc-webhook-signature"]; // modify this accordingly
    const payload = req.rawBody; // Buffer, already, no need to stringify.

    const calculatedSignature = crypto
        .createHmac("sha256", "your-secret-key")
        .update(payload)
        .digest("base64");

    const isValid = calculatedSignature === incomingSignature;
  
    // ...
}

谢谢你,谢谢

相关问题