# mp-service: 订单保险详情独立接口契约梳理 > **服务**: hl-mp-service(端口 8085)→ 透传 hl-order-service-v2(端口 8094) > **PR**: -(纯契约梳理,无代码变更) > **Issue**: - > **日期**: 2026-04-23 > **影响范围**: C 端「订单详情 - 服务包含 - 保险」子详情入口 --- ## ⚠️ 关键变化 **无接口变更**。本 changelog 只梳理 `GET /mp/order/{orderId}/insurance` 的入参/出参契约,方便前端对照接入。 ⚠️ **路径提醒**:Controller 类名为 `MpOrderServiceDetailController`,但 `@RequestMapping` 是 `/mp/order`(不是 `/mp/order-service`)。完整路径以本文档为准。 --- ## 一、接口基本信息 | 项 | 值 | |----|----| | 路径 | `/mp/order/{orderId}/insurance` | | 方法 | GET | | Controller | `MpOrderServiceDetailController#getInsurance` | | 返回类型 | `Result` | | 登录 | 需要(网关 token 解析 userId 透传)| | 缓存 | 无 `@MpCache` 注解 | --- ## 二、调用时机与上下游关系 | 场景 | 推荐接口 | |------|---------| | 订单详情页首屏(聚合) | `GET /mp/order/{orderId}/dashboard` → 取 `.insurance` 字段 | | 从「服务包含」列表点「保险」进子详情 | **`GET /mp/order/{orderId}/insurance`**(本接口)| | 下载保单 PDF(整单合并) | `GET /mp/insurance/policy-pdf/{orderId}` | | 下载单张保单 PDF | `GET /mp/insurance/policy/{insuranceOrderId}/download` | 两条路径返回同一个 VO(`MpInsuranceDetailVO`),字段结构一致。**不要在订单详情页同时调 dashboard 和本接口**。 `insuranceOrderId`(下载单张保单用)从本接口返回的 `policies[].insuranceOrderId` 取。 --- ## 三、入参 ### 路径参数 | 字段 | 位置 | 类型 | 必填 | 说明 | |------|------|------|------|------| | `orderId` | Path | Long | ✅ | 订单ID | ### Header | 字段 | 必填 | 说明 | |------|------|------| | 登录 token | ✅ | 由网关校验并解析出 `userId`,前端无需手动传 `userId` | --- ## 四、出参 `Result` ### 顶层 `MpInsuranceDetailVO` | 字段 | 类型 | 说明 | |------|------|------| | `schemeId` | Long | 方案ID | | `schemeName` | String | 方案名称 | | `description` | String | 方案描述 | | `isOverseas` | Boolean | 是否境外 | | `totalDays` | Integer | 适用行程天数 | | `notice` | String | 保险告知状态:`INCLUDED` / `OPTIONAL` / `EXCLUDED` | | `segments` | `List` | 保障分段列表 | | `policies` | `List` | 投保记录列表(未付款为空数组)| ### `CoverageSegment` — 保障分段(方案层) | 字段 | 类型 | 说明 | |------|------|------| | `segmentName` | String | 分段名称 | | `dayOffsetStart` | Integer | 起始天 | | `dayOffsetEnd` | Integer | 结束天(`-1` = 最后一天)| | `productName` | String | 保险产品名称 | | `planName` | String | 保险计划名称 | ### `PolicyItem` — 投保记录(订单层,已付款才有) | 字段 | 类型 | 说明 | |------|------|------| | `insuranceOrderId` | Long | 保险订单ID(下载单张保单用)| | `policyNo` | String | 保单号 | | `productName` | String | 保险产品名称 | | `planName` | String | 保险计划名称 | | `premium` | BigDecimal | 保费(元)| | `insuredCount` | Integer | 被保人数 | | `coverageStartDate` | LocalDate | 保障开始日期 | | `coverageEndDate` | LocalDate | 保障结束日期 | | `status` | String | `PENDING` / `INSURING` / `INSURED` / `FAILED`(`CANCELLED` 已由后端过滤不返回)| | `statusLabel` | String | 状态中文标签 | | `insuredPersons` | `List` | 被保人列表 | ### `InsuredPerson` — 被保人(证件/电话已脱敏) | 字段 | 类型 | 说明 | |------|------|------| | `name` | String | 姓名 | | `idCardType` | String | `ID_CARD` / `PASSPORT` | | `idCardNo` | String | 证件号码(脱敏)| | `birthday` | LocalDate | 出生日期 | | `gender` | String | `MALE` / `FEMALE` | | `phone` | String | 手机号(脱敏)| --- ## 五、响应示例 ### 已投保订单 ```json { "code": 200, "message": "成功", "success": true, "data": { "schemeId": 101, "schemeName": "境内 7 日综合保障", "description": "含意外/医疗/行李/延误", "isOverseas": false, "totalDays": 7, "notice": "INCLUDED", "segments": [ { "segmentName": "全程", "dayOffsetStart": 1, "dayOffsetEnd": -1, "productName": "平安境内旅行险", "planName": "豪华计划" } ], "policies": [ { "insuranceOrderId": 20439, "policyNo": "PICC2026042300001", "productName": "平安境内旅行险", "planName": "豪华计划", "premium": 38.00, "insuredCount": 2, "coverageStartDate": "2026-05-01", "coverageEndDate": "2026-05-07", "status": "INSURED", "statusLabel": "已生效", "insuredPersons": [ { "name": "张三", "idCardType": "ID_CARD", "idCardNo": "1101**********1234", "birthday": "1990-01-01", "gender": "MALE", "phone": "138****5678" } ] } ] } } ``` ### 未付款订单(policies 为空数组) ```json { "code": 200, "message": "成功", "success": true, "data": { "schemeId": 101, "schemeName": "境内 7 日综合保障", "isOverseas": false, "totalDays": 7, "notice": "INCLUDED", "segments": [ /* 方案分段仍有值 */ ], "policies": [] } } ``` ### 订单不含保险(notice=EXCLUDED) ```json { "code": 200, "data": { "schemeId": null, "schemeName": null, "notice": "EXCLUDED", "segments": [], "policies": [] } } ``` --- ## 六、边界行为 - 未登录 → 401(网关拦截) - `orderId` 不属于当前 userId → 业务异常,`Result.code != 200` - 订单存在但未付款 → `policies=[]`,但 `segments` / `schemeName` 仍返回(方案信息属于产品快照) - 订单不含保险(`notice=EXCLUDED`)→ `policies=[]` 且 `segments=[]` - `status=CANCELLED` 的保单 → **后端已过滤**,不会出现在 `policies` 中 --- ## 七、契约约束 - 下载单张保单时的 `insuranceOrderId` **必须**取自本接口返回的 `policies[].insuranceOrderId`,不要用 `orderId` 替代 - `dayOffsetEnd=-1` 是约定值,表示"保障到行程最后一天",非真实天数 - `premium` 是 `BigDecimal`,JSON 序列化为数字(非字符串),精度 2 位小数 --- ## 八、不影响范围 - **仅新增文档梳理**,代码零改动 - `/mp/order/{orderId}/dashboard` 聚合接口中的 `.insurance` 字段与本接口返回 VO 完全一致,两者**可互换取用** - 保单 PDF 下载两个接口(`/mp/insurance/policy-pdf/{orderId}` 和 `/mp/insurance/policy/{insuranceOrderId}/download`)与本接口是上下游关系,未做变更 --- ## 九、相关文档 - `MpOrderServiceDetailController.java`(hl-mp-service) - VO:`MpInsuranceDetailVO`(hl-mp-service + hl-order-service-v2 镜像一致) - 关联 changelog: - `2026-04-23_mp-dashboard-endpoints-timing-guide.md`(订单/行程 5 个聚合接口调用时机梳理) - `2026-04-23_mp-service_contract-insurance-api-inventory.md`(保险/合同详情 5 接口梳理)