mp-service: 保险/合同详情 5 个接口梳理 + 合同接口返回值强类型化
服务 hl-mp-service(端口 8085)→ 透传 hl-order-service-v2(端口 8094)
PR: wx/HL#1314 · Issue: wx/HL#1312
日期: 2026-04-23
影响范围: C 端「订单详情页」保险详情弹窗、合同详情、保单 PDF 下载
⚠️ 关键变化
合同相关 3 个接口(GET /mp/contract/list / GET /mp/contract/{id} / GET /mp/contract/by-order/{orderId})的返回值类型从后端弱类型 Map<String, Object> 改为具名 VO(MpContractVO / MpContractDetailVO)。JSON 结构与字段名均未改变,Swagger 上能看到具名 schema 了,前端无需改动;本 changelog 重点是一次性把这 5 个接口契约梳理清楚。
一、接口清单
| # |
接口 |
方法 |
路径 |
返回类型 |
| 1 |
订单详情聚合(含保险详情) |
GET |
/mp/order/{orderId}/dashboard |
MpOrderDashboardVO(取 .insurance 字段) |
| 2 |
合同详情(按订单) |
GET |
/mp/contract/by-order/{orderId} |
MpContractVO |
| 3 |
合同详情(按合同 ID) |
GET |
/mp/contract/{id} |
MpContractDetailVO |
| 4 |
订单保单合并 PDF |
GET |
/mp/insurance/policy-pdf/{orderId} |
Map<String,Object>(透传 PolicyShareVO) |
| 5 |
单张保单下载 |
GET |
/mp/insurance/policy/{insuranceOrderId}/download |
String(Base64) |
- 全部需要登录,
userId 由 mp-service 从 token 中取出后透传给 order-v2
- 仅 5 号需要
insuranceOrderId,该 ID 来自订单详情出行人的 insurancePolicies[].insuranceOrderId
二、接口详情
1. 保险详情 GET /mp/order/{orderId}/dashboard
保险详情没有独立接口,走订单详情聚合 MpOrderDashboardVO,取 .insurance 字段(MpInsuranceDetailVO)。未投保或查询失败时该字段为 null(降级,不阻断页面)。
入参
| 字段 |
位置 |
类型 |
必填 |
说明 |
orderId |
Path |
Long |
✅ |
订单 ID |
出参 Result<MpOrderDashboardVO> — 聚合 VO 全字段
| 字段 |
类型 |
说明 |
order |
MpOrderDetailVO |
订单主体(详见 2026-04-17 订单详情 changelog) |
preTripChecklist |
MpPreTripChecklistVO |
出发准备清单(降级时 null) |
files.contract |
MpContractSummaryVO |
合同摘要(无合同 null) |
files.invoice |
MpInvoiceSummaryVO |
发票摘要(未开票 null) |
files.insurancePolicyPdfUrl |
String |
保单合并 PDF 下载路径,固定为 /mp/insurance/policy-pdf/{orderId} |
insurance |
MpInsuranceDetailVO |
保险详情(本 changelog 重点字段) |
refund |
RefundVO |
退款模块(仅取消/退款中状态有值) |
insurance(MpInsuranceDetailVO)字段
| 字段 |
类型 |
说明 |
schemeId |
Long |
方案 ID |
schemeName |
String |
方案名称 |
description |
String |
方案描述 |
isOverseas |
Boolean |
是否境外 |
totalDays |
Integer |
适用行程天数 |
notice |
String |
保险告知状态:INCLUDED / OPTIONAL / EXCLUDED |
segments |
List<CoverageSegment> |
保障分段列表 |
segments[].segmentName |
String |
分段名称 |
segments[].dayOffsetStart |
Integer |
起始天 |
segments[].dayOffsetEnd |
Integer |
结束天(-1 = 最后一天) |
segments[].productName |
String |
保险产品名称 |
segments[].planName |
String |
保险计划名称 |
policies |
List<PolicyItem> |
投保记录列表(未投保为空数组) |
policies[].insuranceOrderId |
Long |
保险订单 ID(用于接口 5 下载) |
policies[].policyNo |
String |
保单号 |
policies[].productName |
String |
保险产品名称 |
policies[].planName |
String |
计划名称 |
policies[].premium |
BigDecimal |
保费(元) |
policies[].insuredCount |
Integer |
被保人数 |
policies[].coverageStartDate |
LocalDate |
保障开始日期 |
policies[].coverageEndDate |
LocalDate |
保障结束日期 |
policies[].status |
String |
保险状态:PENDING / INSURING / INSURED / FAILED(CANCELLED 已过滤不返回) |
policies[].statusLabel |
String |
状态中文标签 |
policies[].insuredPersons |
List<InsuredPerson> |
被保人列表 |
insuredPersons[].name |
String |
姓名(明文,脱敏由前端处理) |
insuredPersons[].idCardType |
String |
证件类型:ID_CARD / PASSPORT |
insuredPersons[].idCardNo |
String |
证件号码(明文) |
insuredPersons[].birthday |
LocalDate |
出生日期 |
insuredPersons[].gender |
String |
MALE / FEMALE |
insuredPersons[].phone |
String |
手机号(明文) |
2. 合同详情(按订单) GET /mp/contract/by-order/{orderId}
返回订单关联的最新有效合同(非作废),一般用于订单详情页的"合同"入口。
入参
| 字段 |
位置 |
类型 |
必填 |
说明 |
orderId |
Path |
Long |
✅ |
订单 ID |
出参 Result<MpContractVO>
| 字段 |
类型 |
说明 |
contractId |
Long |
合同 ID |
orderId |
Long |
订单 ID |
templateCode |
String |
模板编码 |
templateName |
String |
模板名称 |
contractNumber |
String |
合同编号 |
platform |
String |
签约平台 |
contractType |
String |
字典 contract_type:TOUR / INSURANCE |
contractTypeLabel |
String |
合同类型标签 |
mode |
String |
字典 contract_mode:ONLINE / OFFLINE |
modeLabel |
String |
签约模式标签 |
status |
String |
字典 contract_status |
statusLabel |
String |
合同状态标签 |
signUrl |
String |
签署 URL |
qrCodeUrl |
String |
签署二维码 URL |
fileUrl |
String |
合同文件 URL |
agencyCode |
String |
旅行社编号 |
travelAgencyName |
String |
旅行社名称 |
destination |
String |
目的地 |
departureDate |
LocalDate |
出发日期 |
returnDate |
LocalDate |
返回日期 |
totalAmount |
BigDecimal |
合同总金额 |
touristCount |
Integer |
出行人数 |
contactName |
String |
联系人姓名(明文,脱敏由前端处理) |
contactPhone |
String |
联系人电话(明文,脱敏由前端处理) |
createTime |
LocalDateTime |
创建时间 |
无合同时 data 为 null。
3. 合同详情(按合同 ID) GET /mp/contract/{id}
按合同 ID 查完整详情,返回合同基本信息 + 出行人签署详情 + 状态变更日志。
入参
| 字段 |
位置 |
类型 |
必填 |
说明 |
id |
Path |
Long |
✅ |
合同 ID |
出参 Result<MpContractDetailVO>
MpContractDetailVO 继承 MpContractVO(字段见接口 2),额外字段:
| 字段 |
类型 |
说明 |
supplementaryClause |
String |
补充约定内容 |
travelers |
List<TravelerInfo> |
出行人列表 |
travelers[].travelerId |
Long |
出行人 ID |
travelers[].name |
String |
姓名(明文) |
travelers[].idCardType |
String |
ID_CARD / PASSPORT |
travelers[].idCardNo |
String |
证件号码(明文) |
travelers[].phone |
String |
手机号(明文) |
travelers[].isSigner |
Boolean |
是否签署人 |
statusLogs |
List<MpContractStatusLogVO> |
状态变更日志 |
statusLogs[].logId |
Long |
日志 ID |
statusLogs[].contractId |
Long |
合同 ID |
statusLogs[].oldStatus |
String |
旧状态 |
statusLogs[].newStatus |
String |
新状态 |
statusLogs[].source |
String |
变更来源:CALLBACK / POLLING / MANUAL |
statusLogs[].rawPayload |
String |
原始载荷(仅调试用) |
statusLogs[].createTime |
LocalDateTime |
创建时间 |
权限:合同 userId 必须与登录用户一致,否则 403。
4. 订单保单合并 PDF GET /mp/insurance/policy-pdf/{orderId}
合并订单下所有出行人的有效保单为一个 PDF,返回 Base64。
入参
| 字段 |
位置 |
类型 |
必填 |
说明 |
orderId |
Path |
Long |
✅ |
订单 ID |
出参 Result<Map<String,Object>>(BFF 当前透传 order-v2 PolicyShareVO)
| 字段 |
类型 |
说明 |
pdfBase64 |
String |
合并后的保单 PDF(Base64 编码) |
personName |
String |
出行人姓名(订单范围分享时一般为空/null) |
policyCount |
Integer |
成功合并的保单数量 |
failedCount |
Integer |
下载失败的保单数量 |
5. 单张保单下载 GET /mp/insurance/policy/{insuranceOrderId}/download
下载指定保险订单的单张保单 PDF,返回 Base64 字符串。insuranceOrderId 从接口 1 的 insurance.policies[].insuranceOrderId 取。
入参
| 字段 |
位置 |
类型 |
必填 |
说明 |
insuranceOrderId |
Path |
Long |
✅ |
保险订单 ID(非订单 ID) |
出参 Result<String>
| 字段 |
类型 |
说明 |
data |
String |
保单 PDF(Base64 编码) |
三、响应示例
接口 2 GET /mp/contract/by-order/{orderId}
{
"code": 200,
"message": "成功",
"data": {
"contractId": 9001,
"orderId": 20439,
"templateCode": "TOUR_STANDARD",
"templateName": "旅游服务合同(标准版)",
"contractNumber": "HL-2026-0423-0001",
"platform": "fadada",
"contractType": "TOUR",
"contractTypeLabel": "旅游合同",
"mode": "ONLINE",
"modeLabel": "线上签署",
"status": "SIGNED",
"statusLabel": "已签署",
"signUrl": "https://sign.fadada.com/xxx",
"qrCodeUrl": "https://cdn.1814.love/qr-9001.png",
"fileUrl": "https://cdn.1814.love/contract-9001.pdf",
"agencyCode": "HULAL001",
"travelAgencyName": "呼籁旅行",
"destination": "呼伦贝尔",
"departureDate": "2026-07-01",
"returnDate": "2026-07-07",
"totalAmount": "12600.00",
"touristCount": 4,
"contactName": "张三",
"contactPhone": "13800138000",
"createTime": "2026-04-20 10:30:00"
},
"success": true
}
接口 4 GET /mp/insurance/policy-pdf/{orderId}
{
"code": 200,
"message": "成功",
"data": {
"pdfBase64": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeX...(截断)",
"personName": null,
"policyCount": 4,
"failedCount": 0
},
"success": true
}
四、边界行为
- 未登录 → 401(网关拦截)
- 订单/合同不属于当前
userId → 403
- 订单无合同(接口 2)→
data: null
- 订单未投保(接口 1 的
insurance 字段)→ insurance: null,不阻断页面
- 保单 PDF 下载失败(接口 4)→
failedCount > 0,pdfBase64 仍返回已合并部分;下游整体失败时 BFF 返 500
- 合同服务整体不可用(接口 2/3)→ BFF 返
500 合同服务不可用,请稍后重试
五、不影响范围
- 仅影响:C 端订单详情页的保险详情弹窗 / 合同详情 / 保单 PDF 下载入口
- 零影响:
- 下单、支付、退款、发票所有接口
- 合同列表
GET /mp/contract/list(未列出,字段同接口 2 MpContractVO)
- 管理后台合同/保险所有接口(不走
/mp/ 前缀)
- JSON 字段名与取值逻辑(本次仅后端 VO 强类型化)
六、相关历史 PR
| PR |
Issue |
说明 |
是否仍有效 |
| wx/HL#1314 |
wx/HL#1312 |
合同接口返回值从 Map 改为强类型 VO(本 PR) |
✅ 最新 |
2026-04-17 mp-order-detail-refactor |
- |
订单详情聚合 VO MpOrderDashboardVO |
✅ 有效 |
七、代码位置
- Controller
hl-mp-service · com.hulalv.mp.controller.MpOrderController#getOrderDashboard
hl-mp-service · com.hulalv.mp.controller.MpContractController
hl-mp-service · com.hulalv.mp.controller.MpInsuranceController
- VO
hl-mp-service · com.hulalv.mp.vo.MpOrderDashboardVO
hl-mp-service · com.hulalv.mp.vo.MpInsuranceDetailVO
hl-mp-service · com.hulalv.mp.vo.MpContractVO / MpContractDetailVO / MpContractStatusLogVO
- 下游
hl-order-service-v2 · com.hulalv.contract.controller.internal.InternalMpContractController
hl-order-service-v2 · com.hulalv.insurance.controller.internal.InternalInsuranceController
hl-order-service-v2 · com.hulalv.insurance.vo.PolicyShareVO
八、相关文档
- 关联 Issue: wx/HL#1312
- 关联 PR: wx/HL#1314
- 订单详情聚合 VO 参考:
changelogs/2026-04/2026-04-17_order-v2_mp-order-detail-refactor.md