如何使用stymiee/authnetjson调试无效的Authorize.net Webhook负载
我来帮你一步步排查这个Webhook验证失败的问题,咱们从几个关键环节入手:
确认签名密钥完全匹配
首先要确保你使用的签名密钥和Authorize.net后台设置的完全一致——包括大小写、特殊字符,甚至末尾有没有多余的空格。这个密钥是验证的核心,哪怕差一个字符都会导致失败。你可以把密钥复制到纯文本编辑器里,和后台的密钥逐字符对比,避免复制粘贴时带进来的隐形字符问题。检查请求体的完整性和原始性
你用file_get_contents("php://input")获取请求体时,要确保这段代码执行前,没有任何其他代码(比如框架的请求解析中间件)读取过php://input——这个流只能读取一次,重复读取会导致获取到空内容或不完整的payload。
可以在获取payload后立刻把它写入日志,方便对比:error_log("Received payload: " . $payload);然后检查日志里的payload和你收到的示例是否完全一致,包括空格、引号、逗号这些细节——Authorize.net的签名是基于原始请求体生成的,任何修改都会导致验证失败。
验证请求头的正确提取
用getallheaders()获取请求头时,要注意在某些服务器环境(比如FastCGI)下,键名可能会被转换,比如X-ANET-Signature变成HTTP_X_ANET_SIGNATURE。
可以把获取到的headers也写入日志:error_log("Received headers: " . print_r($headers, true));查看日志里是否存在正确的
X-ANET-Signature键,以及对应的签名值是否和示例完全一致。如果键名不对,你可以手动指定键名:$signatureHeader = isset($headers['X-ANET-Signature']) ? $headers['X-ANET-Signature'] : $headers['HTTP_X_ANET_SIGNATURE'];然后把这个值单独处理,再传给AuthnetWebhook。
手动计算签名进行对比
为了确认库的验证逻辑是否正常,你可以手动计算签名和请求头里的签名对比:- 用HMAC-SHA512算法,以你的签名密钥为密钥,原始请求体为消息生成哈希值
- 把哈希值转换成大写十六进制字符串
- 和请求头里
sha512=后面的部分对比
手动计算的代码示例:
$computedSignature = strtoupper(hash_hmac('sha512', $payload, $signature_key)); $expectedSignature = str_replace('sha512=', '', $headers['X-ANET-Signature']); error_log("Computed signature: " . $computedSignature); error_log("Expected signature: " . $expectedSignature);如果这两个值不一致,说明问题出在签名密钥或请求体上;如果一致,那可能是库的使用方式或版本有问题。
检查库的版本和兼容性
确认你使用的stymiee/authnetjson库是最新版本,旧版本可能存在Webhook验证的bug。可以通过Composer更新:composer update stymiee/authnetjson另外,查看库的文档确认构造函数参数顺序是否正确——你的代码顺序
$signature_key, $payload, $headers是对的,但移除$headers后,库可能会尝试从全局变量获取请求头,这在某些环境下可能失效。用测试用例验证代码逻辑
可以用库测试用例里的示例payload和签名密钥来验证你的代码是否能正常工作。如果测试用例能通过验证,说明你的代码逻辑没问题,问题可能出在沙箱环境的请求传输环节。
内容的提问来源于stack exchange,提问作者nfvindaloo

