hl-api-changelog/changelogs-v2-mp/2026-06/23_4290_发票申请票种修正-修改接口-小程序端.md
yaosutu f85aa74eb5 docs(发票): PR #4311 收口——4份发票 changelog 勘误(amount 改 JSON number 元)
修正范围:
- 23_4290_发票申请入参票种修正-修改接口-管理后台.md
- 23_4290_发票申请票种修正-修改接口-小程序端.md
- 23_4258_发票详情接口-新增接口-管理后台.md
- 23_4265_发票列表page结构调整-修改接口-管理后台.md

主要变更(4份文件均已对齐最终线上契约):
1. amount 入参/出参全部改为 JSON number(单位元,如 986.00),
   原「integer 分/字符串分/×100」描述已作废
2. 各文件顶部勘误节追加「截至 PR #4311 收口」条目,
   关联 Issue #4290/#4296/#4310、PR #4292/#4302/#4311
3. 详情接口边界示例:专票 email 由 null 改为始终有值(全电子交付)
4. 列表接口:records.amount 和 stats.amount 均改为 number 类型
2026-06-23 17:09:06 +08:00

337 行
12 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

# 发票申请票种修正(最终契约)— 小程序端
> 变更类型:修改接口(破坏性)
> 端类型:小程序端
> 日期2026-06-23 | Issue#4296 | PR#4292 / #4302 | 服务hl-order-service-v3
> ⚠️ **破坏性变更**`invoiceType` 删除 `ELECTRONIC`、`email` 改为始终必填 + 格式校验、专票限公司抬头 + 必填五项、删除 `mailAddress` 字段。小程序开票页与详情页均需同步改动,上线时前后端须同步发布。
> **勘误(截至 PR #4311 收口)**:抬头字段统一 `titleName`、金额 `amount` 改 JSON number单位元,非分/x100、票种仅 2 值(`VAT_NORMAL`/`VAT_SPECIAL`)、专票限公司抬头、入参和出参均无 `mailAddress`。关联 Issue [#4290](https://git.1814.love:8443/wx/HL/issues/4290) [#4296](https://git.1814.love:8443/wx/HL/issues/4296) [#4310](https://git.1814.love:8443/wx/HL/issues/4310) / PR [#4292](https://git.1814.love:8443/wx/HL/pulls/4292) [#4302](https://git.1814.love:8443/wx/HL/pulls/4302) [#4311](https://git.1814.love:8443/wx/HL/pulls/4311)。
---
## 接口背景
发票模型经 PR #4292 + #4302 多轮修正后定稿:删除「电子发票」票种(业务决策统一走普票),专票收严字段校验(限公司抬头 + 必填银行注册信息,email 改为始终必填(全系统电子交付),删除纸质邮寄字段 `mailAddress`
本次涉及小程序两个接口:初次申请 `POST /v3/internal/mp/order/{orderId}/invoice/apply` 和重新开票 `POST /v3/internal/mp/invoice/{id}/reissue`,入参字段矩阵相同,出参亦做同步修正(删 `mailAddress`,invoiceType 去 ELECTRONIC
---
## 变更清单
| # | 变更类型 | 说明 |
|---|---------|------|
| 1 | ⚠️ 申请入参删枚举值 | `invoiceType` 删除 `ELECTRONIC`,只保留 `VAT_NORMAL` / `VAT_SPECIAL` |
| 2 | ⚠️ 申请入参删字段 | 删除 `mailAddress`(纸质邮寄地址) |
| 3 | ⚠️ 申请入参校验收严 | `email` 改为始终必填 + 邮箱格式校验 |
| 4 | ⚠️ 申请入参校验新增 | `taxNo`:单位抬头或专票时必填 |
| 5 | ⚠️ 申请入参校验新增 | 专票:`bankName` / `bankAccount` / `registAddress` / `registPhone` 四项必填 |
| 6 | ⚠️ 申请入参新增错误码 | `581523` 专票只能开给单位 |
| 7 | ⚠️ 详情出参删字段 | `GET /v3/internal/mp/order/{orderId}/invoice/detail` 出参删除 `mailAddress` |
| 8 | ⚠️ 列表出参枚举收窄 | `GET /v3/internal/mp/order/{orderId}/invoice/list` 出参 invoiceType 不再出现 ELECTRONIC |
| 9 | 重开接口同步 | `POST /v3/internal/mp/invoice/{id}/reissue` 入参字段矩阵与申请接口保持一致 |
---
## 接口详情
### 小程序申请接口
| 项 | 说明 |
|---|------|
| **方法 + 路径** | `POST /v3/internal/mp/order/{orderId}/invoice/apply` |
| **接口名** | 小程序客户自主申请发票 |
| **描述** | 客户在订单完成后自主提交开票申请,支持普票/专票,全电子交付 |
| **认证** | 小程序 JWTBearer Token,C 端用户) |
| **幂等性** | 非幂等,重复提交触发 581511一单一票 |
| **限流** | 无特殊限流 |
### 小程序重开接口
| 项 | 说明 |
|---|------|
| **方法 + 路径** | `POST /v3/internal/mp/invoice/{id}/reissue` |
| **接口名** | 小程序重新开票 |
| **描述** | 旧发票作废后,客户重新提交开票申请;入参字段矩阵与 apply 接口相同 |
| **认证** | 小程序 JWTBearer Token,C 端用户) |
| **幂等性** | 非幂等 |
| **限流** | 无特殊限流 |
---
## 接口入参
### 路径参数
**apply 接口:**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `orderId` | stringLong 雪花 ID | 是 | 订单 ID |
**reissue 接口:**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `id` | stringLong 雪花 ID | 是 | 被重开的旧发票 ID |
### 请求体字段(两接口共用)
| 字段名 | 类型 | 必填条件 | 说明 |
|--------|------|---------|------|
| `invoiceType` | string | 始终必填 | 发票类型:`VAT_NORMAL`(普票)/ `VAT_SPECIAL`(专票);**不含 ELECTRONIC** |
| `titleType` | string | 始终必填 | 抬头类型:`COMPANY`(单位)/ `PERSONAL`(个人);**VAT_SPECIAL 只能 COMPANY** |
| `titleName` | string | 始终必填 | 发票抬头 |
| `taxNo` | string | `titleType=COMPANY``invoiceType=VAT_SPECIAL` 时必填 | 纳税人识别号 |
| `bankName` | string | `invoiceType=VAT_SPECIAL` 时必填 | 开户银行 |
| `bankAccount` | string | `invoiceType=VAT_SPECIAL` 时必填 | 银行账号 |
| `registAddress` | string | `invoiceType=VAT_SPECIAL` 时必填 | 注册地址 |
| `registPhone` | string | `invoiceType=VAT_SPECIAL` 时必填 | 注册电话 |
| `amount` | number | 始终必填 | 开票金额,JSON number,单位**元**(如 `986.00`),须 > 0 且不超过订单总金额 |
| `email` | string | 始终必填 | 收件邮箱,须通过邮箱格式校验 |
| `remark` | string | 选填 | 备注 |
> ⚠️ `mailAddress` 字段**已删除**,不再接收。
---
## 出参字段
### apply / reissue 接口出参
返回结构:`Result<Long>`
| 字段名 | 类型 | 说明 |
|--------|------|------|
| `data` | string | 新建/重开发票 ID,字符串雪花 ID |
### 发票详情出参变化GET /v3/internal/mp/order/{orderId}/invoice/detail
| 字段名 | 变化 | 说明 |
|--------|------|------|
| `mailAddress` | **已删除** | 原出参中此字段已移除,前端不应再渲染邮寄地址 |
| `invoiceType` | 值范围收窄 | 只会出现 `VAT_NORMAL` / `VAT_SPECIAL`,不再出现 `ELECTRONIC` |
| `email` | 始终有值 | 原可能为 null,现始终有值 |
---
## 枚举 / 数据字典
### 发票类型invoiceType
| 枚举值 | 中文名 | 适用抬头 | 专票字段要求 |
|--------|--------|---------|------------|
| `VAT_NORMAL` | 增值税普通发票 | COMPANY / PERSONAL | 专票四项均不需要 |
| `VAT_SPECIAL` | 增值税专用发票 | **仅 COMPANY** | taxNo + bankName + bankAccount + registAddress + registPhone 全必填 |
> ~~`ELECTRONIC`~~ 已删除,不得传入。
### 抬头类型titleType
| 枚举值 | 中文名 | 可选票种 |
|--------|--------|---------|
| `COMPANY` | 单位 | VAT_NORMAL / VAT_SPECIAL |
| `PERSONAL` | 个人 | 只能 VAT_NORMAL,选 VAT_SPECIAL 返回 581523 |
---
## 错误码
| 错误码 | 含义 | 触发场景 |
|--------|------|---------|
| `581510` | 订单未完成,不可开票 | 订单状态不是 COMPLETED |
| `581511` | 一单一票,已有有效发票 | 已有 REQUESTED / ISSUED / PUSHED 状态发票 |
| `581512` | 开票金额超订单总额 | `amount` > 订单 `orderAmount` |
| `581513` | 发票类型非法 | `invoiceType` 不是 VAT_NORMAL 或 VAT_SPECIAL |
| `581514` | 公司抬头或专票须填税号 | 单位抬头或专票时 `taxNo` 为空 |
| `581515` | 专票须填银行及注册信息 | 专票时任一四项为空 |
| `581516` | 收件邮箱不能为空 | HTTP 400,入参层 @NotBlank 校验;格式错误返回 400「邮箱格式不正确」 |
| `581523` | 专票只能开给单位 | `invoiceType=VAT_SPECIAL``titleType=PERSONAL` |
| `401` | 未授权 | 未携带有效 JWT |
| `403` | 无权限 / 越权 | 非订单归属用户操作 |
---
## 示例
### 典型成功(增值税普通发票,个人抬头)
请求:
```
POST /v3/internal/mp/order/1920000000000000001/invoice/apply
Authorization: Bearer <mp-token>
Content-Type: application/json
```
```json
{
"invoiceType": "VAT_NORMAL",
"titleType": "PERSONAL",
"titleName": "张三",
"taxNo": null,
"amount": 986.00,
"email": "zhangsan@qq.com",
"remark": "旅游报销"
}
```
响应:
```json
{
"code": 200,
"msg": "success",
"data": "1934567890123456789"
}
```
### 典型成功(增值税专用发票,公司抬头,全字段)
请求:
```
POST /v3/internal/mp/order/1920000000000000002/invoice/apply
Authorization: Bearer <mp-token>
Content-Type: application/json
```
```json
{
"invoiceType": "VAT_SPECIAL",
"titleType": "COMPANY",
"titleName": "某某科技有限公司",
"taxNo": "91310000XXXXXXXXXX",
"bankName": "招商银行上海支行",
"bankAccount": "1234567890123456",
"registAddress": "上海市浦东新区XX路XX号",
"registPhone": "021-88888888",
"amount": 2980.00,
"email": "finance@company.com"
}
```
响应:
```json
{
"code": 200,
"msg": "success",
"data": "1934567890123456790"
}
```
### 业务失败(专票个人抬头,错误码 581523
请求:
```
POST /v3/internal/mp/order/1920000000000000003/invoice/apply
Authorization: Bearer <mp-token>
Content-Type: application/json
```
```json
{
"invoiceType": "VAT_SPECIAL",
"titleType": "PERSONAL",
"titleName": "李四",
"taxNo": null,
"amount": 500.00,
"email": "lisi@example.com"
}
```
响应:
```json
{
"code": 581523,
"msg": "增值税专用发票只能开给单位,个人抬头不可选专票",
"data": null
}
```
---
## 业务边界
**适用场景**
- 客户在小程序「我的订单 - 订单详情」中点「申请发票」,订单状态为 COMPLETED 时可用
- 旧发票被作废后,客户在小程序发起重新申请reissue 接口)
**不适用场景**
- 订单未完成(非 COMPLETED 状态),返回 581510
- 已有有效发票,须先由财务作废后才能 reissue,不能再次 apply
- 管理后台代客申请走 admin 专属接口
**特殊边界**
- 金额单位:`amount` 为 JSON number,单位**元**(如 `986.00`),前端输入框以元为单位直接提交,无需 x100
- 一单一票:同一订单至多一张有效发票
- 专票抬头联动:选专票后,抬头类型需强制为单位,个人选项需禁用或隐藏
- 详情回显:`mailAddress` 字段已不存在,前端不应渲染邮寄地址块
---
## 修改前后对比
### 发票类型枚举
| 旧值 | 新值 |
|------|------|
| VAT_NORMAL保留 | VAT_NORMAL保留 |
| VAT_SPECIAL保留 | VAT_SPECIAL保留 |
| ELECTRONIC电子发票 | **已删除** |
### email 字段校验
| 旧行为 | 新行为 |
|--------|--------|
| 条件必填ELECTRONIC 时才必填) | **始终必填 + 邮箱格式校验** |
### mailAddress 字段
| 旧行为 | 新行为 |
|--------|--------|
| 申请入参可选填;详情/列表出参包含此字段 | **申请入参已删除;详情出参已删除** |
### 专票限制
| 旧行为 | 新行为 |
|--------|--------|
| titleType 无限制 | 专票只能 COMPANY个人返回 581523 |
| bankName 等无强制要求 | 专票 taxNo + 银行四项全部必填(返回 581515 |
---
## 影响评估 / 回滚
### 小程序开票页必须改动
| 模块 | 必须改动 |
|------|---------|
| 发票类型选择 | 去掉「电子发票」,只保留「增值税普通发票」/「增值税专用发票」 |
| 专票表单区块 | 新增开户行、银行账号、注册地址、注册电话 4 个必填项,仅选专票时显示 |
| 抬头类型联动 | 选专票时隐藏/禁用「个人」选项 |
| email 输入框 | 改为必填(加红星),增加邮箱格式校验 |
| mailAddress 输入框 | 移除,不再渲染邮寄地址块 |
| 详情页 | 移除邮寄地址展示区,invoiceType 显示只有普票/专票两种文案 |
### 回滚方案
后端回滚至 PR #4292 前,ELECTRONIC 重新有效,email 恢复条件必填,mailAddress 重新可用。小程序需同步回滚开票页逻辑。
---
## 注意事项
1. `ELECTRONIC` 已从枚举删除,小程序开票选项只有两项,禁止出现「电子发票」
2. 重开接口reissue入参字段矩阵与 apply 完全相同,改动同步适用
3. 专票五项taxNo + 开户行 + 账号 + 注册地址 + 注册电话)在专票场景下全必填,缺一返回 581515
4. 详情页 `mailAddress` 字段已消失,老版本小程序读到 undefined 需做好空值守卫(不报错)
5. `amount` 为 JSON number,单位**元**(如 `986.00`),小程序输入框直接传元值,无需 x100
---
## 关联 / 联系人
| 项 | 内容 |
|----|------|
| **Issue功能** | [#4290 发票申请票种修正](https://git.1814.love:8443/wx/HL/issues/4290) |
| **Issue小程序** | [#4296 小程序发票申请同步修正](https://git.1814.love:8443/wx/HL/issues/4296) |
| **PR票种删 ELECTRONIC** | [#4292](https://git.1814.love:8443/wx/HL/pulls/4292) |
| **PR专票限公司/email 必填/删 mailAddress** | [#4302](https://git.1814.love:8443/wx/HL/pulls/4302) |
| **后端负责人** | yst |