增值税发票在线查验 API 怎么接入:Base64 图片上传、返回字段与工程实践

简介: 本文介绍阿里云市场增值税发票在线查验接口的技术接入方式:支持通过 imgBase64 或 imgUrl 传入发票图片,服务端完成 OCR 识别并联网核验后返回发票代码、号码、金额、购销方信息等结构化字段。文中给出请求参数表、完整 JSON 返回样例、常见 HTTP 与业务错误码排查方法,并提供 curl、Python、Node.js、Java、PHP 多语言示例,以及重试、缓存、限流等工程实践建议。

增值税发票在线查验 API 技术接入指南

封面图

1. 背景与适用场景

在企业财务、费用报销、电子发票归档等场景中,经常需要对纸质或电子发票进行真伪核验与票面信息提取。传统人工核对方式效率低、易出错,而通过 API 将发票图片传入服务端,由服务端完成 OCR 识别并联网核验,是一种常见的工程化方案。

本接口适合以下场景:

  • 报销系统:员工上传发票后自动提取发票代码、号码、金额等字段。
  • 财务对账:批量核对销方、购方、价税合计等信息。
  • 发票归档:将纸质发票扫描件结构化存储,便于检索与审计。

说明:本接口为阿里云市场入驻服务商提供的数据服务,正文示例中的鉴权头与调用路径均按阿里云 API 网关标准接入。

2. 接口概览

  • 调用方式:POST
  • 路径:/ocrCheckVAT
  • 协议:HTTPS
  • 返回格式:JSON
  • 鉴权方式:阿里云 API 网关 APPCODE 简单身份认证,请求头:Authorization: APPCODE <appcode>

请求体中传入发票图片的 Base64 编码或图片 URL,服务端完成识别与核验后返回票面结构化字段。完整调用地址请在阿里云控制台查看。

接口概览

3. 请求参数

字段名 类型 必填 说明
imgBase64 string 否 发票图片的 Base64 字符串,与 imgUrl 二选一
imgUrl string 否 发票图片的可访问下载地址,与 imgBase64 二选一

注意:imgBase64 与 imgUrl 必须且只能传一个。建议优先使用 Base64,避免图片外链失效或被限制访问。

4. 返回结构

顶层返回结构统一如下:

字段名 类型 说明
showapi_res_code int 接口调用是否成功,0 为成功,其他为失败
showapi_res_error string 错误提示信息
showapi_res_id string 请求唯一标识
showapi_res_body object 业务数据主体

showapi_res_body 内部字段:

字段名 类型 说明
ret_code int 业务调用结果,0 为成功
remark string 提示信息
invoiceType string 发票类型
invoiceCode string 发票代码
invoiceNo string 发票号码
invoiceDate string 开票日期
buyerName string 购方名称
buyerTaxNo string 购方税号
buyerContact string 购方地址电话
buyerBank string 购方开户行账户
salerName string 销方名称
salerTaxNo string 销方税号
salerContact string 销方地址电话
salerBank string 销方开户行账户
invoiceAmt string 合计金额
totalTaxAmt string 合计税额
totalAmt string 价税合计
notes string 发票备注
status int 发票状态:1 未作废、2 作废、3 红冲
itemList array 商品明细列表

itemList 每项字段:

字段名 类型 说明
name string 商品名称
amount string 数量
spec string 规格
unit string 单位
taxAmt string 税额
taxRate string 税率
priceAmt string 金额
priceUnit string 单价

成功响应示例:

