PHP调用invoiz.de API创建发票报ValidationError的问题排查
PHP 调用 invoiz.de 创建发票接口参数校验错误排查
前置可正常运行的流程
已获取平台API密钥、密钥对、安装ID参数,以下两个接口调用逻辑可正常返回数据:
- 获取Bearer Token的代码:
// 获取接口授权Token $curl = curl_init('https://app.invoiz.de/api/auth/token'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_USERPWD, $apiKey . ":" . $secretApiKey); curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query([ 'installationId' => $installationId ])); $content = curl_exec($curl); $token = json_decode($content); curl_close($curl);
- 拉取全量文章列表的代码:
// 获取文章列表 $curl = curl_init('https://app.invoiz.de/api/article'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($curl, CURLOPT_USERPWD, $apiKey . ":" . $secretApiKey); curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer '.$token->token ]); curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query([ 'limit' => 20, 'orderBy' => 'title' ])); $content = curl_exec($curl); $article = json_decode($content); curl_close($curl); echo '<pre>'; print_r($article); echo '</pre>';
报错场景与原因
根据API文档要求,创建发票的接口需要提交JSON格式的请求体,官方示例结构为:
{ "date": "2020-03-01T00:00:00.000Z", "customerId": 542, "priceKind": "net", "deliveryDate": "2020-03-01T00:00:00.000Z", "articles": [ { "id": 143, "amount": 5, "discount": 10 } ] }
最初编写的创建发票代码运行后,接口返回ValidationError校验错误,提示输入内容为空,具体返回结构为:
stdClass Object ( [name] => ValidationError [message] => Please check your entries. [meta] => stdClass Object ( [body] => Array ( [0] => stdClass Object ( [code] => NOT_EMPTY [message] => Please check your entries. ) ) ) )
对应的问题代码如下:
// 存在问题的创建发票代码 $curl = curl_init('https://app.invoiz.de/api/v2/invoice'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_USERPWD, $apiKey . ":" . $secretApiKey); curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer '.$token->token ]); // 直接传入PHP数组作为POST字段 curl_setopt($curl, CURLOPT_POSTFIELDS, [ 'date' => '2021-04-20T00:00:00.000Z', 'customerId' => 100110, 'deliveryDate' => '2021-04-20T00:00:00.000Z', 'priceKind' => 'net', 'articles' => [ 'id' => MY_ARTICLE_ID, 'amount' => 2, 'discount' => 10 ] ]); $content = curl_exec($curl); $invoice = json_decode($content); curl_close($curl); echo '<pre>'; print_r($invoice); echo '</pre>';
报错的核心原因有三点:
- curl收到数组类型的
CURLOPT_POSTFIELDS参数时,会自动以multipart/form-data格式编码提交,不符合接口要求的JSON格式; - 请求头未声明
Content-Type: application/json,服务端无法正确解析提交的内容,最终判定请求体为空,触发参数非空校验失败; - 原有代码里的
articles参数直接传了单个关联数组,没有嵌套为数组结构,和接口要求的「商品列表」结构不匹配。
修正后的可运行方案
调整逻辑为:先将请求参数序列化为合法JSON字符串,同时在请求头中声明JSON内容类型,再提交给接口:
// 修正后的创建发票代码 $values = [ "date" => "2020-03-01T00:00:00.000Z", "customerId" => 100110, "priceKind" => "net", "deliveryDate" => "2020-03-01T00:00:00.000Z", "articles" => [ ["id" => 45203, "amount" => 5, "discount" => 10] ] ]; // 序列化为JSON字符串 $data = json_encode($values); $curl = curl_init('https://app.invoiz.de/api/v2/invoice'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_USERPWD, $apiKey . ":" . $secretApiKey); // 携带授权头、声明JSON内容类型 curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Content-Type:application/json', 'Authorization: Bearer '.$token->token ]); // 提交序列化后的JSON字符串 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); $content = curl_exec($curl); $invoice = json_decode($content); curl_close($curl); echo '<pre>'; print_r($invoice); echo '</pre>';
内容的提问来源于stack exchange,提问作者Trombone0904
相关产品推荐
相关产品推荐

