# 通用票通开票模块设计书 ## 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 分阶段持续推进。