使用CURL向API发起POST请求返回‘格式错误的JSON’问题排查
排查"Malformed JSON"错误的核心关键点
咱们一步步拆解你的问题——你已经修正了变量覆盖的问题,但还有几个容易被忽略的细节,很可能是导致错误的根源:
1. HMAC计算中的URI处理完全错误
这大概率是核心问题!Buckaroo的API规范要求,计算HMAC签名时使用的URI应该是请求的路径部分(小写),而不是对整个域名+路径做URL编码。你当前代码里的:
$uri = strtolower(urlencode('testcheckout.buckaroo.nl/json/Transaction'));
会生成类似testcheckout.buckaroo.nl%2Fjson%2Ftransaction的错误URI,但正确的写法应该是直接使用小写的请求路径:
$uri = '/json/transaction';
错误的URI会导致HMAC签名验证失败,服务器经常会返回误导性的"Malformed JSON"错误,而非直接提示签名不通过。
2. HMAC签名的密钥使用错误
在修正后的代码里,你把hash_hmac的密钥写死成了'----':
$s = hash_hmac('sha256', $hmac, '----', true);
这必须替换成你的实际$websiteKey,否则签名完全无效,服务器会直接拒绝请求。修正为:
$s = hash_hmac('sha256', $hmac, $websiteKey, true);
3. 可选优化:确保JSON编码的兼容性
虽然你生成的JSON格式看起来没问题,但可以给json_encode加上参数提升兼容性:
$post1 = json_encode($postArray, JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES);
JSON_PRESERVE_ZERO_FRACTION会让10.00保留为10.00而非10,如果API对数值格式有严格要求,这个参数很关键JSON_UNESCAPED_SLASHES避免不必要的转义,让JSON更简洁规范
4. 验证Content-Length的准确性
你已经修正为使用$post1的长度,这点是对的,但可以用mb_strlen确保计算的是字节长度(避免多字节字符干扰):
$headers[] = 'Content-Length: ' . mb_strlen($post1, '8bit');
5. 额外调试技巧
如果以上修正后仍有问题,可以开启CURL的调试模式,查看实际发送的请求内容:
curl_setopt($curl, CURLOPT_VERBOSE, true); $verboseLog = fopen('curl_debug.log', 'w+'); curl_setopt($curl, CURLOPT_STDERR, $verboseLog);
执行后打开curl_debug.log,就能看到完整的请求头和POST数据,确认JSON是否真的正确发送到了服务器。
内容的提问来源于stack exchange,提问作者Kevin.a
相关产品推荐
相关产品推荐

