well, there are no difference between the hmac's in both php and node.js .
this is the normal behavior for the two pieces of codes your provided.
in your php you are packing
your $hmacKey
the step which is not exists in your node side;
in all the next examples i will use 123456
as hmac key and yello
as a data string
for example :
php without packing :
$merchantSig = base64_encode(hash_hmac('sha256',$signData, $hmacKey,true));
echo $merchantSig; // output : gKjrFq1nrRP33vGiAK9V1Z5bLX5EFZhcfy2flRIGPEI=
node.js without packing :
let h = crypto.createHmac('sha256', hmacKey).update(keyString).digest('base64');
console.log(h); // output : gKjrFq1nrRP33vGiAK9V1Z5bLX5EFZhcfy2flRIGPEI=
now let's pack the both :
php with packing :
$merchantSig = base64_encode(hash_hmac('sha256',$signData,pack("H*" , $hmacKey),true));
echo $merchantSig; // output : Y8D5crzxQfFkwQn1OJHeZTS1KVuTH0y7qLuxyetE0TY=
node.js with packing here is the trick
var h = crypto.createHmac('sha256', hmacKey.packHex()).update(keyString).digest('base64');
// ^^^^^^^^^
console.log(h); // output : Y8D5crzxQfFkwQn1OJHeZTS1KVuTH0y7qLuxyetE0TY=
Update
Here is some online tests for both php & nodejs in the two cases (using pack-without using pack)
php : https://3v4l.org/HCt4g
nodejs : http://rextester.com/YNNWN69327
here is another tests with another keys and strings . for php :
https://3v4l.org/JKdNk
and node.js
http://rextester.com/RXGM49887 ,