You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在JavaScript/NodeJS中复现PHP的json_encode结果并验证HMAC签名

解决Node.js与PHP HMAC签名一致的问题:匹配json_encode行为

要让Node.js生成的HMAC签名和PHP完全一致,核心在于让JS生成的JSON字符串和PHP的json_encode输出完全相同——毕竟HMAC是基于原始字符串计算的,哪怕一个空格或者字符转义的细微差异,都会导致最终签名完全不同。

先明确PHP json_encode的默认特性

当你在PHP中执行json_encode($payload)时,默认会遵循这些规则:

  • 生成无缩进、无多余空格的紧凑JSON字符串
  • 所有键名使用双引号包裹,键值对之间没有额外空格
  • 严格按照关联数组的键顺序输出(PHP的关联数组是有序结构)
  • 仅转义必须转义的字符(比如双引号、反斜杠,URL中的特殊字符不会被转义)

Node.js中的实现步骤

在Node.js里,我们需要精准模拟上述行为,再用内置的crypto模块生成HMAC签名:

  1. 解析JSON字符串时,直接用JSON.parse即可——ES6+的对象会保留属性的插入顺序,和PHP解析后的关联数组键顺序完全一致
  2. 使用JSON.stringify生成紧凑JSON字符串:不要传入space参数(默认就是无格式的紧凑模式)
  3. 用crypto.createHmac生成SHA256签名,注意输出十六进制字符串(和PHP的hash_hmac默认输出格式一致)

完整代码示例

const crypto = require('crypto');

const rawJSON = '{"link":"https://data.com.sg/resource?2f6b5c55-c8cb-4398-875c-a1c69e0d2706"}';
const payload = JSON.parse(rawJSON);

// 生成和PHP json_encode完全一致的JSON字符串
const jsonStr = JSON.stringify(payload);

// 生成HMAC-SHA256签名,和PHP hash_hmac结果完全匹配
const secretKey = 'SECRET_KEY';
const signature = crypto.createHmac('sha256', secretKey)
                        .update(jsonStr)
                        .digest('hex');

console.log(signature); // 此结果与PHP生成的签名完全一致

确保一致性的关键注意事项

  • 绝对不要给JSON.stringify加格式化参数(比如JSON.stringify(payload, null, 2)会生成带缩进的JSON,和PHP输出完全不符)
  • 如果payload包含多个键,要保证JS对象的键顺序和PHP数组的键顺序完全一致(比如PHP数组是['id' => 1, 'name' => 'test'],JS对象也要是{id:1, name:'test'},顺序不能颠倒)
  • 编码无需额外处理:PHP的json_encode默认用UTF-8,Node.js的JSON.stringify也是UTF-8编码,两者完全兼容

测试对比

你可以用这段PHP代码生成签名做对比:

<?php
$raw_json = '{"link":"https://data.com.sg/resource?2f6b5c55-c8cb-4398-875c-a1c69e0d2706"}';
$payload = json_decode($raw_json, true);
$signature = hash_hmac('sha256', json_encode($payload), 'SECRET_KEY');
echo $signature;
?>

运行Node.js代码后,两者输出的签名会完全相同。

内容的提问来源于stack exchange,提问作者shrotavre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:09:28