本文以 AP 审单(应付账款审核)为业务场景,演示如何通过 API 完成从创建空间、配置类别、上传文件、获取抽取结果到智能审核的完整流程。
如果您刚刚接触 DocFlow,建议先在 Web 页面 体验一下产品的基本功能,再阅读本文。
01 场景说明
在 AP(应付账款)审单业务中,财务人员每次付款前需要对一组采购单据进行交叉核验。典型的单据组合包括:
- 发票(含数电票、纸质增值税专用发票/普通发票等):记录销售方/购买方信息、开票金额和税率
- 采购订单(PDF/Word):约定供应商信息、合同金额、税率和产品明细
- 收货单(PDF):记录实际收货数量、物料信息及关联的采购订单号
通过 DocFlow,您只需配置一次分类和字段,后续上传的单据即可自动完成分类识别和结构化信息抽取;配置好审核规则库后,还可对多份单据进行跨文档智能审核,自动发现供应商不一致、金额超标、数量异常等问题。
02 业务流程
工作空间、文件类别和审核规则库只需配置一次,后续可持续复用——直接上传新的待处理文件并创建新的审核任务即可。本示例为演示完整流程,将配置步骤和处理步骤放在同一段代码中运行。
03 先决条件
- 登录 TextIn 控制台,获取
x-ti-app-id 和 x-ti-secret-code
- 下载示例样本文件,或使用自己的单据文件
04 类别与字段配置
本示例配置四个文件类别,均通过 category/create 接口创建并配置字段。
国内票-数电票(样本:sample_invoice.pdf)
增值税电子发票(数电票),包含发票号码、开票日期、购买方/销售方名称及税号、价税合计等基本信息字段,以及商品明细表格字段:| 字段名 | 类型 |
|---|
| 发票号码 | 基本信息字段 |
| 开票日期 | 基本信息字段 |
| 价税合计 | 基本信息字段 |
| 税前金额 | 基本信息字段 |
| 税额 | 基本信息字段 |
| 销售方名称 | 基本信息字段 |
| 销售方纳税人识别号 | 基本信息字段 |
| 购买方名称 | 基本信息字段 |
| 购买方纳税人识别号 | 基本信息字段 |
| 发票备注 | 基本信息字段 |
| 商品名称 | 表格字段 |
| 规格型号 | 表格字段 |
| 单位 | 表格字段 |
| 数量 | 表格字段 |
| 单价 | 表格字段 |
| 金额 | 表格字段 |
| 税率 | 表格字段 |
| 税额 | 表格字段 |
采购合同(样本:sample_contract.pdf)
采购合同是约定交易条款的核心文件,包含合同编号、甲乙方信息、金额、税率和产品明细。字段配置同时使用基本信息字段和表格字段:| 字段名 | 类型 |
|---|
| 编号 | 基本信息字段 |
| 甲方 | 基本信息字段 |
| 乙方 | 基本信息字段 |
| 签订日期 | 基本信息字段 |
| 合作期间 | 基本信息字段 |
| 支付条款 | 基本信息字段 |
| 乙方银行账户信息 | 基本信息字段 |
| 开票信息 | 基本信息字段 |
| 违约金条款 | 基本信息字段 |
| 采购物料/服务数量 | 基本信息字段 |
| 合同类型 | 基本信息字段 |
| 采购金额 | 基本信息字段 |
| 采购单价 | 基本信息字段 |
| 税率 | 基本信息字段 |
| 乙方税号 | 基本信息字段 |
| 采购物料/服务 | 基本信息字段 |
| 产品型号 | 表格字段 |
| 产品说明 | 表格字段 |
| 单价 | 表格字段 |
| 数量 | 表格字段 |
| 金额 | 表格字段 |
入库单(样本:sample_inbound.pdf)
入库单是仓库收货的凭证,记录实收数量、物料信息和供应商信息。字段配置同时使用基本信息字段和表格字段:| 字段名 | 类型 |
|---|
| 收货单编号 | 基本信息字段 |
| 收货日期 | 基本信息字段 |
| 对应合同号 | 基本信息字段 |
| 供应商名称 | 基本信息字段 |
| 仓库/库位 | 基本信息字段 |
| 物流单号 | 基本信息字段 |
| 入库总金额 | 基本信息字段 |
| 收货结论 | 基本信息字段 |
| 备注 | 基本信息字段 |
| 仓库收货人 | 基本信息字段 |
| 仓库收货人日期 | 基本信息字段 |
| 质检确认 | 基本信息字段 |
| 质检确认日期 | 基本信息字段 |
| 供应商送货人 | 基本信息字段 |
| 供应商送货人日期 | 基本信息字段 |
| 供应商税号 | 基本信息字段 |
| 收货入库明细-物料编码 | 表格字段 |
| 收货入库明细-物料描述 | 表格字段 |
| 收货入库明细-单位 | 表格字段 |
| 收货入库明细-应收 | 表格字段 |
| 收货入库明细-实收 | 表格字段 |
| 收货入库明细-差异 | 表格字段 |
| 收货入库明细-质检 | 表格字段 |
| 收货入库明细-签收人 | 表格字段 |
验收单(样本:sample_acceptance.pdf)
验收单是确认货物/服务交付质量的凭证,仅包含基本信息字段:| 字段名 | 类型 |
|---|
| 项目名称 | 基本信息字段 |
| 合同编号 | 基本信息字段 |
| 甲方单位名称 | 基本信息字段 |
| 乙方单位名称 | 基本信息字段 |
| 甲方验收人 | 基本信息字段 |
| 乙方施工人 | 基本信息字段 |
| 交付内容 | 基本信息字段 |
| 验收说明 | 基本信息字段 |
| 验收结论 | 基本信息字段 |
| 验收数量 | 基本信息字段 |
| 验收日期 | 基本信息字段 |
| 乙方税号 | 基本信息字段 |
05 审核规则配置
本示例的审核规则库包含 2 个规则组、12 条审核规则,覆盖跨单据业务一致性核验和文档完整性预检两个维度:
| 规则名称 | 风险等级 | 审核逻辑 |
|---|
| 供应商一致性 | 🔴 高风险 | 若均存在税号,则发票销售方税号 = 合同乙方税号 = 入库单供应商税号;否则比对名称 |
| 金额匹配 | 🔴 高风险 | 发票价税合计金额 ≤ 采购合同总金额;框架协议(金额为空或 0)时不校验 |
| 数量一致性(入库单维度) | 🟡 中风险 | 若发票含商品明细,则发票数量合计 ≤ 入库单实收数量合计 |
| 标的一致性 | 🟢 低风险 | 合同约定的规格型号须与入库单、发票中的规格型号一致;未约定规格型号时校验标的物描述是否指向同一商品 |
| 税率一致性 | 🟡 中风险 | 发票各行税率须与合同约定税率一致;合同未约定税率时跳过 |
| 验收结论校验 | 🟡 中风险 | 验收单的验收结论须为合格/通过/验收通过/同意验收或类似认可状态 |
| 数量一致性(验收单维度) | 🟡 中风险 | 若发票含商品明细且验收单有合格数量,则发票数量合计 ≤ 验收单合格数量 |
| 合同关联性 | 🟡 中风险 | 入库单合同编号 = 采购合同编号;验收单合同编号 = 采购合同编号 |
跨文档规则的 category_ids 包含多个分类 ID,只有当审核任务覆盖所有关联分类时,该规则才会被触发执行。
| 规则名称 | 风险等级 | 审核逻辑 |
|---|
| 信息完整性校验 | 🟡 中风险 | 检查四类文档齐全性并核验各文档必填字段非空(详见审核点说明) |
| 发票日期合规性 | 🟡 中风险 | 发票开票日期 ≥ 合同签订日期 |
| 购买方信息匹配 | 🔴 高风险 | 发票购买方名称 = 上海合合信息科技股份有限公司;购买方税号 = 91310110791485269J |
| 税率合规性校验 | 🟡 中风险 | 货物类税率应为 13%,服务类应为 6%,小规模纳税人应为 1% 或 3% |
06 代码结构说明
示例代码将完整的七步流程放在一起运行,便于理解端到端的调用链路。在实际生产中,步骤 1、2、5(创建工作空间、配置文件类别、配置审核规则库)只需执行一次;后续处理新单据时,只需重复步骤 3、4、6、7(上传文件 → 获取抽取结果 → 提交审核任务 → 获取审核结果),直接复用已有的配置即可。参见 AP 审单场景(已完成配置)。
示例代码中的函数分为两类,理解这一点有助于对照 API 文档进行调试和扩展。
两类函数
REST API 调用函数 — 每个函数直接封装一个 API 端点,函数参数与接口文档一一对应:
| 函数(Python) | 方法(Java) | 对应 API 端点 | 说明 |
|---|
create_workspace | createWorkspace | POST /workspace/create | 创建工作空间,返回 workspace_id |
create_category | createCategory | POST /category/create | 创建文件类别并上传样本,返回 category_id |
add_category_field | addCategoryField | POST /category/fields/add | 为已有类别追加字段(用于添加表格字段) |
upload_file | uploadFile | POST /file/upload | 上传待处理文件,返回 batch_number |
create_rule_repo | createRuleRepo | POST /review/rule_repo/create | 创建审核规则库,返回 repo_id |
create_rule_group | createRuleGroup | POST /review/rule_group/create | 在规则库内创建规则组,返回 group_id |
create_rule | createRule | POST /review/rule/create | 在规则组内创建审核规则,绑定适用分类 |
submit_review_task | submitReviewTask | POST /review/task/submit | 提交审核任务,返回审核 task_id |
工具辅助函数 — 不直接对应 API 端点,提供公共基础能力或封装轮询/展示逻辑:
| 函数(Python) | 方法(Java) | 作用 |
|---|
_headers | authHeaders | 构造鉴权请求头 |
_check | checkResponse | 校验响应 code,统一异常处理 |
_mime | mimeType | 根据扩展名推断 MIME 类型 |
wait_for_result | waitForResult | 循环轮询 file/fetch,等待抽取完成 |
display_result | displayResult | 格式化打印抽取结果 |
wait_for_review | waitForReview | 循环轮询 review/task/result,等待审核完成 |
display_review_result | displayReviewResult | 格式化打印审核结果 |
逐步代码说明
国内票-数电票、采购合同和入库单均包含表格字段,需先创建类别(配置基本信息字段),再通过 add_category_field 追加表格字段。table_id=-1 表示挂载到默认表格。# 国内票-数电票(基本信息字段 + 明细表格字段)
invoice_id = create_category(
workspace_id=workspace_id,
name="国内票-数电票",
sample_file_path="sample_invoice.pdf",
fields=[
{"name": "发票号码"}, {"name": "开票日期"}, {"name": "价税合计"},
# ... 其余基本信息字段
],
)
for field_name in ["商品名称", "规格型号", "单位", "数量", "单价", "金额", "税率", "税额"]:
add_category_field(workspace_id, invoice_id, field_name, table_id=-1)
# 采购合同(基本信息字段 + 表格字段)
contract_id = create_category(
workspace_id=workspace_id,
name="采购合同",
sample_file_path="sample_contract.pdf",
fields=[{"name": "编号"}, {"name": "甲方"}, {"name": "乙方"}, ...],
)
for field_name in ["产品型号", "产品说明", "单价", "数量", "金额"]:
add_category_field(workspace_id, contract_id, field_name, table_id=-1)
// 国内票-数电票
String invoiceId = createCategory(workspaceId, "国内票-数电票",
SAMPLE_DIR + "/sample_invoice.pdf", invoiceFields, "增值税电子发票(数电票)...");
for (String fn : new String[]{"商品名称", "规格型号", "单位", "数量", "单价", "金额", "税率", "税额"}) {
addCategoryField(workspaceId, invoiceId, fn, "-1");
}
// 采购合同
String contractId = createCategory(workspaceId, "采购合同",
SAMPLE_DIR + "/sample_contract.pdf", contractFields, "");
for (String fn : new String[]{"产品型号", "产品说明", "单价", "数量", "金额"}) {
addCategoryField(workspaceId, contractId, fn, "-1");
}
跨文档规则在 category_ids 中传入多个分类 ID。DocFlow 会从各分类已抽取的结果中提取规则关联字段,交由 AI 统一判断。# 供应商一致性——关联发票、合同、入库单三个分类
create_rule(workspace_id, repo_id, group1_id,
"供应商一致性",
"若均存在税号字段,则发票【销售方纳税人识别号】= 合同【乙方纳税人识别号】"
"= 入库单【供应商税号】;否则比对名称",
[invoice_id, contract_id, inbound_id], 10)
createRule(workspaceId, repoId, group1Id, "供应商一致性",
"若均存在税号字段,则发票【销售方纳税人识别号】= 合同【乙方纳税人识别号】"
+ "= 入库单【供应商税号】;否则比对名称",
Arrays.asList(invoiceId, contractId, inboundId), 10);
抽取结果示例
审核结果示例
07 完整示例代码下载
完整可运行代码(含 Python、Java 两个版本)已内置在文档仓库的 examples/ 目录下:
examples/
├── python/
│ ├── ap_review.py # Python 完整示例
│ ├── requirements.txt
│ └── README.md
├── java/
│ ├── src/main/java/com/docflow/ApReview.java
│ ├── pom.xml
│ └── README.md
└── sample_files/
└── ap_review/
├── sample_invoice.pdf
├── sample_contract.pdf
├── sample_inbound.pdf
└── sample_acceptance.pdf
Python 示例
查看 Python 完整示例代码
08 运行示例
环境要求:Python 3.8+1. 安装依赖cd examples/python
pip install -r requirements.txt
2. 填写配置打开 ap_review.py,填写文件顶部的配置项:APP_ID = "your-app-id" # x-ti-app-id
SECRET_CODE = "your-secret-code" # x-ti-secret-code
3. 运行 环境要求:JDK 11+,Maven 3.6+1. 填写配置打开 src/main/java/com/docflow/ApReview.java,填写文件顶部的配置项:private static final String APP_ID = "your-app-id";
private static final String SECRET_CODE = "your-secret-code";
2. 编译并运行cd examples/java
mvn compile -q
mvn exec:java -Dexec.mainClass="com.docflow.ApReview"
运行成功后,可登录 DocFlow Web 页面,在对应工作空间下直观查看每份文件的分类、字段抽取结果和智能审核结果,便于与代码输出对照验证。
预期控制台输出
成功运行后,控制台将输出如下内容(workspace_id、category_id 等 ID 因运行环境不同而变化):
============================================================
DocFlow AP 审单场景示例
============================================================
[步骤1] 工作空间创建成功 workspace_id=<workspace_id>
[步骤2] 文件类别创建成功 name=国内票-数电票 category_id=<category_id>
追加字段成功 name=商品名称 field_id=<field_id>
追加字段成功 name=规格型号 field_id=<field_id>
追加字段成功 name=单位 field_id=<field_id>
追加字段成功 name=数量 field_id=<field_id>
追加字段成功 name=单价 field_id=<field_id>
追加字段成功 name=金额 field_id=<field_id>
追加字段成功 name=税率 field_id=<field_id>
追加字段成功 name=税额 field_id=<field_id>
[步骤2] 文件类别创建成功 name=采购合同 category_id=<category_id>
追加字段成功 name=产品型号 field_id=<field_id>
追加字段成功 name=产品说明 field_id=<field_id>
追加字段成功 name=单价 field_id=<field_id>
追加字段成功 name=数量 field_id=<field_id>
追加字段成功 name=金额 field_id=<field_id>
[步骤2] 文件类别创建成功 name=入库单 category_id=<category_id>
追加字段成功 name=收货入库明细-物料编码 field_id=<field_id>
追加字段成功 name=收货入库明细-物料描述 field_id=<field_id>
追加字段成功 name=收货入库明细-单位 field_id=<field_id>
追加字段成功 name=收货入库明细-应收 field_id=<field_id>
追加字段成功 name=收货入库明细-实收 field_id=<field_id>
追加字段成功 name=收货入库明细-差异 field_id=<field_id>
追加字段成功 name=收货入库明细-质检 field_id=<field_id>
追加字段成功 name=收货入库明细-签收人 field_id=<field_id>
[步骤2] 文件类别创建成功 name=验收单 category_id=<category_id>
配置完成 workspace_id=<workspace_id>
国内票-数电票: category_id=<category_id>
采购合同: category_id=<category_id>
入库单: category_id=<category_id>
验收单: category_id=<category_id>
开始上传待处理文件...
[步骤3] 文件上传成功 name=sample_invoice.pdf batch_number=<batch_number>
[步骤3] 文件上传成功 name=sample_contract.pdf batch_number=<batch_number>
[步骤3] 文件上传成功 name=sample_inbound.pdf batch_number=<batch_number>
[步骤3] 文件上传成功 name=sample_acceptance.pdf batch_number=<batch_number>
开始获取处理结果...
[步骤4] 等待处理结果(batch_number=<batch_number>)..... 完成
============================================================
文件名 : sample_invoice.pdf
分类结果 : 国内票-数电票
── 普通字段 ──────────────────────────
发票号码 : 25442000000012345678
开票日期 : 2025-01-15
价税合计 : 50,900.00
税前金额 : 48,000.00
税额 : 2,900.00
销售方名称 : 上海某某科技有限公司
销售方纳税人识别号 : 91310000XXXXXXXXXX
购买方名称 : 合合信息科技(上海)有限公司
购买方纳税人识别号 : 91310000YYYYYYYYYY
── 表格行数据 ────────────────────────
第1行: 商品名称=智能硬件设备 | 规格型号=XH-2000 | 单位=台 | 数量=10 | 单价=4,800.00 | 金额=48,000.00 | 税率=6% | 税额=2,880.00
[步骤4] 等待处理结果(batch_number=<batch_number>)......... 完成
============================================================
文件名 : sample_contract.pdf
分类结果 : 采购合同
── 普通字段 ──────────────────────────
编号 : HT-2025-001
甲方 : 合合信息科技(上海)有限公司
乙方 : 上海某某科技有限公司
签订日期 : 2025-01-10
采购金额 : 50,900.00
税率 : 6%
乙方税号 : 91310000XXXXXXXXXX
[步骤4] 等待处理结果(batch_number=<batch_number>)...... 完成
============================================================
文件名 : sample_inbound.pdf
分类结果 : 入库单
── 普通字段 ──────────────────────────
收货单编号 : RK-2025-0115
收货日期 : 2025-01-20
对应合同号 : HT-2025-001
供应商名称 : 上海某某科技有限公司
入库总金额 : 50,900.00
供应商税号 : 91310000XXXXXXXXXX
[步骤4] 等待处理结果(batch_number=<batch_number>).... 完成
============================================================
文件名 : sample_acceptance.pdf
分类结果 : 验收单
── 普通字段 ──────────────────────────
合同编号 : HT-2025-001
甲方单位名称 : 合合信息科技(上海)有限公司
乙方单位名称 : 上海某某科技有限公司
验收结论 : 验收合格
开始配置审核规则库...
[步骤5] 规则库创建成功 name=AP审单场景审核规则库 repo_id=<repo_id>
规则组创建成功 name=供应商一致性校验 group_id=<group_id>
规则创建成功 name=供应商一致性 rule_id=<rule_id>
规则创建成功 name=发票与合同金额匹配 rule_id=<rule_id>
规则创建成功 name=发票购买方与合同甲方一致 rule_id=<rule_id>
规则组创建成功 name=入库与合同一致性 group_id=<group_id>
规则创建成功 name=入库数量与合同数量匹配 rule_id=<rule_id>
规则创建成功 name=入库单号关联合同号 rule_id=<rule_id>
规则组创建成功 name=验收合规性 group_id=<group_id>
规则创建成功 name=验收单与入库单物料一致 rule_id=<rule_id>
[步骤6] 审核任务提交成功 task_id=<task_id>
[步骤7] 等待审核结果(task_id=<task_id>)................. 完成
============================================================
审核任务状态 : 审核通过
规则通过数 : 6
规则不通过数 : 0
── 规则组:供应商一致性校验 ───────────────────
✓ [高风险] 供应商一致性: 审核通过
依据: 发票销售方纳税人识别号与采购合同乙方税号均为 91310000XXXXXXXXXX,一致。
✓ [高风险] 发票与合同金额匹配: 审核通过
依据: 发票价税合计 50,900.00 与采购合同采购金额 50,900.00 完全一致。
✓ [中风险] 发票购买方与合同甲方一致: 审核通过
依据: 发票购买方"合合信息科技(上海)有限公司"与合同甲方一致。
── 规则组:入库与合同一致性 ───────────────────
✓ [高风险] 入库数量与合同数量匹配: 审核通过
依据: 入库单实收数量 10 台与采购合同约定数量 10 台一致。
✓ [中风险] 入库单号关联合同号: 审核通过
依据: 入库单对应合同号 HT-2025-001 与采购合同编号一致。
── 规则组:验收合规性 ───────────────────
✓ [中风险] 验收单与入库单物料一致: 审核通过
依据: 验收单合同编号与入库单对应合同号均为 HT-2025-001,物料关联一致。
============================================================
示例运行完成
============================================================
09 结果说明
抽取结果
处理完成后,每份文件将返回分类结果和字段抽取结果。字段抽取结果位于 data.fields[],表格字段位于 data.items[][],每个字段包含 key、value 及坐标 position(可用于原文高亮回显)。
以下为发票样本文件的实际接口返回(来自 file/fetch,省略了部分 position 坐标):
{
"id": "2029124607672344576",
"name": "sample_invoice.pdf",
"format": "pdf",
"category": "国内票-数电票",
"recognition_status": 1,
"duration_ms": 4832,
"data": {
"fields": [
{ "key": "发票号码", "value": "25442000000012345678" },
{ "key": "开票日期", "value": "2025-01-15" },
{ "key": "价税合计", "value": "50900.00" },
{ "key": "税前金额", "value": "48000.00" },
{ "key": "税额", "value": "2900.00" },
{ "key": "销售方名称", "value": "上海某某科技有限公司" },
{ "key": "销售方纳税人识别号", "value": "91310000XXXXXXXXXX" },
{ "key": "购买方名称", "value": "合合信息科技(上海)有限公司" },
{ "key": "购买方纳税人识别号", "value": "91310000YYYYYYYYYY" },
{ "key": "发票备注", "value": "" }
],
"items": [
[
{ "key": "商品名称", "value": "智能硬件设备" },
{ "key": "规格型号", "value": "XH-2000" },
{ "key": "单位", "value": "台" },
{ "key": "数量", "value": "10" },
{ "key": "单价", "value": "4800.00" },
{ "key": "金额", "value": "48000.00" },
{ "key": "税率", "value": "6%" },
{ "key": "税额", "value": "2880.00" }
]
],
"stamps": [],
"handwritings": []
}
}
审核结果
审核完成后,可从 review/task/result 接口获取以下信息:
status:任务整体状态(1=审核通过,4=审核不通过,2=审核失败)
statistics:规则通过数、不通过数汇总
groups[].review_tasks[]:每条规则的详细审核结果,包含:
review_result:该规则的审核结论(1=通过,4=不通过)
reasoning:AI 给出的审核依据说明
anchors:依据在原文中的坐标位置(可用于高亮回显)
{
"task_id": "31415926",
"task_name": "AP审核",
"status": 1,
"statistics": { "pass_count": 6, "failure_count": 0, "error_count": 0 },
"groups": [
{
"group_name": "供应商一致性校验",
"review_tasks": [
{
"rule_name": "供应商一致性",
"risk_level": 10,
"review_result": 1,
"reasoning": "发票销售方纳税人识别号与采购合同乙方税号均为 91310000XXXXXXXXXX,一致,审核通过。"
},
{
"rule_name": "发票与合同金额匹配",
"risk_level": 10,
"review_result": 1,
"reasoning": "发票价税合计 50900.00 与采购合同采购金额 50900.00 完全一致,审核通过。"
},
{
"rule_name": "发票购买方与合同甲方一致",
"risk_level": 20,
"review_result": 1,
"reasoning": "发票购买方"合合信息科技(上海)有限公司"与采购合同甲方一致,审核通过。"
}
]
},
{
"group_name": "入库与合同一致性",
"review_tasks": [
{
"rule_name": "入库数量与合同数量匹配",
"risk_level": 10,
"review_result": 1,
"reasoning": "入库单实收数量 10 台与采购合同约定数量 10 台一致,审核通过。"
},
{
"rule_name": "入库单号关联合同号",
"risk_level": 20,
"review_result": 1,
"reasoning": "入库单对应合同号 HT-2025-001 与采购合同编号一致,审核通过。"
}
]
},
{
"group_name": "验收合规性",
"review_tasks": [
{
"rule_name": "验收单与入库单物料一致",
"risk_level": 20,
"review_result": 1,
"reasoning": "验收单合同编号与入库单对应合同号均为 HT-2025-001,物料关联一致,审核通过。"
}
]
}
]
}