12 KiB
C端订单详情页接口变更 — 2026-04-17
服务 hl-order-service-v2(端口8094)· 类型 feat 前端调用路径: 网关(8080) → hl-mp-service(8085) → hl-order-service-v2(8094) 前端实际请求前缀:
GET /mp/order/(mp-service 需同步新增 BFF 转发层)
一、已改接口(1个)
✏️ GET /mp/order/{orderId} — 订单详情
请求参数:不变(路径参数 orderId)
返回值变更:整体结构从 OrderDetailVO 改为 MpOrderDetailVO
新增字段
| 字段 | 类型 | 必有 | 说明 | 示例 |
|---|---|---|---|---|
serviceItems |
List |
✅ | 服务包含摘要列表,每项含 type/title/summary/clickable | 见下方 |
notIncluded |
String |
否 | 不含说明 | "往返大交通、个人消费" |
priceBreakdown |
Object |
否 | 价格明细(新订单有值,历史订单null) | 见下方 |
balancePayMethodLabel |
String |
否 | 尾款方式标签 | "落地后由领队收取" |
refundProgress |
Object |
否 | 退款进度(退款中/已取消时有值) | 见下方 |
tripProgress |
Object |
否 | 行程进度(仅行程中状态有值) | 见下方 |
invoiceStatus |
String |
✅ | 发票状态 | "AFTER_TRIP" |
productTypeLabel |
String |
✅ | 产品类型中文 | "核心产品" |
删除的字段(前端不再使用)
totalCost, surchargeAmount, pendingUpgradeAmount, depositRatio, balanceProofUrl, balancePayMethod, remark, checklistConfirmed, unlockRequestedAt, confirmedAt, readyAt, creatorAdminId, creatorName, mchId, mchName, sharerOpenid, productSnapshot, expiryMinutes, timeline, processStatus, processStatusLabel, discountReason, discounts, surcharges, transportSegments, roomInfo, hotelAssignments, hotelAssignmentDetails, vehicleInfo, refundPolicy, refundPolicyId, contactName, contactPhone
保留不变的字段
orderId, orderNo, groupCode, productId, productName, productCoverUrl, productType, departureDate, returnDate, tripDays, tripNights, adultCount, childCount, youngChildCount, babyCount, createTime, status, statusLabel, displayStatus, displayStatusLabel, cancelReason, cancelledAt, completedAt, expiryTime, totalPrice, depositAmount, balanceAmount, paidAmount, paymentType, paymentTypeLabel, paidAt, payMethodLabel, discountAmount, refundAmount, contracts, insurances, travelers, todos, reviewed, customizerId, customizerName, customizerAvatarUrl, customizerQrUrl
二、新增接口(6个弹窗)
用户点击
serviceItems列表中某项时按需调用,不需要在详情页一次性请求。 每个接口都需要传 userId(mp-service 从 token 中获取后透传)。
🆕 GET /mp/order/{orderId}/tickets — 门票清单
请求参数:路径参数 orderId
返回值 MpTicketListVO:
| 字段 | 类型 | 说明 |
|---|---|---|
hint |
String |
顶部提示语 |
items |
List |
门票列表 |
items[].seq |
Integer |
序号(1开始) |
items[].scenicName |
String |
景点名称 |
items[].coverUrl |
String |
景点封面图(可能为空) |
items[].dayNumber |
Integer |
第几天 |
items[].originalPrice |
BigDecimal |
门票原价/人(可能为null) |
items[].included |
Boolean |
是否已含 |
totalValue |
BigDecimal |
门票总价值/人(可能为null) |
footerText |
String |
底部文案 |
响应示例:
{
"code": 200,
"data": {
"hint": "以下景点门票已包含在套餐内,无需另购",
"items": [
{ "seq": 1, "scenicName": "莫日格勒河", "coverUrl": null, "dayNumber": 2, "originalPrice": 80.00, "included": true },
{ "seq": 2, "scenicName": "根河湿地", "coverUrl": null, "dayNumber": 3, "originalPrice": 120.00, "included": true }
],
"totalValue": 200.00,
"footerText": "全部已含·无需再付"
}
}
🆕 GET /mp/order/{orderId}/hotels — 住宿清单
请求参数:路径参数 orderId
返回值 MpHotelListVO:
| 字段 | 类型 | 说明 |
|---|---|---|
hint |
String |
顶部提示语(如"5晚精选当地酒店") |
items |
List |
酒店列表 |
items[].hotelName |
String |
酒店名称 |
items[].coverUrl |
String |
酒店封面图(可能为空) |
items[].dayNumber |
Integer |
第几天入住 |
items[].hotelType |
String |
酒店类型(如"5星"/"特色民宿",可能为空) |
items[].roomType |
String |
房型(如"大床房",可能为空) |
footerNote |
String |
底部备注 |
响应示例:
{
"code": 200,
"data": {
"hint": "5晚精选当地酒店",
"items": [
{ "hotelName": "海拉尔铂尔曼大酒店", "coverUrl": null, "dayNumber": 1, "hotelType": "", "roomType": "大床房" }
],
"footerNote": "实际入住酒店以出行前确认为准"
}
}
🆕 GET /mp/order/{orderId}/meals — 餐饮清单
请求参数:路径参数 orderId
返回值 MpMealListVO:
| 字段 | 类型 | 说明 |
|---|---|---|
hint |
String |
顶部提示语(如"已含5早8正餐") |
specialMeals |
List |
特色正餐列表 |
specialMeals[].dayNumber |
Integer |
第几天 |
specialMeals[].mealName |
String |
餐名 |
specialMeals[].mealType |
String |
餐型(午餐/晚餐) |
specialMeals[].description |
String |
菜品描述 |
stats |
Object |
餐饮统计 |
stats.breakfast |
String |
早餐统计(如"5餐·酒店自助") |
stats.specialDinner |
String |
特色正餐统计(如"3餐") |
stats.regularDinner |
String |
日常正餐统计(如"5餐·当地特色餐厅") |
footerNote |
String |
底部备注 |
响应示例:
{
"code": 200,
"data": {
"hint": "已含1早2正餐",
"specialMeals": [
{ "dayNumber": 2, "mealName": "手把肉宴", "mealType": "午餐", "description": "含奶茶/手把肉" }
],
"stats": { "breakfast": "1餐·酒店自助", "specialDinner": "1餐", "regularDinner": "1餐·当地特色餐厅" },
"footerNote": "对食物有过敏请提前告知领队"
}
}
🆕 GET /mp/order/{orderId}/vehicle — 用车详情
请求参数:路径参数 orderId
返回值 MpVehicleDetailVO:
| 字段 | 类型 | 说明 |
|---|---|---|
hint |
String |
顶部提示语 |
vehicleName |
String |
车型名称 |
coverUrl |
String |
车型图片(可能为空) |
description |
String |
车型描述/特点(可能为空) |
matchRule |
String |
匹配规则说明 |
响应示例:
{
"code": 200,
"data": {
"hint": "一家一车不拼团·全程同一辆车",
"vehicleName": "商务车",
"coverUrl": null,
"description": "",
"matchRule": "匹配规则:根据出行人数自动配车"
}
}
🆕 GET /mp/order/{orderId}/guide — 领队详情
请求参数:路径参数 orderId
返回值 MpGuideInfoVO:
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String |
姓名(可能为null) |
avatarUrl |
String |
头像(可能为null) |
role |
String |
角色标签(固定"主领队"或"领队") |
phone |
String |
电话(可能为null) |
remark |
String |
简介(可能为null) |
⚠️ 产品服务快照扩展完成前,除
role外所有字段可能为 null
🆕 GET /mp/order/{orderId}/photographer — 摄影详情
请求参数:路径参数 orderId
返回值 MpPhotographerInfoVO:
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String |
姓名(可能为null) |
avatarUrl |
String |
头像(可能为null) |
role |
String |
角色标签(固定"摄影师") |
phone |
String |
电话(可能为null) |
remark |
String |
简介(可能为null) |
⚠️ 同领队,产品服务快照扩展完成前字段可能为 null
三、新增结构体详细说明
serviceItems(服务包含摘要)
详情接口返回的 serviceItems 是一个数组,每项代表一个服务类别:
[
{ "type": "HOTEL", "title": "住宿", "summary": "5晚精选当地酒店", "clickable": true },
{ "type": "MEAL", "title": "餐饮", "summary": "5早 8正餐", "clickable": true },
{ "type": "VEHICLE", "title": "用车", "summary": "专属车辆 + 司机", "clickable": true },
{ "type": "GUIDE", "title": "领队", "summary": "全程陪同", "clickable": true },
{ "type": "PHOTOGRAPHER", "title": "摄影", "summary": "全程跟拍 + 精修照片", "clickable": true },
{ "type": "TICKET", "title": "门票", "summary": "4处景点门票", "clickable": true },
{ "type": "INSURANCE", "title": "保险", "summary": "旅行意外险", "clickable": false }
]
clickable=true 时点击应调用对应弹窗接口:type=HOTEL → GET /mp/order/{orderId}/hotels,以此类推。
priceBreakdown(价格明细)
{
"items": [
{ "label": "成人", "unitPrice": 2300.00, "quantity": 2, "amount": 4600.00 },
{ "label": "儿童", "unitPrice": 1800.00, "quantity": 1, "amount": 1800.00 }
],
"subtotal": 6400.00,
"discounts": [
{ "tag": "早鸟优惠", "description": "提前30天", "amount": -400.00 }
],
"totalDiscount": -400.00,
"totalPayable": 6000.00
}
⚠️ 仅新创建的订单有值,历史订单为 null,前端需做空判断
refundProgress(退款进度)
{
"steps": [
{ "title": "提交退款申请", "description": "用户发起退款", "status": "COMPLETED", "time": "2026-06-25T16:32:00" },
{ "title": "商家审核中", "description": "客服正在审核您的退款申请", "status": "ACTIVE", "time": null },
{ "title": "退款处理", "description": "原路退回您的微信账户", "status": "PENDING", "time": null },
{ "title": "退款到账", "description": "预计1-3个工作日", "status": "PENDING", "time": null }
],
"currentStep": 1,
"refundAmount": 1000.00,
"refundMethod": null,
"refundArrivalTime": null
}
step.status 取值:COMPLETED=已完成 / ACTIVE=进行中 / PENDING=待处理
⚠️ 仅退款中/已取消且有退款时有值,其他状态为 null
tripProgress(行程进度)
{
"currentDay": 2,
"totalDays": 6,
"progressPercent": 33,
"todayDestination": "莫日格勒河"
}
⚠️ 仅行程中(displayStatus=TRAVELLING)状态有值,其他状态为 null
invoiceStatus 取值
| 值 | 说明 |
|---|---|
ISSUED |
已开票 |
PENDING |
开票中 |
NOT_ISSUED |
未开票(已完成订单可申请) |
AFTER_TRIP |
出行后可开 |
四、mp-service BFF 层需同步新增
以上6个弹窗接口目前在 order-service-v2 的 /internal/mp/order/ 路径下已就绪。
mp-service(hl-mp-service)需要新增对应的 BFF 转发层,路径映射如下:
| 前端调用 | mp-service 转发到 |
|---|---|
GET /mp/order/{orderId}/tickets |
GET /internal/mp/order/{orderId}/tickets?userId=xxx |
GET /mp/order/{orderId}/hotels |
GET /internal/mp/order/{orderId}/hotels?userId=xxx |
GET /mp/order/{orderId}/meals |
GET /internal/mp/order/{orderId}/meals?userId=xxx |
GET /mp/order/{orderId}/vehicle |
GET /internal/mp/order/{orderId}/vehicle?userId=xxx |
GET /mp/order/{orderId}/guide |
GET /internal/mp/order/{orderId}/guide?userId=xxx |
GET /mp/order/{orderId}/photographer |
GET /internal/mp/order/{orderId}/photographer?userId=xxx |
mp-service 从用户 token 中提取 userId,作为查询参数透传给 order-service。