Files
Ticket/history/通用票通开票模块设计书.md
2026-05-07 10:25:02 +08:00

11 KiB

通用票通开票模块设计书

1. 设计目标

结论:可以,而且我认为这是一个很适合当前阶段的做法。

在不先对接你现有业务系统待开票数据的前提下,可以先建设一个“通用票通开票模块”,目标是:

  • 先把票通接口、加密签名、认证流程、开票状态流转跑通
  • 先验证票通联调、测试账号、测试税号、回调、查询这些关键链路
  • 先形成一个独立可用的开票能力层
  • 后续再把你自己的待开票数据、锁单、回写逻辑接到这个能力层上

也就是说,第一阶段把系统拆成两层:

  • 通用票通开票层
  • 业务系统适配层

当前先只做第一层。

2. 为什么适合先这样做

先做通用票通模块有 5 个好处:

  • 把最大不确定性先消化掉:票通联调、认证、回调、状态码
  • 不被你现有业务系统接口进度卡住
  • 可以先做出可演示、可测试、可验收的开票闭环
  • 后续接你自己的平台时,改动集中在“数据映射”和“回写适配”
  • 更适合 Codex 分阶段落地,每次任务可以更聚焦

这条路线本质上是先做:

  • 票通能力产品

再做:

  • 你自己业务平台的票通接入

3. 系统定位

这个模块在一期不关心“待开票数据来自哪里”,只关心:

  • 用户手工录入或粘贴开票数据
  • 系统把数据转换成票通标准报文
  • 系统调用票通完成开票
  • 系统处理认证、查询、回调、重试

所以它不是“农产品收购发票业务平台完整体”,而是一个:

  • 通用票通开票控制台

它先支持:

  • 企业和数电账号准备
  • 手工发起蓝字开票
  • 查看开票任务
  • 处理短信/扫码认证
  • 查看开票结果

后续再扩展:

  • 对接你自己的待开票业务单据
  • 自动锁单
  • 自动结果回写

4. 一期范围

一期只做“纯票通能力闭环”,不做以下内容:

  • 不对接你现有业务系统待开票列表
  • 不做你自己的业务锁单/预写库
  • 不做你自己的业务结果回写
  • 不做复杂经营报表
  • 不做红冲

一期只保留这些能力:

  1. 企业信息查询
  2. 数电账号维护/查询
  3. 认证状态查询
  4. 短信认证
  5. 扫码认证
  6. 手工录入开票信息
  7. 发起蓝字开票
  8. 查询开票状态
  9. 接收票通推送
  10. 查看开票任务与结果

5. 核心业务流程

5.1 初始化准备

  1. 录入或查询开票企业税号
  2. 查询企业是否已在票通开通
  3. 查询企业下可用数电账号
  4. 选择一个开票账号
  5. 查询该账号当前认证状态

5.2 手工开票

  1. 用户在页面上录入开票信息
  2. 系统校验必填字段
  3. 系统生成 invoiceReqSerialNo
  4. 系统调用 invoiceBlue.pt
  5. 记录本地开票任务
  6. 返回初始结果

5.3 认证处理

如果票通返回需要认证:

  1. 查询认证建议
  2. 根据返回结果进入短信认证或扫码认证
  3. 认证完成后继续原开票任务
  4. 复用原 invoiceReqSerialNo

5.4 结果同步

结果同步同时走两条线:

  • 票通推送
  • 主动查询

处理原则:

  • 推送优先
  • 查询补偿
  • 状态幂等更新

6. 功能模块设计

建议先做 4 个模块。

6.1 企业与账号模块

作用:

  • 查询票通企业信息
  • 查询企业开户行及账号信息
  • 查询数电账号列表
  • 维护本地默认开票账号

建议菜单:

  • 票通企业
  • 数电账号

6.2 认证中心模块

作用:

  • 查询账号认证状态
  • 发送短信验证码
  • 提交短信登录
  • 获取实名认证二维码
  • 查询二维码扫码状态
  • 执行退出电子税局登录

建议菜单:

  • 认证中心

6.3 通用开票模块

