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