6.2 KiB
订单服务v3 接口契约审计修复(W1 钱/状态热区:金额=String + 被保人脱敏 + 退款筛选 + 投保幂等)— 修改接口 — 管理后台
变更类型:⚠️ 序列化口径变更(金额字段改 String)+ 安全收紧(PII 脱敏)+ 行为收紧(投保幂等)+ 数据补全(退款筛选/派生字段),无破坏性删除 端类型:管理后台(保险 / 订单 / 支付 / 退款 / 结算 / 调价 / 折扣 / 班期) 日期:2026-06-18 服务:hl-order-service-v3 PR:wx/HL#3965
⚠️ 关键说明
经 api-contract-audit workflow 对 order-v3 钱/状态关键热区 14 个 Controller 做语义审计(实现 ⨯ 声明契约 ⨯ 设计文档 ⨯ 7 维度业务规则)+ 对抗式复核,97 发现 → 50 确认(P0=0/P1=17/P2=19/P3=14),本批修复其中 32 条清晰契约 bug。已合并 dev-v3、部署测试服双实例(totalCodes=626)、本地全量 3566 单测零净增回归、测试服 9443 + 真 admin token 行为实测通过。
前端最需关注:第 1 条金额字段序列化口径变更(解析方式要改)。
1. 🔴 金额字段统一改为 String(解析口径变更,前端必看)
平台铁律「JSON 金额必为 String」此前在 order-v3 多处 RespVO 漏标 @JsonSerialize(ToStringSerializer),金额被序列化成 JSON number。本次全部补齐,这些字段从「数字」变为「带引号字符串」:
| 端点 | VO / 字段 |
|---|---|
GET /v3/admin/order/{id}/finance |
FinanceVO 全部金额 + 内部 payments/discounts/surcharges.amount |
GET /v3/admin/order 列表 / GET /v3/admin/order/list |
列表项 totalAmount/paidAmount/balanceAmount/depositAmount/singleRoomSurcharge |
GET /v3/admin/order/{id}/refund(退款 Tab) |
totalRefundAmount/refundAmount/amount |
POST /v3/admin/order/{id}/cancel/pre-trip、/terminate、GET /cancel-preview |
refundAmount/baselineRefund/adjustAmount/finalRefund/paidAmount/deductAmount |
GET /v3/admin/payment/list、/{transactionId}、/order/{orderId} |
PaymentTransactionVO.totalAmount / PaymentListItemRespVO.amount |
GET /v3/admin/order/{orderId}/payment/list |
amount |
GET /v3/admin/refund/{refundId} 等退款记录 |
RefundRecordVO.refundAmount/totalAmount |
| 折扣 5 端点 / 结算各保存与汇总 / 调价 / 保险方案 preview-apply / 保险方案保费 | 各金额字段 |
注:比率字段(profitRate 等)仍为数字,不受影响。
示例(支付列表):
{ "code": 200, "data": { "records": [ { "totalAmount": "1500.00" } ] } } // 此前是 1500.00(数字)
前端请用字符串解析金额(new Decimal(str) / parseFloat(str)),勿假设为 number。
2. 被保人证件号 / 手机号脱敏(安全收紧)
此前以下端点返回的 insuredPersons[].idNo / idCardNo / phone 为明文(VO 声明「脱敏」但实现直塞解密值)。本次在装配处统一脱敏(前 3 后 4,与司机险链口径一致):
| 端点 |
|---|
GET /v3/admin/insurance/orders/{id}(详情) |
GET /v3/admin/insurance/coverage/{orderId} |
GET /v3/internal/insurance/coverage/{orderId} |
POST /v3/admin/insurance/purchase / selective-purchase / orders/{id}/sync-status(返回详情) |
{ "insuredPersons": [ { "idNo": "152***********5216", "phone": "138****8000" } ] }
如管理端确需明文,需另开专用解密端点(产品决策,见 PR)。
3. 退款申请分页:筛选维度补齐 + 派生字段填充
GET /v3/admin/refund/application/page 此前声称支持多维筛选但实现全部忽略(仅分页 + createTime 倒序)。本次补齐:
- 筛选(均可选):
orderId/orderNo(模糊)/applicantName(模糊)/applicantId/status(多选)/auditStatus/createTimeFrom-createTimeTo/refundedAtFrom-refundedAtTo - 排序:
sortField(白名单 createTime/refundedAt/actualAmount)+sortOrder(ASC/DESC,默认 createTime DESC) - 派生字段填充:
reviewerNameLast(最后审核人)、refundRecordCount(退款执行记录数)此前恒 null,现批量回填 - 移除字段:
appealRoundCount(refund_appeal 表已于 V20260527_001 DROP,该字段永不可填,删除避免误导)
4. 投保幂等防护(行为收紧)
POST /v3/admin/insurance/purchase(手动投保)/ selective-purchase(选择性投保)此前无幂等/锁,重复提交会重复出单扣保费。本次加 @Idempotent + @Lock4j(按 orderId 串行 + 业务键去重),短时间内完全相同的重复请求会被拦截,前端无须额外处理但可知悉。
5. 其它(前端基本无感 / 字典对齐)
- 支付交易状态字典:
FAILED→REFUNDED(对齐枚举/DB;此前 notes/VO/DTO 写的 FAILED 实际无法存储)。状态取值:PENDING/SUCCESS/CLOSED/REFUNDED。 - 新增错误码
589516:团期共享成本录入的成本类型非法(此前抛裸异常)。 - 保单下载 notes 修正:
GET /v3/internal/insurance/policy/{id}/download返回的是 OSS 下载 URL 字符串(非 Base64),未生成返 540310 / 手工单返 540226。 - 保险方案删除:删除前引用校验只统计在途/生效保单(INSURED/INSURING),历史退保/失败单不再永久拦死删除。
- 保险方案 toggle-status:改为原子操作(消除并发读改写竞态)。
- 被保人 gender:新投保单详情正确返回性别(1=男/2=女/0=未知);修复前的历史单仍可能为 null(不回填历史)。
- 删除若干孤儿字段(保险方案 autoInsure/segmentType/destinationCode 等声明但从未赋值)。
备注
- P3 + 低置信发现暂未处理;以下产品/行为决策项未改行为,待确认:删退款政策语义(禁删 vs 软删降级)、结算 step6 金额公式与状态语义、后台建单幂等键定义、班期结算 D1/D2 返回结构、preview-apply 覆盖参数、PARTIAL 部分退款语义、transition 的 Map payload。
- 结算 step6 逻辑补全(confirmCheckHash 校验 / OrderSettledEvent MQ / Step 前置校验 / Step3 响应字段 / insurance_premium 实值)建议独立工单(P1,重型)。