{
   
  "showapi_res_code": 0,
  "showapi_res_error": "",
  "showapi_res_id": "",
  "showapi_res_body": {
   
    "ret_code": 0,
    "remark": "核验成功",
    "invoiceType": "增值税普通发票(电子)",
    "invoiceCode": "031*****411",
    "invoiceNo": "28*****251",
    "invoiceDate": "2019-01-01",
    "buyerName": "孟**",
    "buyerTaxNo": "",
    "buyerContact": "",
    "buyerBank": "",
    "salerName": "上海***有限公司",
    "salerTaxNo": "913*****40M",
    "salerContact": "上海市普陀区...",
    "salerBank": "",
    "invoiceAmt": "2891.98",
    "totalTaxAmt": "28.92",
    "totalAmt": "2920.90",
    "notes": "",
    "status": 1,
    "itemList": [
      {
   
        "name": "*信息技术服务*数据服务费",
        "spec": "API-AL",
        "unit": "项",
        "amount": "1.0",
        "taxRate": "0.01",
        "taxAmt": "28.92",
        "priceAmt": "2891.98",
        "priceUnit": "2891.980198019801980"
      }
    ]
  }
}

返回结构

5. 错误码与排查

接口存在两类错误:网关层 HTTP 状态码与业务层 ret_code / remark。

常见 HTTP 状态码:

状态码 含义 可能原因 排查办法
400 请求参数错误 缺少 imgBase64/imgUrl,或图片格式不支持 检查请求体是否包含有效图片字段
401 身份校验失败 APPCODE 缺失、错误或未启用该 API 在控制台确认 APPCODE 与授权状态
403 请求被禁止 剩余次数已用完或接口未购买 查看控制台余量与有效期
404 服务地址不存在 路径拼写错误 核对路径 /ocrCheckVAT
500 服务端内部错误 服务商端异常 稍后重试或联系平台
503 服务暂不可用 限流或维护 降低调用频率,稍后重试

业务层失败返回示例:

{
   
  "showapi_res_code": 0,
  "showapi_res_error": "",
  "showapi_res_body": {
   
    "ret_code": -1,
    "remark": "查验不一致!"
  }
}

常见业务提示:

  • "查验不成功,请重试。":服务商端核验超时或网络波动,可稍后重试。
  • "查验不一致!":票面信息与税局底账不一致。
  • "查无此票!":税局系统中未找到该发票记录。
  • "超过该张发票当日查验次数":单张发票当日查验次数已达上限,次日再试。

6. 频控与合规

  • 调用频次:具体 QPS 上限以阿里云控制台实时配置为准。
  • 次数扣减:当 HTTP 响应状态码为 200 时扣减调用次数;非 200 状态码不扣减。
  • 数据合规:发票图片属于敏感经营数据,传输请使用 HTTPS,并避免在日志中完整留存图片 Base64。核验结果仅用于业务校验,不作为唯一法律依据。
  • 缓存策略:发票状态在短时间内通常不变,对同一张发票的核验结果可做短时缓存(如 5~15 分钟),以减少重复调用。

适用场景

7. 多语言接入示例

curl

curl -X POST '<调用地址>/ocrCheckVAT' \
  -H 'Authorization: APPCODE <YOUR_APPCODE>' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'imgBase64=<BASE64_IMAGE_STRING>'

Python

import base64
import requests


def verify_invoice(image_path: str, appcode: str, endpoint: str):
    with open(image_path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode("utf-8")

    url = f"{endpoint}/ocrCheckVAT"
    headers = {
   "Authorization": f"APPCODE {appcode}"}
    resp = requests.post(
        url, data={
   "imgBase64": b64}, headers=headers, timeout=30
    )
    return resp.json()


# 使用示例
result = verify_invoice("invoice.jpg", "<YOUR_APPCODE>", "<调用地址>")
print(result["showapi_res_body"]["remark"])

Node.js

const fs = require('fs');
const axios = require('axios');

async function verifyInvoice(imagePath, appcode, endpoint) {
   
  const b64 = fs.readFileSync(imagePath, {
    encoding: 'base64' });
  const url = `${
     endpoint}/ocrCheckVAT`;
  const headers = {
    Authorization: `APPCODE ${
     appcode}` };
  const data = new URLSearchParams({
    imgBase64: b64 });
  const resp = await axios.post(url, data, {
    headers, timeout: 30000 });
  return resp.data;
}

Java

// 省略依赖引入,示例使用 JDK HttpClient + Jackson
public Map<String, Object> verifyInvoice(
        String imagePath, String appcode, String endpoint) throws Exception {
   
    byte[] bytes = Files.readAllBytes(Paths.get(imagePath));
    String b64 = Base64.getEncoder().encodeToString(bytes);

    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(endpoint + "/ocrCheckVAT"))
        .header("Authorization", "APPCODE " + appcode)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .POST(HttpRequest.BodyPublishers.ofString(
            "imgBase64=" + URLEncoder.encode(b64, StandardCharsets.UTF_8)))
        .build();

    HttpResponse<String> response = client.send(
        request, HttpResponse.BodyHandlers.ofString());

    return new ObjectMapper().readValue(
        response.body(), new TypeReference<Map<String, Object>>() {
   });
}

