文件
hyb-oa/.trellis/tasks/archive/2026-08/07-28-travel-reimbursement-guide/research/tencent-ocr-api-review.md
T

8.0 KiB

腾讯 OCR API 调研

调研日期:2026-07-28。仅查阅腾讯云官方文档、当前锁定 SDK 和本地代码;未创建密钥、未调用付费 API、未上传票据。

官方资料

结论

1. 当前接口不适合作为两类差旅票据的统一入口

当前代码调用 VatInvoiceOCR。官方说明明确覆盖增值税专票、普票、电子专票、电子普票和数电普通/专用发票,适合住宿电子普通发票;但官方用于统一识别火车票、电子发票(铁路电子客票)和增值税发票的是 RecognizeGeneralInvoice。

RecognizeGeneralInvoice 明确返回 ElectronicTrainTicketFull,同时覆盖 VatElectronicCommonInvoice、VatElectronicInvoiceFull 等住宿发票常见子类型。因此本轮应在现有腾讯 provider 内改用该接口,而不是直接给当前 VatInvoiceOCR 配密钥。

2. 请求合同

  • API 版本仍为 2018-11-19,请求域名为 ocr.tencentcloudapi.com。
  • 当前锁定的 Node SDK 已包含 RecognizeGeneralInvoice;无需为了该方法先升级依赖。
  • PDF 通过 Base64 传输,不需要公开文件 URL。
  • Base64 编码后不得超过 10M;为避免 OA 的 10MiB 原文件上限在编码后超限,正式发票应增加不高于 7MiB 的 OCR 输入门禁。
  • 本系统一份 PDF 对应一张发票,只识别第一页:EnablePdf=true、PdfPageNumber=1、EnableMultiplePage=false。
  • 不请求切图、字段坐标、二维码或印章返回,避免无用数据和额外敏感内容。
  • 默认接口频率为 5 次/秒;当前 job 串行处理,远低于该上限。

3. 返回结构和业务字段

  • 住宿增值税/电子普通发票:从对应 VAT 子类型归一化发票代码(存在时)、号码、日期、不含税金额、税额、价税合计、销售方和购买方。
  • 电子发票(铁路电子客票):从 ElectronicTrainTicketFull 归一化发票号码、开票日期、价税合计、税额和购买方;该票种可以没有发票代码和销售方,不能继续套用现有 VAT 五字段必填规则。
  • 归一化结果需要保留安全的 documentSubtype,用它选择必填字段和脱敏处理;不得把乘车人姓名、证件号、完整票面字段或腾讯原始响应写入 OcrResult.result_json。
  • 电子票据没有发票代码时,不再把发票号码复制到代码字段。文件 SHA-256 查重继续生效;号码级查重需要按已知无代码子类型做显式规则,不能依赖伪造代码绕过现有复合键。

4. CAM 最小权限

腾讯官方确认 OCR 支持接口级自定义授权,接口级授权的 resource 必须为 *。运行身份只需:

{
  "version": "2.0",
  "statement": [
    {
      "effect": "allow",
      "action": ["ocr:RecognizeGeneralInvoice"],
      "resource": ["*"]
    }
  ]
}

运行子用户不需要 QcloudOCRFullAccess,也不需要开通/关闭服务或控制台管理权限。OCR 服务开通、计费设置和告警由管理员在控制台完成。