作用:

  • 手工录入发票信息
  • 支持普通蓝字数电票
  • 支持农产品收购发票
  • 生成标准开票任务
  • 发起票通开票

建议菜单:

  • 手工开票

6.4 开票任务模块

作用:

  • 查看任务状态
  • 查看票通返回信息
  • 查看发票号码、数电发票号码
  • 查看失败原因
  • 手动查询状态
  • 重试失败任务

建议菜单:

  • 开票任务

7. 页面设计

建议新增 5 个页面。

7.1 票通企业页

展示内容:

  • 企业税号
  • 企业名称
  • 审核状态
  • 开通票种
  • 服务状态

操作:

  • 查询企业信息
  • 查询开户行及账号信息

7.2 数电账号页

展示内容:

  • 数电账号
  • 姓名
  • 身份类型
  • 认证状态
  • 登录状态
  • 风险认证状态
  • 是否绑定公众号

操作:

  • 查询账号列表
  • 登记账号
  • 设为默认账号

7.3 认证中心页

展示内容:

  • 当前认证建议
  • 当前认证状态
  • 短信验证码状态
  • 二维码状态

操作:

  • 查询认证状态
  • 发送短信验证码
  • 提交短信登录
  • 获取扫码二维码
  • 轮询扫码状态
  • 退出登录

7.4 手工开票页

展示内容:

  • 基本信息表单
  • 购买方信息
  • 销方信息
  • 开票项目明细
  • 农产品收购发票专用字段

操作:

  • 保存草稿
  • 发起开票
  • 清空表单

7.5 开票任务页

展示内容:

  • 发票请求流水号
  • 企业税号
  • 数电账号
  • 发票种类
  • 状态
  • 失败原因
  • 发票号码
  • 数电发票号码
  • 开票时间

操作:

  • 查看详情
  • 查询最新状态
  • 重新发起查询
  • 失败后重试

8. 后端设计

8.1 目录建议

server/src/main/kotlin/com/bbit/platform/
  database/piaotong/
    PtInvoiceJobTable.kt
    PtInvoiceJobItemTable.kt
    PtTaxAccountTable.kt
    PtCallbackLogTable.kt

  integration/piaotong/
    PiaotongClient.kt
    PiaotongCrypto.kt
    PiaotongDtos.kt
    PiaotongMapper.kt

  modules/piaotong/company/
    PtCompanyModule.kt

  modules/piaotong/account/
    PtAccountModule.kt

  modules/piaotong/auth/
    PtAuthModule.kt

  modules/piaotong/invoice/
    PtInvoiceModule.kt

  modules/piaotong/task/
    PtTaskModule.kt

  modules/piaotong/callback/
    PtCallbackModule.kt

8.2 后端接口建议

企业与账号

  • GET /api/piaotong/company/{taxpayerNum}
  • GET /api/piaotong/company/{taxpayerNum}/bank-info
  • GET /api/piaotong/accounts
  • POST /api/piaotong/accounts/register
  • PUT /api/piaotong/accounts/{id}/default

认证

  • GET /api/piaotong/accounts/{account}/auth-status
  • POST /api/piaotong/accounts/{account}/sms-code
  • POST /api/piaotong/accounts/{account}/sms-login
  • POST /api/piaotong/accounts/{account}/auth-qrcode
  • GET /api/piaotong/accounts/{account}/auth-qrcode/{authId}
  • POST /api/piaotong/accounts/{account}/logout

开票

  • POST /api/piaotong/invoices
  • POST /api/piaotong/invoices/validate
  • GET /api/piaotong/invoices/{jobId}
  • POST /api/piaotong/invoices/{jobId}/query
  • POST /api/piaotong/invoices/{jobId}/retry

推送

  • POST /api/callbacks/piaotong/invoice-summary
  • POST /api/callbacks/piaotong/invoice-detail

9. 前端设计

9.1 目录建议

web/src/
  api/piaotong/
    company.ts
    account.ts
    auth.ts
    invoice.ts
    task.ts

  types/piaotong/
    company.ts
    account.ts
    auth.ts
    invoice.ts
    task.ts

  features/piaotong/
    company/index.vue
    accounts/index.vue
    auth-center/index.vue
    invoice-create/index.vue
    tasks/index.vue

  components/piaotong/
    InvoiceItemEditor.vue
    InvoicePreviewCard.vue
    AuthQrcodePanel.vue
    InvoiceStatusTag.vue

