diff --git a/changelogs-v2/2026-06/18_3965_订单v3接口契约审计修复W1-金额String+被保人脱敏+退款筛选+幂等-修改接口-管理后台.md b/changelogs-v2/2026-06/18_3965_订单v3接口契约审计修复W1-金额String+被保人脱敏+退款筛选+幂等-修改接口-管理后台.md new file mode 100644 index 0000000..1a39722 --- /dev/null +++ b/changelogs-v2/2026-06/18_3965_订单v3接口契约审计修复W1-金额String+被保人脱敏+退款筛选+幂等-修改接口-管理后台.md @@ -0,0 +1,97 @@ +# 订单服务v3 接口契约审计修复(W1 钱/状态热区:金额=String + 被保人脱敏 + 退款筛选 + 投保幂等)— 修改接口 — 管理后台 + +> 变更类型:⚠️ 序列化口径变更(金额字段改 String)+ 安全收紧(PII 脱敏)+ 行为收紧(投保幂等)+ 数据补全(退款筛选/派生字段),无破坏性删除 +> 端类型:管理后台(保险 / 订单 / 支付 / 退款 / 结算 / 调价 / 折扣 / 班期) +> 日期:2026-06-18 +> 服务:hl-order-service-v3 +> PR:https://git.1814.love:8443/wx/HL/pulls/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 等)仍为数字,不受影响。 + +示例(支付列表): + +```json +{ "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`(返回详情) | + +```json +{ "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,重型)。