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

572 lines
11 KiB
Markdown

# 通用票通开票模块设计书
## 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 目录建议
```text
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 目录建议
```text
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` -> `PENDING``PROCESSING`
- `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 分阶段持续推进。