2

I am attempting to a validate the webhook transaction from WooCommerce on my Node.js website. However I cannot get the 2 strings to match.

I can see that the php signature is generated with the following code, and the source can be viewed here WooCommerce Source.

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

I have noticed that if i turn off true on the hash_hmac, I can then get the 2 systems to create a match, however I would rather not edit the core of WooCommerce so I am wondering if there is something I am missing here?

For my Example I did edit the core and forced the payload to be the following, just so i could easily try and match the 2 systems

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

My code in Node.Js is the following.

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);

If I remove the url from the "host" JSON then it does work, is it something to do with the way it has been escaped? I think it may be an issue with the way PHP and node do the SHA256 hashing. I really can't workout exactly how to solve this.

Any help would be great,

Thanks

shaune
  • 1,020
  • 8
  • 12
  • did you eventually figure this out? I'm still working on getting an order update webhook to fire properly, and after that I suspect I'll run into this problem. – fortuneRice Jan 26 '17 at 16:28
  • I never resolved the miss matching crypto properly, I ended up modifying the way woo commerce creates the hash in it's core, not the best solution as I need to update this every time woo updates... If you have manage to get the 2 to be synced natively, i'd love to see the code! – shaune Jan 26 '17 at 23:04
  • @fortuneRice Did you have any luck? – shaune Mar 07 '17 at 07:35
  • I had to put that project on hold so I'm not at that stage yet. – fortuneRice Mar 07 '17 at 07:38

1 Answers1

4

I have run into a similar issue as you, using the code suggested here: 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;
}

(Where body comes from req.body).

This only started working for me when I changed the way I obtain the raw body. I got it using the bodyParser middleware:
app.use(bodyParser.json({verify:function(req,res,buf){req.rawBody=buf}}))
(As explained in: https://github.com/expressjs/body-parser/issues/83#issuecomment-80784100)

So now instead of using new Buffer(JSON.stringify(body), 'utf8') I just use req.rawBody
I hope this solves your problems too.

genau
  • 184
  • 1
  • 5
  • 16