PHP

<?php
$appcode = '<YOUR_APPCODE>';
$endpoint = '<调用地址>';
$imagePath = 'invoice.jpg';
$b64 = base64_encode(file_get_contents($imagePath));

$ch = curl_init("{$endpoint}/ocrCheckVAT");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['imgBase64' => $b64]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: APPCODE {$appcode}"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo $data['showapi_res_body']['remark'];
?>

在线调试

8. 工程实践建议

  1. 前置校验:调用前检查图片大小与格式,建议压缩至 2MB 以内,避免 Base64 过大导致请求超时。
  2. 参数二选一:代码中显式校验 imgBase64 与 imgUrl 有且仅有一个,否则直接返回参数错误。
  3. 超时与重试:建议设置 30 秒超时;当返回 503 或 "查验不成功,请重试。" 时,采用指数退避重试 2~3 次。
  4. 结果缓存:对同一张发票的核验结果做幂等缓存,键可设为 发票代码_发票号码,TTL 5~15 分钟。
  5. 密钥管理:APPCODE 不要硬编码在前端或公开仓库,通过环境变量或密钥管理服务注入。
  6. 敏感数据:日志中不要打印完整 Base64 字符串;返回结果中购方/销方信息按需脱敏展示。
  7. 限流保护:客户端实现令牌桶或固定窗口限流,避免突发流量触发网关限流。

工程实践

9. 技术 FAQ

Q1:可以同时传 imgBase64 和 imgUrl 吗?
不建议。两个参数二选一,服务端以其中一个为准;同时传入可能造成请求体过大。

Q2:图片格式有要求吗?
通常支持 JPG、PNG、BMP 等常见图片格式。建议上传清晰、完整的电子发票 PDF 转图或拍照件。

Q3:为什么返回 "查无此票"?
可能原因:发票尚未同步至税局系统;输入图片模糊导致 OCR 识别错误;发票状态异常。建议核对图片清晰度与票面信息。

Q4:HTTP 200 但 ret_code 不为 0 是否扣次数?
根据该接口的次数扣减规则,HTTP 状态码为 200 时即视为一次成功调用并扣减剩余次数。因此 ret_code 不为 0 的业务失败(如查无此票)仍会扣减次数。

Q5:如何降低调用成本?
对高频重复核验场景使用短时缓存;批量处理前先做参数校验与去重;设置合理的限流策略。

10. 小结

本文围绕增值税发票在线查验接口,介绍了其适用场景、请求参数、返回结构、常见错误码以及多语言接入示例。接入时需注意:

  • 仅传 imgBase64 或 imgUrl 之一;
  • 使用 Authorization: APPCODE <appcode> 鉴权;
  • 完整调用地址、QPS 与收费规则以阿里云控制台为准;
  • 对敏感发票图片与核验结果做好传输加密、日志脱敏与缓存控制。

通过合理的重试、缓存与限流设计,可将该能力稳定集成到财务、报销或发票归档系统中。

