新增: - changelogs-v2/2026-06/23_4290_发票申请入参票种修正-修改接口-管理后台.md - changelogs-v2-mp/2026-06/23_4290_发票申请票种修正-修改接口-小程序端.md 勘误: - 23_4258_发票详情接口:删除 mailAddress 出参字段、去掉 ELECTRONIC 枚举、email 改为始终有值 - 23_4265_发票列表:invoiceType 枚举去掉 ELECTRONIC(普票/专票两值) 契约定稿要点:invoiceType 只有 VAT_NORMAL/VAT_SPECIAL;email 始终必填+格式; 专票限 COMPANY 抬头(581523);专票五项全必填(581515);删 mailAddress(全电子交付)
12 KiB
12 KiB
发票申请票种修正(最终契约)— 小程序端
变更类型:修改接口(破坏性) 端类型:小程序端 日期:2026-06-23 | Issue:#4296 | PR:#4292 / #4302 | 服务:hl-order-service-v3
⚠️ 破坏性变更:
invoiceType删除ELECTRONIC、mailAddress字段。小程序开票页与详情页均需同步改动,上线时前后端须同步发布。
接口背景
发票模型经 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 |
| 接口名 | 小程序客户自主申请发票 |
| 描述 | 客户在订单完成后自主提交开票申请,支持普票/专票,全电子交付 |
| 认证 | 小程序 JWT(Bearer Token,C 端用户) |
| 幂等性 | 非幂等,重复提交触发 581511(一单一票) |
| 限流 | 无特殊限流 |
小程序重开接口
| 项 | 说明 |
|---|---|
| 方法 + 路径 | POST /v3/internal/mp/invoice/{id}/reissue |
| 接口名 | 小程序重新开票 |
| 描述 | 旧发票作废后,客户重新提交开票申请;入参字段矩阵与 apply 接口相同 |
| 认证 | 小程序 JWT(Bearer Token,C 端用户) |
| 幂等性 | 非幂等 |
| 限流 | 无特殊限流 |
接口入参
路径参数
apply 接口:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
orderId |
string(Long 雪花 ID) | 是 | 订单 ID |
reissue 接口:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
id |
string(Long 雪花 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 |
integer | 始终必填 | 开票金额,单位分,须 > 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
{
"invoiceType": "VAT_NORMAL",
"titleType": "PERSONAL",
"titleName": "张三",
"taxNo": null,
"amount": 98600,
"email": "zhangsan@qq.com",
"remark": "旅游报销"
}
响应:
{
"code": 200,
"msg": "success",
"data": "1934567890123456789"
}
典型成功(增值税专用发票,公司抬头,全字段)
请求:
POST /v3/internal/mp/order/1920000000000000002/invoice/apply
Authorization: Bearer <mp-token>
Content-Type: application/json
{
"invoiceType": "VAT_SPECIAL",
"titleType": "COMPANY",
"titleName": "某某科技有限公司",
"taxNo": "91310000XXXXXXXXXX",
"bankName": "招商银行上海支行",
"bankAccount": "1234567890123456",
"registAddress": "上海市浦东新区XX路XX号",
"registPhone": "021-88888888",
"amount": 298000,
"email": "finance@company.com"
}
响应:
{
"code": 200,
"msg": "success",
"data": "1934567890123456790"
}
业务失败(专票个人抬头,错误码 581523)
请求:
POST /v3/internal/mp/order/1920000000000000003/invoice/apply
Authorization: Bearer <mp-token>
Content-Type: application/json
{
"invoiceType": "VAT_SPECIAL",
"titleType": "PERSONAL",
"titleName": "李四",
"taxNo": null,
"amount": 50000,
"email": "lisi@example.com"
}
响应:
{
"code": 581523,
"msg": "增值税专用发票只能开给单位,个人抬头不可选专票",
"data": null
}
业务边界
适用场景
- 客户在小程序「我的订单 - 订单详情」中点「申请发票」,订单状态为 COMPLETED 时可用
- 旧发票被作废后,客户在小程序发起重新申请(reissue 接口)
不适用场景
- 订单未完成(非 COMPLETED 状态),返回 581510
- 已有有效发票,须先由财务作废后才能 reissue,不能再次 apply
- 管理后台代客申请走 admin 专属接口
特殊边界
- 金额单位:
amount为整数分,前端显示元时需在提交前 ×100 - 一单一票:同一订单至多一张有效发票
- 专票抬头联动:选专票后,抬头类型需强制为单位,个人选项需禁用或隐藏
- 详情回显:
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 重新可用。小程序需同步回滚开票页逻辑。
注意事项
ELECTRONIC已从枚举删除,小程序开票选项只有两项,禁止出现「电子发票」- 重开接口(reissue)入参字段矩阵与 apply 完全相同,改动同步适用
- 专票五项(taxNo + 开户行 + 账号 + 注册地址 + 注册电话)在专票场景下全必填,缺一返回 581515
- 详情页
mailAddress字段已消失,老版本小程序读到 undefined 需做好空值守卫(不报错) amount单位为分,小程序展示/输入框以元为单位时,提交前须 ×100
关联 / 联系人
| 项 | 内容 |
|---|---|
| Issue(功能) | #4290 发票申请票种修正 |
| Issue(小程序) | #4296 小程序发票申请同步修正 |
| PR(票种删 ELECTRONIC) | #4292 |
| PR(专票限公司/email 必填/删 mailAddress) | #4302 |
| 后端负责人 | yst |