文件
hl-api-changelog/changelogs-v2/2026-06/23_4290_发票申请入参票种修正-修改接口-管理后台.md
T
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

12 KiB
原始文件 Blame 文件历史

发票申请入参票种修正(最终契约)

变更类型:修改接口(破坏性) 端类型:管理后台 日期:2026-06-23 | Issue:#4290 | PR:#4292 / #4302 | 服务:hl-order-service-v3

⚠️ 破坏性变更:invoiceType 删除 ELECTRONIC、email 改为始终必填 + 格式校验、新增 taxNo/银行/注册信息专票五项校验、删除 mailAddress 字段、专票限 COMPANY 抬头。前端申请表单需同步改动,上线时前后端须同步发布。

勘误(截至 PR #4311 收口):抬头字段统一 titleName、金额 amount 改 JSON number(单位元,非分/×100)、票种仅 2 值(VAT_NORMAL/VAT_SPECIAL)、专票限公司抬头、入参和出参均无 mailAddress。关联 Issue #4290 #4296 #4310 / PR #4292 #4302 #4311。

勘误(截至 PR #4311 收口):抬头字段统一 titleName、金额 amount 改 JSON number(单位元,非分/x100)、票种仅 2 值(VAT_NORMAL/VAT_SPECIAL)、专票限公司抬头、入参和出参均无 mailAddress。关联 Issue #4290 #4296 #4310 / PR #4292 #4302 #4311。


接口背景

发票模型经 PR #4292 + #4302 多轮修正后定稿:删除原设计中的「电子发票」票种(业务决策统一走 VAT_NORMAL 普票),对专票收严字段校验(专票限公司抬头 + 必填五项),email 改为始终必填(全系统电子交付),删除纸质邮寄字段 mailAddress。

本文档为最终契约,与本月早前 23_4172_... 系列文件中的历史设计存在差异,以本文档为准。


变更清单

# 变更类型 说明
1 ⚠️ 删枚举值 invoiceType 删除 ELECTRONIC,只保留 VAT_NORMAL / VAT_SPECIAL
2 ⚠️ 删字段 申请入参 + 详情出参均删除 mailAddress(纸质邮寄地址)
3 ⚠️ 校验收严 email 改为始终必填(原为条件必填),并加邮箱格式校验
4 ⚠️ 新增校验 taxNo:单位抬头或专票时必填(原仅"公司抬头"须填)
5 ⚠️ 新增校验 bankName / bankAccount / registAddress / registPhone:专票必填(原无此四项限制)
6 ⚠️ 新增错误码 581523 专票只能开给单位(titleType 须 COMPANY)
7 ✨ 行为明确 VAT_SPECIAL 自动限 COMPANY 抬头,个人选专票被拒(581523)

接口详情

管理后台申请接口

项 说明
方法 + 路径 POST /v3/admin/order/{orderId}/invoice/apply
接口名 管理后台代客申请发票
描述 财务或定制师代客提交开票申请,支持普票/专票,全电子交付
认证 管理后台 JWT(Bearer Token)
幂等性 非幂等,重复提交触发 581511(一单一票)
限流 无特殊限流

接口入参

路径参数

参数名 类型 必填 说明
orderId 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 number 始终必填 开票金额,JSON number,单位元(如 986.00),须 > 0 且 ≤ 订单总金额
email string 始终必填 收件邮箱,全电子交付,须通过邮箱格式校验
remark string 选填 申请备注
applyReason string 选填 申请原因(与 remark 二选一或并用)

⚠️ mailAddress 字段已删除,后端不接收,填了也忽略。


出参字段

返回结构:Result<Long> — 返回新建发票 ID(字符串,雪花 ID)。

字段名 类型 说明
data string 新建发票 ID,如 "1934567890123456789"

枚举 / 数据字典

发票类型(invoiceType)

枚举值 中文名 校验规则
VAT_NORMAL 增值税普通发票 bankName / bankAccount / registAddress / registPhone 均不需要
VAT_SPECIAL 增值税专用发票 taxNo + 银行四项均必填,且 titleType 必须 COMPANY

ELECTRONIC 已删除,禁止传入(传入返回 581513)。

抬头类型(titleType)

枚举值 中文名 限制
COMPANY 单位 普票/专票均可
PERSONAL 个人 只能选 VAT_NORMAL,选 VAT_SPECIAL 返回 581523

错误码

错误码 含义 触发场景
581510 订单未完成,不可开票 订单状态不是 COMPLETED
581511 一单一票,已有有效发票 该订单已存在 REQUESTED / ISSUED / PUSHED 状态发票
581512 开票金额超订单总额 amount > 订单 orderAmount
581513 发票类型非法 invoiceType 不是 VAT_NORMAL 或 VAT_SPECIAL
581514 公司抬头或专票须填税号 titleType=COMPANY 或 invoiceType=VAT_SPECIAL 时 taxNo 为空
581515 专票须填银行及注册信息 invoiceType=VAT_SPECIAL 时 taxNo / bankName / bankAccount / registAddress / registPhone 任一为空
581516 收件邮箱不能为空 入参层 @NotBlank,返回 HTTP 400「收件邮箱不能为空」;格式错误返回 400「邮箱格式不正确」
581523 专票只能开给单位 invoiceType=VAT_SPECIAL 且 titleType=PERSONAL
401 未授权 未携带有效 JWT
403 无权限 当前账号无发票申请权限

注意:581516 在入参校验层(@NotBlank / @Email)返回 HTTP 400,不走业务错误码;581513~581523 走 BusinessException 返回 200 包体。


示例

典型成功(增值税普通发票,个人抬头)

请求:

POST /v3/admin/order/1920000000000000001/invoice/apply
Authorization: Bearer <token>
Content-Type: application/json
{
  "invoiceType": "VAT_NORMAL",
  "titleType": "PERSONAL",
  "titleName": "李四",
  "taxNo": null,
  "amount": 986.00,
  "email": "lisi@example.com",
  "remark": "报销使用"
}

响应:

{
  "code": 200,
  "msg": "success",
  "data": "1934567890123456789"
}

典型成功(增值税专用发票,公司抬头,全字段)

请求:

POST /v3/admin/order/1920000000000000002/invoice/apply
Authorization: Bearer <token>
Content-Type: application/json
{
  "invoiceType": "VAT_SPECIAL",
  "titleType": "COMPANY",
  "titleName": "某某贸易有限公司",
  "taxNo": "91310000YYYYYYYYYY",
  "bankName": "工商银行上海支行",
  "bankAccount": "6222000000000001",
  "registAddress": "上海市浦东新区XX路XX号",
  "registPhone": "021-12345678",
  "amount": 1500.00,
  "email": "finance@company.com",
  "remark": null
}

响应:

{
  "code": 200,
  "msg": "success",
  "data": "1934567890123456790"
}

业务失败(专票个人抬头被拒,错误码 581523)

请求:

POST /v3/admin/order/1920000000000000003/invoice/apply
Authorization: Bearer <token>
Content-Type: application/json
{
  "invoiceType": "VAT_SPECIAL",
  "titleType": "PERSONAL",
  "titleName": "张三",
  "taxNo": null,
  "amount": 500.00,
  "email": "zhangsan@example.com"
}

响应:

{
  "code": 581523,
  "msg": "增值税专用发票只能开给单位,个人抬头不可选专票",
  "data": null
}

业务边界

适用场景

  • 财务在「发票管理 - 未申请 tab」找到已完成订单,代客提交开票申请
  • 定制师在订单详情页为客户发起申请

不适用场景

  • 重新开票(走 POST /v3/admin/order/invoice/{id}/reissue 重开接口,入参相同)
  • 小程序客户自主申请(走小程序端专属接口 POST /v3/internal/mp/order/{orderId}/invoice/apply)

特殊边界

  • 一单一票:同一订单只允许一张有效发票(REQUESTED / ISSUED / PUSHED 状态),若已有则返回 581511,须先作废旧发票再申请
  • 订单状态:仅 COMPLETED(已完成)状态订单可申请,其他状态返回 581510
  • 金额单位:amount 为 JSON number,单位元(如 986.00),>0,≤ 订单总金额;前端输入框以元为单位直接提交,无需 ×100

修改前后对比

发票类型(invoiceType 枚举)

旧值(历史设计) 新值(最终实现)
VAT_NORMAL 增值税普通发票 VAT_NORMAL 增值税普通发票(保留)
VAT_SPECIAL 增值税专用发票 VAT_SPECIAL 增值税专用发票(保留)
ELECTRONIC 电子发票 已删除,禁止传入

email 字段

旧行为 新行为
条件必填(电子发票时必填,普票/专票选填) 始终必填 + 邮箱格式校验(全电子交付)

mailAddress 字段

旧行为 新行为
纸质发票邮寄地址(选填) 已删除(无纸质邮寄,全电子交付)

专票校验

旧行为 新行为
无 titleType 限制 专票只能 COMPANY(个人返回 581523)
bankName 等四项无强制 专票 bankName / bankAccount / registAddress / registPhone 全部必填(返回 581515)

影响评估 / 回滚

破坏兼容性评估(前端申请表单必须改动)

模块 必须改动
发票类型下拉 去掉「电子发票」选项,只保留「增值税普通发票」/「增值税专用发票」
专票表单区块 新增开户行、银行账号、注册地址、注册电话 4 个必填输入框,仅在选专票时显示
抬头类型联动 选专票时,抬头类型只能选「单位」,隐藏或禁用「个人」选项
email 字段 改为始终必填,加邮箱格式校验(正则或 HTML input type=email)
mailAddress 字段 移除,不再向后端传此字段

回滚方案

后端回滚至 #4292 前版本后,ELECTRONIC 枚举值重新有效,email 恢复条件必填,mailAddress 重新可用。前端需同步回滚或做前向兼容处理。


注意事项

  1. ELECTRONIC 枚举值已删除,前端下拉不可出现此选项;老订单历史数据如有该枚举值,出参展示时可显示「未知类型」或联系后端处理
  2. email 无论票种均必填,前端不可根据票种做条件隐藏
  3. 专票表单区块(税号 + 开户行 + 账号 + 注册地址 + 注册电话)共 5 个字段,在选专票时全部必填,不可缺任何一项
  4. amount 为 JSON number,单位元(如 986.00),前端输入框直接传元值,无需 ×100;后端已按元存储和校验

关联 / 联系人

项 内容
Issue(功能) #4290 发票申请票种修正
Issue(小程序) #4296 小程序发票申请同步修正
PR(票种删 ELECTRONIC) #4292
PR(专票限公司/email 必填/删 mailAddress) #4302
后端负责人 yst