9.2 菜单建议

新增一级菜单:

  • 票通开票

二级菜单建议:

  • 票通企业
  • 数电账号
  • 认证中心
  • 手工开票
  • 开票任务

10. 数据库设计

10.1 pt_tax_account

保存:

  • 企业税号
  • 数电账号
  • 姓名
  • 身份类型
  • 默认账号标记
  • 最近认证状态
  • 最近登录状态
  • 最近风险认证状态

10.2 pt_invoice_job

保存:

  • 任务 ID
  • 企业税号
  • 数电账号
  • 发票请求流水号
  • 发票类型
  • 特殊票种
  • 状态
  • 票通状态码
  • 状态描述
  • 发票号码
  • 数电发票号码
  • 开票日期
  • 金额
  • 税额
  • 原始请求
  • 原始响应

10.3 pt_invoice_job_item

保存:

  • 所属任务
  • 商品名称
  • 税编
  • 数量
  • 单价
  • 金额
  • 税率
  • 税额

10.4 pt_callback_log

保存:

  • 回调类型
  • 回调时间
  • 回调报文
  • 验签结果
  • 处理结果

11. 状态设计

建议本地状态统一为:

  • DRAFT
  • PENDING
  • PROCESSING
  • NEED_AUTH
  • SUCCESS
  • FAILED

票通状态映射建议:

  • 0000 -> SUCCESS
  • 6666 -> PENDINGPROCESSING
  • 7777 -> PROCESSING
  • 3999 -> NEED_AUTH
  • 9999 -> FAILED

12. 关键接口映射

一期建议优先实现以下票通接口:

  • 2.45 查询数电账号列表
  • 2.8 查询数电账号认证状态
  • 2.9 开具蓝字数电发票
  • 2.11 查询发票主要信息
  • 2.13 推送发票主要信息
  • 2.4 获取登录短信验证码
  • 2.5 短信登录
  • 2.6 获取实名认证二维码
  • 2.7 查询实名认证二维码扫码状态
  • 2.47 查询企业信息
  • 2.49 查询企业开户行及账号

可选补充:

  • 2.3 数电账号登记
  • 2.12 查询发票全票面信息
  • 2.14 推送发票全票面信息
  • 2.46 退出电子税局登录

13. 农产品收购发票特别说明

虽然这是“通用票通开票模块”,但你这个项目核心还是农产品收购发票,所以一期最好直接支持它。

需要特别处理:

  • specialInvoiceKind=02
  • 只能开数电普通票
  • purchaseInvSellerIdType 必填
  • buyerTaxpayerNum 必填
  • 购销双方字段语义与普通发票不同

建议做法:

  • 表单层支持“普通票模式”和“农产品收购模式”切换
  • 由后端统一做字段映射和报文转换

14. 与后续业务系统对接的衔接方式

后续如果接你自己的待开票平台,不推翻这套设计,只是增加一层适配。

后续新增的只会是:

  • 待开票列表读取
  • 业务单据锁定
  • 开票任务自动创建
  • 结果回写业务系统

也就是说,后续结构会变成:

  • 你的业务平台 -> 通用票通开票模块 -> 票通

而不是重新写一套票通集成。

15. 推荐实施顺序

建议按下面顺序推进:

第一阶段

  • 建票通企业页
  • 建数电账号页
  • 打通企业查询、账号查询、认证状态查询

第二阶段

  • 建认证中心
  • 打通短信认证、扫码认证

第三阶段

  • 建手工开票页
  • 打通蓝字开票
  • 建开票任务页

第四阶段

  • 接票通推送
  • 做主动查询补偿
  • 做重试

16. 最终结论

可以先不接你自己的待开票数据,先单独构建一个“通用票通开票模块”,而且这条路线很合理。

我建议把它当成:

  • 票通能力底座

先完成这个底座,再把你的业务系统往上挂。这样后续不管接待开票列表、锁单、回写,都会顺很多,也更适合 Codex 分阶段持续推进。