$raw = file_get_contents('php://input');
$sign = $_SERVER['HTTP_X_SIGN'] ?? '';
$calc = hash_hmac('sha256', $raw, getenv('PAY_KEY'));
if (!hash_equals($calc, $sign)) { http_response_code(400); exit('fail'); }
回调接口的返回一直是 {code: 'SIGN ERROR'},渠道侧显示通知失败重试 6 次。同一份代码在测试环境跑得好好的,换到线上第一条就挂。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,配置文件里 merchant_key 还留着沙箱那串 32 位字符串,线上渠道用的是另一套商户密钥,HMAC-SHA256 算出来的摘要自然对不上。部署脚本只替换了数据库配置,密钥这项被漏掉。
「沙箱密钥误用」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。
处理上按这个顺序:把密钥从代码里挪到环境变量,沙箱和生产的键名分开,部署时按环境注入;验签前按渠道文档的字段顺序拼待签串,顺序错一样过不了;加一条启动自检,用固定报文算一次签名与预期值比对,启动日志里就能看出用的哪套密钥。
改完只确认一件事:线上发一条模拟通知返回 success,日志里打印的密钥后缀与渠道后台一致。
