514 lines
14 KiB
Markdown
514 lines
14 KiB
Markdown
# 票通对接业务流程说明
|
||
|
||
本文基于以下资料整理:
|
||
|
||
- [系统设计.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` 必须稳定复用,不能重试就换
|
||
- 回调地址不是请求里传的,而是提前配置给票通的
|
||
- “开票结果回写接口”不是票通接口,而是你自己的业务系统接口
|