Files
Ticket/history/票通对接业务流程说明.md
T
2026-05-07 10:25:02 +08:00

514 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 票通对接业务流程说明
本文基于以下资料整理:
- [系统设计.md](C:\Users\BBIT\Desktop\农产品收购发票开票平台\系统设计.md)
- [doc\票通数电平台对接指引v1.0(2).txt](C:\Users\BBIT\Desktop\农产品收购发票开票平台\doc\票通数电平台对接指引v1.0(2).txt)
- [doc\票通数电发票接口文档3.3.5.txt](C:\Users\BBIT\Desktop\农产品收购发票开票平台\doc\票通数电发票接口文档3.3.5.txt)
## 1. 你的角色本质是什么
结论:是的,你本质上是“接入方平台 / 第三方平台 / 中台”,帮助甲方企业对接票通,以甲方企业的名义完成开票。
但这里不是简单的 HTTP 转发,还包括以下职责:
- 维护“你的平台”和“开票企业”的绑定关系
- 维护或选择甲方企业可用的数电账号
- 组织开票报文并调用票通接口
- 处理登录认证、风险认证
- 接收票通推送或主动查询开票结果
- 再把开票结果回写给你自己的业务系统
从票通文档看,这个角色被明确定义为:
- `第三方平台` / `集团企业`
- `接入方系统`
关键依据:
- 对接指引说明“接入方系统开发完成后,由票通提供正式环境参数”
- 直接开票场景中,`系统接入方组织好待开票信息后,直接调用 2.9 开具蓝字数电发票`
- 企业通过接口注册后,会自动生成“平台和企业的绑定关系”;如果企业已在票通完成入驻,则需要联系票通侧建立“接入方平台和开票企业的绑定关系”
所以业务归属上:
- 开票主体是甲方企业
- 票通是开票服务平台
- 你是中间接入平台
## 2. 票通是否提供测试接口
结论:提供。
### 2.1 测试环境说明
票通对接指引明确写了:
- 测试环境和参数信息由票通对接人员提供
- 包括平台编码、RSA 证书、3DES 密钥、测试税号
- 正式上线前,再由票通提供正式环境参数
文档里的核心说明:
- 测试环境参数:平台编码、RSA 签名验签证书、3DES 密钥、测试税号
- 联调测试阶段,可直接使用票通对接人员提供的测试税号
### 2.2 测试地址风格
核心测试地址统一是:
```text
http://fpkj.testnw.vpiaotong.cn/tp/openapi/...
```
正式地址统一是:
```text
https://fpkj.vpiaotong.com/tp/openapi/...
```
### 2.3 你当前真正会用到的测试接口
- `register.pt`
- `registerUser.pt`
- `sendLoginSmsCode.pt`
- `smsLogin.pt`
- `getAuthenticationQrcode.pt`
- `queryAuthQrcodeScanStatus.pt`
- `getTaxBureauAccountAuthStatus.pt`
- `listTaxBureauAccount.pt`
- `invoiceBlue.pt`
- `queryInvoice.pt`
- `queryInvoiceInfo.pt`
- `logoutEtax.pt`
- `getEnterpriseInfo.pt`
- `queryEnterpriseBankInfo.pt`
注意:
- 推送接口 `2.13 / 2.14 / 2.48` 没有票通固定测试地址,因为这是“票通调用你提供的接口地址”
- 也就是说,回调 URL 不是你调用票通时传进去的,而是你提供给票通侧配置使用的
## 3. 开票结果“回写”到底分几层
这里要分清楚两层,不要混在一起。
### 3.1 第一层:票通把结果返回给你的平台
这是票通体系内的结果同步,主要有两种方式:
#### 方式 A:票通推送
票通文档定义了:
- `2.13 推送发票主要信息`
- `2.14 推送发票全票面信息`
调用关系写得很明确:
- `票通平台调用第三方平台`
- `接口地址:第三方平台提供`
这就是我们说的“回调”。
#### 方式 B:你的平台主动查询
票通文档定义了:
- `2.11 查询发票主要信息`
- `2.12 查询发票全票面信息`
也就是说,开票结果可以:
- 等票通推送过来
- 或者你主动轮询查询
最佳实践不是二选一,而是:
- 主用推送
- 查询作为补偿和兜底
### 3.2 第二层:你的平台再把结果写回你自己的业务系统
这个“开票结果回写接口”不是给票通用的。
它是你自己的业务系统接口,用来做这些事:
- 把原始业务单据状态改成“开票成功/失败/处理中”
- 回写发票号码、数电发票号码、开票日期
- 回写失败原因
- 记录票通流水号或发票请求流水号
所以:
- `票通 -> 你的平台`:票通文档里有
- `你的平台 -> 你的业务系统`:票通文档里没有,需要你自己定义
## 4. 回调是怎么和票通绑定的
从文档能确认两件事:
1. `2.13 / 2.14 / 2.48` 都是“票通平台调用第三方平台”
2. 接口地址不是你在开票请求里传递,而是“第三方平台提供”
因此可以得出一个明确结论:
- 回调地址不是按每张发票动态传的
- 而是你先提供给票通,由票通侧事先配置
文档没有给出“通过某个接口动态设置回调地址”的描述,所以这里应按“线下配置 / 对接阶段配置”理解。
实际落地时通常就是:
1. 你先准备一个公网可访问的回调地址
2. 提供给票通对接人员
3. 票通侧把这个地址配置成推送接收地址
4. 票通后续在开票成功、失败、认证异常等场景调用你的回调接口
对你来说要注意:
- 回调接口必须能公网访问
- 必须按票通公共报文做验签和解密
- 要做幂等,避免重复推送重复入库
- 不能只靠回调,最好仍保留主动查询兜底
## 5. 开票结果样例怎么理解
这里也分两种。
### 5.1 票通推送/查询给你的样例
这个在票通文档里是有的。
最有代表性的就是:
- `2.13 推送发票主要信息` 样例
- `2.11 查询发票主要信息` 样例
- `2.12 查询发票全票面信息` 样例
例如 `2.13` 的成功推送报文会包含:
- `taxpayerNum`
- `invoiceReqSerialNo`
- `invoiceType`
- `invoiceKind`
- `code`
- `msg`
- `tradeNo`
- `definedData`
- `invoiceCode`
- `invoiceNo`
- `electronicInvoiceNo`
- `invoiceDate`
- `noTaxAmount`
- `taxAmount`
- `invoicePdf`
- `invoiceXml`
- `downloadUrl`
其中:
- `code=0000` 表示成功
- `code=3999` 表示需要扫码或短信认证
- `code=9999` 表示开票失败
### 5.2 你写回甲方业务系统的样例
这个在票通文档里没有,因为这是你自己的内部系统接口。
你至少需要自己约定一份这样的回写报文:
```json
{
"bizOrderNo": "CG202604290001",
"companyId": "COMP_001",
"invoiceReqSerialNo": "DEMO202604290001234567",
"status": "SUCCESS",
"ptCode": "0000",
"ptMsg": "开具成功",
"invoiceCode": "123456789012",
"invoiceNo": "12345678",
"electronicInvoiceNo": "12345678901212345678",
"invoiceDate": "2026-04-29 14:20:31",
"noTaxAmount": "90.50",
"taxAmount": "11.50",
"downloadUrl": "https://...",
"definedData": "自定义数据"
}
```
失败样例建议至少保留:
```json
{
"bizOrderNo": "CG202604290001",
"companyId": "COMP_001",
"invoiceReqSerialNo": "DEMO202604290001234567",
"status": "FAILED",
"ptCode": "9999",
"ptMsg": "开票失败,失败原因见票通返回",
"failReason": "票通返回的失败描述"
}
```
## 6. 按业务流程顺序,你需要知道和会用到的接口
下面按实际开发顺序来列,不按文档章节号罗列。
### 6.1 安全机制和公共报文
所有接口调用前都要先满足:
- 公共报文使用 RSA 签名
- 业务报文使用 3DES 加密
- 编码统一 UTF-8
- 公共字段包括:
- `platformCode`
- `signType`
- `sign`
- `format`
- `timestamp`
- `version`
- `serialNo`
- `content`
注意事项:
- `content` 里放的是除公共参数外的全部业务参数
- RSA 签名结果要做 Base64 编码
- 业务 JSON 编码统一 UTF-8
### 6.2 企业是否已入驻票通
你需要先确认开票企业是否已经具备票通开票资格。
可用接口:
- `2.2 注册企业`
- `2.47 查询企业信息`
- `2.48 企业审核结果推送`
使用顺序建议:
1. 如果甲方企业尚未入驻,走 `2.2 注册企业`
2. 注册后用 `2.47 查询企业信息` 看审核状态
3. 如果票通侧支持,可接 `2.48 企业审核结果推送`
注意事项:
- 企业必须先完成入驻才能开票
- 如果企业不是通过接口注册,而是在票通侧已存在,需要和票通做“平台与企业绑定”
- `reviewStatus` 要关注:
- `0` 待审核
- `1` 审核通过
- `2` 审核不通过
- `3` 审核中
### 6.3 数电账号准备
如果甲方企业已经入驻,下一步是准备可以用于开票的数电账号。
可用接口:
- `2.3 数电账号登记`
- `2.45 查询数电账号列表`
- `2.8 查询数电账号认证状态`
- `2.46 退出电子税局登录`
使用顺序建议:
1. 先用 `2.45` 查询某税号下已经维护好的数电账号
2. 如果你需要平台内维护账号,再用 `2.3` 登记
3. 开票前用 `2.8` 检查认证状态
4. 如存在异常登录状态,再视情况用 `2.46` 退出后重登
注意事项:
- `2.3` 的密码和身份密码要用票通要求的 3DES 加密
- `2.45 / 2.8` 会返回:
- `operationProposed`
- `authStatus`
- `switchable`
- `wechatUserBindStatus`
- `operationProposed` 最重要:
- `0` 无需认证
- `1` 需扫码认证
- `2` 需扫码或短信认证
- `3` 需短信认证
### 6.4 开票前置检查
正式开票前,建议先做企业和票面数据检查。
建议用到:
- `2.47 查询企业信息`
- `2.49 查询企业开户行及账号`
- `2.45 查询数电账号列表`
- `2.8 查询数电账号认证状态`
注意事项:
- `2.49` 文档明确说明:可用于避免“企业没有维护开户行及账号导致开票失败”
- 如果票通平台和电子税局都没有维护开户行及账号,需要先提醒企业维护
- 查询电子税局开户行及账号时,要求数电账号已登录认证
### 6.5 发起开票
核心接口:
- `2.9 开具蓝字数电发票`
你的业务场景重点注意以下字段:
- `invoiceIssueKindCode`
- 农产品收购发票只能开数电普通票,建议按 `82`
- `specialInvoiceKind`
- 农产品收购发票必须传 `02`
- `invoiceReqSerialNo`
- 一张发票的唯一幂等号
- `account`
- 明确指定开票使用的数电账号
- `definedData`
- 建议传你自己的业务单号或关联标识,后续推送会原样带回
- `tradeNo`
- 可传业务订单号,不传时票通默认使用 `invoiceReqSerialNo`
农产品收购发票特别注意:
- 文档写明:`specialInvoiceKind=02` 时,只能开具数电票(普通发票)
- 文档还写明:`购方信息代表实际的销方信息,销方信息是实际的购方`
- `purchaseInvSellerIdType` 开具农产品收购发票时必填
- `buyerTaxpayerNum` 开具农产品收购发票时必填
注意事项:
- `invoiceReqSerialNo` 对同一张票重试时不能变
- 文档明确提示:如果变更同一张票的请求流水号,可能造成重开发票
- 返回里的 `qrCodePath` / `qrCode` 可用于打开 H5 实时查看开票状态
### 6.6 如果开票遇到认证
如果开票返回 `3999`,不要直接判成普通失败。
可用接口:
- `2.8 查询数电账号认证状态`
- `2.4 获取登录短信验证码`
- `2.5 短信登录`
- `2.6 获取实名认证二维码`
- `2.7 查询实名认证二维码扫码状态`
短信认证路径:
1.`2.8` 看建议
2. 如果允许短信认证,调 `2.4`
3. 再调 `2.5` 完成登录
扫码认证路径:
1.`2.6` 获取二维码
2. 展示二维码给用户
3. 轮询 `2.7` 查询扫码状态
4. 认证完成后,再继续原开票流程
注意事项:
- `2.4` 返回 `6666` 时,文档说“无需真正发送短信验证码,系统会自动登录成功”
- `2.6` 二维码一般 5 分钟左右过期
- `2.7` 文档特别提示:接口比较耗时,请调长超时时间
- `2.7``scanStatus`
- `1` 未扫码
- `2` 已扫码
- `3` 二维码已过期
### 6.7 获取开票结果
结果同步建议两条线都做。
#### 第一条:票通推送
- `2.13 推送发票主要信息`
- `2.14 推送发票全票面信息`
作用:
- 票通开票成功、失败、需要认证时,主动通知你
注意事项:
- 接口地址由你提供给票通配置
- 你返回的业务结果码:
- `0000` 接收成功
- `9999` 接收失败
#### 第二条:主动查询
- `2.11 查询发票主要信息`
- `2.12 查询发票全票面信息`
作用:
- 回调没到时兜底
- 开票中状态补偿查询
- 手动刷新状态
关键状态码:
- `0000` 开票成功
- `6666` 未开票
- `7777` 开票中
- `9999` 开票失败
- `3999` 需要扫码或短信认证
### 6.8 结果落库并回写你自己的业务系统
这一段票通不会帮你做,需要你自己做。
建议你的平台在收到 `2.13` 推送或 `2.11 / 2.12` 查询结果后:
1. 更新本地开票任务状态
2. 保存发票号码、数电发票号码、开票时间、失败原因
3. 再调用你自己的业务系统回写接口
建议你自己的回写接口至少要包含:
- 业务单号
- 公司标识
- 发票请求流水号
- 开票状态
- 票通状态码
- 票通状态描述
- 发票号码 / 数电发票号码
- 开票日期
- 金额 / 税额
- 下载地址或文件标识
## 7. 这份文档给你的最终结论
你现在最需要抓住的不是“票通有多少接口”,而是下面这条最小闭环:
1. 确认企业已入驻且已与平台绑定
2. 确认企业下有可用数电账号
3. 开票前检查认证状态和企业基础信息
4.`2.9` 发起农产品收购发票开具
5. 如遇 `3999`,走短信认证或扫码认证
6.`2.13 / 2.14` 收推送,同时用 `2.11 / 2.12` 做补偿查询
7. 最后把结果回写到你自己的业务系统
如果只按开发优先级排序,你最先应该落的接口就是:
- `2.45 查询数电账号列表`
- `2.8 查询数电账号认证状态`
- `2.9 开具蓝字数电发票`
- `2.11 查询发票主要信息`
- `2.13 推送发票主要信息`
- `2.4 / 2.5 / 2.6 / 2.7` 认证链路
对你这个项目最容易踩坑的点有 4 个:
- 农产品收购发票字段语义和普通蓝票不同,购销方字段有反转
- `invoiceReqSerialNo` 必须稳定复用,不能重试就换
- 回调地址不是请求里传的,而是提前配置给票通的
- “开票结果回写接口”不是票通接口,而是你自己的业务系统接口