支付平台后台显示回调已送达,Magento 却每次记录 signature mismatch。最关键的证据不是解析后的数组,而是应用收到的原始字节。
一次失败回调要保留什么
- 请求 ID、到达时间和来源 IP;
- 签名头名称与算法版本;
- 原始 body 的 SHA-256,仅在安全环境短期保留脱敏样本;
- 用于签名的时间戳;
- 代理是否解压、改写或转换编码。
不要在日志中输出密钥、完整银行卡数据或未经脱敏的请求体。
常见错误是先 json_decode(),业务处理后再 json_encode() 去算 HMAC。键顺序、斜杠、空白和 Unicode 转义任何一个变化,摘要都不同。签名必须用框架读取到的原始 body 按支付平台规定拼接。
$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($expected, $received)) {
throw new LocalizedException(__('Invalid signature.'));
}
示例中的拼接格式只是结构说明,实际必须严格使用该支付平台当前协议。
验证通过也不能直接处理两次
校验时间戳允许窗口,保存 event ID 并做唯一约束。平台重试同一事件时应返回成功但不重复开票、发货或改状态。密钥轮换期间可同时验证新旧密钥,但必须记录命中哪一把,并在窗口结束后移除旧密钥。
最终用官方测试事件验证:正常签名成功、改一个字节失败、过期时间戳失败、同一 event 重放不产生第二次业务动作。

