无法向HMRC测试API提交VAT Return,请求排查代码问题
HMRC VAT API提交VAT Return报错排查
问题场景
我正在使用HMRC VAT API提交VAT Return,最初的代码如下:
$vrn = 'test'; $endpoint = 'https://test-api.service.hmrc.gov.uk/organisations/vat/'.$vrn.'/returns'; $periodKey = 'A001'; $authToken = $access_token;// it is $token_data['access_token'] $vatReturnData = json_encode([ "periodKey" => $periodKey, "vatDueSales" => 105.5, "vatDueAcquisitions" => -100.45, "totalVatDue" => 5.05, "vatReclaimedCurrPeriod" => 105.15, "netVatDue" => 100.1, "totalValueSalesExVAT" => 300, "totalValuePurchasesExVAT" => 300, "totalValueGoodsSuppliedExVAT" => 3000, "totalAcquisitionsExVAT" => 3000, "finalised" => true ]); $vatReturnJson = json_encode($vatReturnData); $headers = [ 'Accept: application/vnd.hmrc.1.0+json', 'Authorization: Bearer ' . $authToken, 'Content-Type: application/json', 'Content-Length: ' . strlen($vatReturnJson) ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $vatReturnData); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); $response = curl_exec($ch); if ($response === false) { echo 'Error: ' . curl_error($ch). ' '. show_line_number(); } else { echo 'Response: ' . $response. ' '. show_line_number(); } curl_close($ch);
授权后后台执行约1分钟后重定向至我的网站,显示错误:Error: Recv failure: Connection reset by peer 125。
随后我修改代码,将$vatReturnData改为数组:
$vatReturnData = array( "periodKey" => $periodKey, "vatDueSales" => 105.5, "vatDueAcquisitions" => -100.45, "totalVatDue" => 5.05, ... );
修改后收到响应:Response: {"code":"INTERNAL_SERVER_ERROR","message":"An internal server error occurred"}。
问题根源
1. 重复JSON编码导致格式与长度不匹配
最初代码中,先将数组编码为JSON字符串存入$vatReturnData,接着又对这个字符串再次执行json_encode得到$vatReturnJson,同时请求头的Content-Length使用的是二次编码后的字符串长度,但实际POST的内容是一次编码的$vatReturnData。这会导致:
- 服务器收到的内容长度与声明的长度不符,触发连接重置
- 即使长度巧合匹配,二次编码的内容会变成字符串嵌套的无效JSON,不符合API数据格式要求
2. 直接传递数组导致请求格式错误
修改为直接传递数组时,cURL默认会将数组编码为multipart/form-data格式,但HMRC API要求的是application/json格式,服务器无法正确解析请求体,因此返回内部错误。
3. 不必要的HTTP版本指定
手动指定CURL_HTTP_VERSION_1_1没有必要,cURL会自动协商最优的HTTP版本,多余的设置可能引发兼容性问题。
修复后的代码
$vrn = 'test'; $endpoint = 'https://test-api.service.hmrc.gov.uk/organisations/vat/'.$vrn.'/returns'; $periodKey = 'A001'; $authToken = $access_token; // 对应$token_data['access_token'] // 构造原始数据数组 $vatReturnArray = [ "periodKey" => $periodKey, "vatDueSales" => 105.5, "vatDueAcquisitions" => -100.45, "totalVatDue" => 5.05, "vatReclaimedCurrPeriod" => 105.15, "netVatDue" => 100.1, "totalValueSalesExVAT" => 300, "totalValuePurchasesExVAT" => 300, "totalValueGoodsSuppliedExVAT" => 3000, "totalAcquisitionsExVAT" => 3000, "finalised" => true ]; // 仅执行一次JSON编码 $vatReturnJson = json_encode($vatReturnArray); $headers = [ 'Accept: application/vnd.hmrc.1.0+json', 'Authorization: Bearer ' . $authToken, 'Content-Type: application/json' // 无需手动设置Content-Length,cURL会自动计算并添加 ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $vatReturnJson); // 移除不必要的HTTP版本强制设置 $response = curl_exec($ch); if ($response === false) { echo 'Error: ' . curl_error($ch) . ' ' . show_line_number(); } else { echo 'Response: ' . $response . ' ' . show_line_number(); } curl_close($ch);
额外检查点
- 确保
$vrn使用的是测试环境下的有效编号,而非占位符'test' - 确认
$authToken是具备VAT提交权限的有效访问令牌 - 若仍有问题,可添加
curl_setopt($ch, CURLOPT_VERBOSE, true);开启cURL调试模式,查看详细请求日志定位问题
内容的提问来源于stack exchange,提问作者Andris
相关产品推荐
相关产品推荐

