Laravel中Xero Webhooks接收验证失败问题求助
Xero Webhook签名验证失败的解决方案
核心问题出在Webhook密钥的处理方式以及哈希函数的返回格式设置上,以下是具体修正方案:
错误原因拆解
- 你定义的
WEBHOOKKEY是Base64编码后的字符串,Xero要求使用解码后的原始字节作为HMAC密钥,直接用Base64字符串计算会导致哈希结果完全错误。 hash_hmac函数默认返回十六进制字符串,直接对其做Base64编码会得到比签名更长的结果;必须让它返回原始二进制数据,再进行Base64编码才能匹配Xero的签名格式。
修正后的代码
<?php namespace App\Http\Controllers\Xero; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class ContactsController extends Controller { const WEBHOOKKEY = '+3mCdl4IykKfH+Y9CZTy5TpvqB4ir3RsdwJmdpKXnR9xCTIQrKCQAKYii5IioTaujGYojiKfV7IUu7cywypuSg=='; public function index(Request $request) { $signature = $request->header('x-xero-signature'); // 1. 解码Base64格式的Webhook密钥为原始字节 $decodedKey = base64_decode(self::WEBHOOKKEY); // 2. 使用原始密钥计算HMAC-SHA256,第三个参数设为true返回二进制数据 $hmacBinary = hash_hmac('sha256', $request->getContent(), $decodedKey, true); // 3. 对二进制结果做Base64编码,得到与Xero签名格式一致的字符串 $hash = base64_encode($hmacBinary); if ($signature === $hash) { return response('OK', 200); } return response('Unauthorized', 401); } }
额外验证提示
- 确保请求体是原始未修改的:Laravel的
$request->getContent()会返回原始请求负载,但要避免在前置中间件中修改请求内容(比如解析JSON后重新编码,可能改变空格、换行符等格式,导致哈希不匹配)。 - 测试时直接使用Xero发送的Intent to Receive请求,不要自行构造,避免请求体格式差异。
内容的提问来源于stack exchange,提问作者Lochinvar
相关产品推荐
相关产品推荐