相关文章
|
7月前
|
API
快递时效查询-快递预估到达时间-快递物流到达时间预测API接口介绍
快递时效查询API支持发货前预估和发货后预测,覆盖顺丰、中通、京东等11家主流快递,返回预计送达时间、时效、路径等关键信息,助力商家与用户高效规划物流。
1497 0
|
9月前
|
XML 算法 Java
电子税务平台Api接口-发票查验-发票验真-发票核验-发票查验真伪
随着数字化办公和财税电子化管理日益普及,发票的真实性查验已经成为企业财务、税务审计等业务流程中重要的一环。而不符合规定、虚假的发票,不得作为财务凭证,任何企业和个人有权拒收。发票查验接口即可实现发票真实性查验的功能。如对查验结果有疑议,可持发票原件至当地税务机关进行鉴定。
1426 0
|
14天前
|
缓存 自然语言处理 安全
图片验证码生成 API 接入教程,支持数字、字母、干扰线自定义
以一个图片验证码生成接口为样例,系统讲解 API 网关的通用接入方式与工程化落地。内容覆盖:鉴权方式(APPCODE 简单身份认证与 AppKey & AppSecret 签名认证)、请求参数设计(验证码长度、字符集、字体颜色、边框、干扰与混淆样式)、返回结构(code/msg 与 data 中的验证码文本及图片)、错误码排查、频控与合规、多语言接入示例(curl / Python / Node.js / PHP,含重试与指数退避),以及前置校验、幂等、超时熔断、短期缓存与密钥安全等工程实践。所讲范式可平移到任意 API 网关服务。
74 0
图片验证码生成 API 接入教程,支持数字、字母、干扰线自定义
|
1月前
|
缓存 JSON 自然语言处理
企业工商信息查询接口技术解析:接入流程、返回结构与工程实践
本文以统一社会信用代码查询企业工商数据接口为样例,梳理 RESTful 数据查询接口的通用接入方式。内容涵盖接口概览(HTTPS GET、APPCODE 鉴权、调用地址与请求参数)、返回结构(showapi_res_body 字段与两层返回码解析)、错误排查(HTTP 状态码与业务 ret_code)、频控与合规(限流、缓存 TTL、敏感信息脱敏)、多语言接入示例(curl/Python/Java/Node.js/PHP),以及重试、幂等、密钥安全等工程实践要点。适用于金融风控、商户资质审核、合规审查等需核验企业工商登记信息的场景。
243 0
企业工商信息查询接口技术解析:接入流程、返回结构与工程实践
|
1月前
2026-09-21 全国 31 省区市今日油价数据解析
本文整理 2026-09-21 全国 31 省区市今日油价数据,覆盖 89/92/95/98 号汽油与 0 号柴油明细,并梳理 92 号汽油区域价差等关键特征。
181 0
2026-09-21 全国 31 省区市今日油价数据解析
|
13天前
十万个为什么 | 2026年10月10日今日科普精选:8大主题科学问答一览
「十万个为什么」科普问答接口当日返回 8 大主题共 113 条科学问答,本文精选 26 条,覆盖地球、天空、水、动物、植物、人体、星星、天气八类话题,问答短小有趣,适合家长辅助儿童科学启蒙,也可作为科普内容创作的素材来源。
52 0
|
1月前
|
文字识别 API
VIN图片识别-车辆VIN识别-车辆VIN图片识别-车架号OCR-车架号OCR识别
车架号OCR识别技术可自动从图片中精准提取17位VIN码,广泛应用于二手车评估、保险理赔、维修保养等场景,提升效率、降低差错。支持Base64、URL、文件三种输入方式,返回结构化VIN结果。(239字)
147 0
VIN图片识别-车辆VIN识别-车辆VIN图片识别-车架号OCR-车架号OCR识别
|
1月前
2026-09-17 历史上的今天数据解析
本文整理 2026-09-17 当日历史上的今天数据,覆盖各年代明细,并给出年代分布特征。数据每日同步一次,实际以官方史料为准。
179 0
|
1月前
|
人工智能 安全
国庆自驾去远方:成都→拉萨 & 杭州→西安 两条经典线路全攻略
国庆自驾不只赶路!本攻略提供两条AI规划的精品线路:高原史诗线(成都→拉萨,7天适应高反)与丝路人文线(杭州→西安,5天慢游美食)。每条均配「日期+天气+风景」漫画行程图,行程、天气、画面三者精准同步,助你轻松玩转黄金周。
124 0