5. 免费接口选择、计费和错误

  • 官方免费额度表明确列出:通用票据识别(高级版) 使用同名专用资源包,免费额度为每月 1,000 次,当月有效、每月发放。它不是与其他票据接口共用的模糊额度。
  • 增值税发票识别 也有每月 1,000 次专用免费额度,但只能解决住宿常见 VAT/电子普通发票,不能统一覆盖电子发票(铁路电子客票)。
  • 独立的 火车票识别 位于官方“仅老客户续费相关接口”区域,且增加第二套 API、权限、归一化和错误处理,不适合作为当前新接入方案。
  • 因此最省钱且最简单的方案是只接 RecognizeGeneralInvoice:一个接口同时覆盖住宿和铁路电子客票,并消耗通用票据识别(高级版)的每月 1,000 次专用免费额度。按当前 8 人规模通常足够,但免费政策不是永久合同,上线前仍必须在实际账号控制台确认免费包已到账。
  • 高级版免费额度耗尽后,如已购买预付费包则继续扣包;如开通后付费则可能继续计费。官方当前后付费起价为 0.15 元/次。
  • 为确保零费用,生产应使用中国大陆地域,在 OCR 控制台设置页确认后付费关闭;免费额度耗尽后允许 OCR 不可用并进入可解释失败,不为保持识别可用而自动付费。境外地域按国际站后付费计费,不能抵扣国内账号资源包,因此不在本轮方案内。
  • 官方 FAQ 说明,2021 年 12 月 14 日前开通 OCR 的客户在资源包耗尽后可能自动开通后付费;无论账号何时开通,都以实际控制台开关状态为准,不能只凭开通日期推断不会收费。
  • 通用票据识别高级版按实际识别出的发票张数计费;增值税发票进入大票计费项,铁路电子客票/全电发票进入小票计费项。
  • 每份 PDF 必须只含一张票据,使一次正常识别对应一次额度扣减;混贴或多票文件可能按实际识别张数扣减,应用继续拒绝多票结果。
  • 免费/付费资源包耗尽且未开后付费时会不可用;应用需把它分类为额度/计费门禁失败,而不是票据质量失败。腾讯云侧同时设置费用或余额告警作为兜底。
  • 高级版接口官方错误码已核对:ResourceUnavailable.ResourcePackageRunOut 表示资源包耗尽,ResourceUnavailable.InArrears 表示欠费,ResourcesSoldOut.ChargeStatusException 表示计费状态异常,FailedOperation.UnOpenError 表示服务未开通,LimitExceeded.TooLargeFileError 表示文件过大。这些状态对同一输入重试没有收益,应用应一次终止并给出配置/额度类提示。
  • 大部分失败不计费,但官方明确有少量失败错误也可能计费。应用必须保留有限重试和可解释终态,不能无限重试。
  • 需要区别处理未开通、欠费/资源包耗尽、文件过大、图片解码/模糊和一般 OCR 失败;不得把配置或额度错误伪装成票据质量问题。

当前实现差距

  1. server/src/services/ocr/tencent.js 调用 VatInvoiceOCR,没有铁路电子客票结构解析。
  2. server/src/services/ocr/index.js 对所有 vat 强制要求代码、号码、日期、金额、销售方;铁路电子客票和部分数电票会被误判失败。
  3. 现有归一化会在代码/号码缺失时互相回填,掩盖无代码电子票据并污染复合查重语义。
  4. 现有归一化把腾讯完整响应放进 raw,随后持久化到 OcrResult.result_json;改用高级版后可能保存乘车人证件信息。
  5. OA 发票上传使用通用 10MiB 上限,可能产生“上传成功、腾讯因 Base64 超限失败”的死路。
  6. 旧版腾讯 OcrResult.result_json 可能仍带 raw;新 adapter 不再生成还不够,命中历史缓存时也必须先按安全白名单压缩,避免旧格式绕过新隐私边界。

推荐

只使用 RecognizeGeneralInvoice,不拆成 VatInvoiceOCR + TrainTicketOCR 两个接口。先完成腾讯 adapter、票种归一化、按票种质量门禁、敏感响应最小化、7MiB PDF 门禁和聚焦测试;再由用户在实际腾讯云账号确认高级版每月 1,000 次免费包已到账、中国大陆地域、后付费关闭和费用告警,最后创建最小权限密钥并部署。住宿发票和铁路电子客票各用一份已授权 PDF 做真实验收;在此之前不允许真实票据进入当前 mock 环境。