Files
mipu-open/docs/03-04_shopping-seat.md
杨柳杰 b450b512a2 init: mipu-open 对外开放项目统一管理仓库
- 添加 mipu-api 作为 git submodule (Claude Code Skill)
- 迁移 API 文档源文件到 docs/ 目录统一维护
- 添加 Gitea Actions 工作流:tag推送自动打包docs并发布Release
- Skill 运行时自动从 mipu-open Release 下载最新文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-04 12:16:08 +08:00

355 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- mipuyun-api-doc: shopping-seat -->
# shopping/seat - 选座报价
## 用户使用场景
> 获取航班座位图信息,包括每个座位的位置、价格、状态(可用/已占)、以及座位特性(靠窗、靠过道、紧急出口等)
## 性能指标
> - 通过 sessionId 访问,或者 sessionId 有效,响应时间 < 10 秒
> - 接口成功率:> 90%
## 请求说明
| **请求地址** | https://${endpoint}/shopping/seat |
| --- | --- |
| **请求方法** | POST |
| **注意事项** | Header 必须带压缩请求 |
## 请求参数
### Header
| **参数名称** | **类型** | **是否必选** | **示例值** | **说明** |
| --- | --- | --- | --- | --- |
| Content-Type | String | 是 | application/json | 固定值,指定请求体格式为 JSON |
| Accept-Encoding | String | 是 | gzip, deflate, br | 必须要填写,否则服务器会拒绝 |
| client-key | String | 是 | xxxxx | 联系我们获取生产环境 key |
| client-secret | String | 是 | xxxxx | 联系我们获取生产环境 secret |
### 请求体
```json
{
"sessionId": "743768c1-8bdc-46ed-a586-94fdbd0ce24a",
"journeyType": "OW",
"origin": "OTP",
"destination": "CAG",
"departureDate": "20260116",
"adults": 1,
"children": 0,
"infants": 0,
"agent": "AXZ",
"proxy": "res_mipu_bookxWdyg-it",
"outboundFareFamily": "BASIC",
"inboundFareFamily": "",
"outboundSegments": [
{
"carrier": "XZ",
"originAirport": "OTP",
"destinationAirport": "FCO",
"flightNumber": "XZ3115",
"departureDate": "20260116"
},
{
"carrier": "XZ",
"originAirport": "FCO",
"destinationAirport": "CAG",
"flightNumber": "XZ2341",
"departureDate": "20260116"
}
],
"inboundSegments": []
}
```
| **参数名称** | **类型** | **是否必选** | **示例值(默认值)** | **说明** |
| --- | --- | --- | --- | --- |
| sessionId | String | 否 | 743768c1-8bdc-46ed-a586-94fdbd0ce24a | 目的是为了复用前一步的 shopping/search 或 shopping/select 的 session提升速度 & 成功率。如带入 session请务必保障1. 出发到达/旅行日期/人数与前一步保持一致 |
| journeyType | String | 是 | "OW" | 行程为单程还是往返程<br>OW单程 OneWay<br>RT往返 RoundTrip |
| origin | String | 是 | "OTP" | 出发地,为 IATA 3 字码兼容城市或者机场 3 字码 |
| destination | String | 是 | "CAG" | 到达地,为 IATA 3 字码兼容城市或者机场 3 字码 |
| departureDate | String | 是 | 20260116 | 出发日期,格式为 `YYYYMMDD`(如 2024 年 5 月 1 日为 20240501 |
| returnDate | String | 否 | 20240423仅 RT 必填) | 返程日期,格式同 departureDate仅当 journeyType=RT 时必传OW 时可传空 |
| adults | Integer | 是 | 1 | 成人,乘机人数量 |
| children | Integer | 是 | 0 | 儿童,乘机人数量 |
| infants | Integer | 是 | 0 | 婴儿,乘机人数量 |
| agent | String | 是 | "AXZ" | Agent 代码 |
| proxy | String | 是 | "res_mipu_bookxWdyg-it" | 本次获取航司数据采用的代理方式。如果需要指定代理国家请在代理用户后面加上国家二字码。如 myproxy-USUS 代表美国 |
| outboundSegments | Array<FlightSegmentRequest> | 是 | 见示例 | 去程航段信息,详见 [FlightSegmentRequest](07-01_flight-segment-request.md) |
| inboundSegments | Array<FlightSegmentRequest> | 否 | | 返程航段信息,往返行程为必须,详见 [FlightSegmentRequest](07-01_flight-segment-request.md) |
| outboundFareFamily | String | 是 | "BASIC" | 去程 FareFamily 的名字 |
| inboundFareFamily | String | 否 | | 回程 FareFamily 的名字,仅往返程有值 |
| acceptCacheMinutes | Integer | 否 | 5 | 默认值5<br>**如无特殊情况,本参数不建议设置或调整。**为了避免频繁请求航司设置的缓存,用户可以指定缓存时长,不填写为 5 |
| async | Boolean | 是 | false | 是否启用 Webhook 异步模式。<br>- **false**: 同步模式,等待完整结果返回<br>- **true**: 异步模式,立即返回 202结果通过 Webhook 回调<br><br>**异步模式说明**<br>1. 系统会同步检查是否有新鲜缓存acceptCacheMinutes如有则立即返回<br>2. 无缓存时返回 202 Accepted包含 requestId 用于追踪<br>3. 航司数据返回后,通过预先配置的 Webhook 回调通知<br><br>**注意**:使用异步模式需提前配置 `shopping_response` 类型的 Webhook |
| callbackId | String | 否 | - | 异步模式下的业务回调标识,用于客户自行匹配业务。建议格式:`seat_{origin}_{destination}_{departureDate}_{adults}-{children}-{infants}_{flightNumber}`,最大 50 个字符 |
## 返回参数
### 响应示例
```json
{
"cached": false,
"code": 0,
"itineraries": [],
"msg": "success",
"seatMapList": [
{
"segmentIndex": 1,
"journeyDirection": "outbound",
"segment": {
"flightNumber": "DM200",
"dptAirport": "AUA",
"arrAirport": "CUR",
"departureTime": "202604261100",
"arrivalTime": "202604261150"
},
"cabins": [
{
"deck": "main",
"cabinType": "Business",
"cabinLayout": {
"columns": [
{ "designator": "A", "characteristics": "W" },
{ "designator": "C", "characteristics": "A" },
{ "designator": "D", "characteristics": "A" },
{ "designator": "G", "characteristics": "A" },
{ "designator": "J", "characteristics": "W" }
],
"rows": { "first": 1, "last": 8 },
"exitRowPositions": []
},
"rows": [
{
"number": 1,
"seats": [
{
"column": "A",
"currency": "EUR",
"price": 120.0,
"seatCharacteristics": ["W", "L"],
"seatStatus": "F"
}
]
}
]
},
{
"deck": "main",
"cabinType": "Economy",
"cabinLayout": {
"columns": [
{ "designator": "A", "characteristics": "W" },
{ "designator": "B", "characteristics": "M" },
{ "designator": "C", "characteristics": "A" },
{ "designator": "D", "characteristics": "A" },
{ "designator": "E", "characteristics": "M" },
{ "designator": "F", "characteristics": "W" }
],
"rows": { "first": 9, "last": 32 },
"exitRowPositions": [
{ "first": 16, "last": 16 },
{ "first": 17, "last": 17 }
]
},
"rows": [
{
"number": 9,
"seats": [
{
"column": "A",
"currency": "EUR",
"price": 21.0,
"seatCharacteristics": ["W", "IE", "E", "L"],
"seatStatus": "F"
}
]
}
]
}
]
}
],
"sessionId": "shopping-seat-fa149f406bcd4df9a1a318d230afc422"
}
```
### 响应字段说明
| 参数名称 | 类型 | 说明 |
| --- | --- | --- |
| code | Integer | 系统状态码0 = 成功,非 0 为失败 |
| msg | String | 系统消息:成功时为 null失败时返回具体系统提示信息 |
| cached | Boolean | 是否使用缓存数据 |
| sessionId | String | UUID与航司通信的 session 值,可以用于加速后续动作,如下单 |
| itineraries | Array<Itinerary> | 航线组合列表(本接口通常为空数组) |
| seatMapList | Array<SeatMap> | **座位图列表,按航段返回每个航段的座位信息** |
### 异步模式响应async=true
`async=true` 且无可用缓存时,系统立即返回 202 Accepted
| 参数名称 | 类型 | 说明 |
|----------|------|------|
| code | Integer | 202表示请求已接受正在处理中 |
| msg | String | "Accepted. Please wait for the webhook callback" |
| requestId | String | 请求IDUUID用于追踪和关联 Webhook 回调 |
| status | String | "PROCESSING"(处理中) |
完整结果将通过预先配置的 Webhook 回调返回。
### SeatMap座位图对象说明
seatMapList 数组中的每个元素代表一个航段的座位图,结构如下:
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| segmentIndex | Integer | 航段索引(从 1 开始),对应 outboundSegments 或 inboundSegments 中的位置 |
| journeyDirection | String | 行程方向:`outbound`(去程)/ `inbound`(返程) |
| segment | Object | 航段信息对象,包含航班号、出发/到达机场和时间 |
| cabins | Array\<Cabin\> | 客舱信息列表,按舱位等级排列(如商务舱在前、经济舱在后) |
#### Segment航段对象
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| flightNumber | String | 航班号,如 "DM200" |
| dptAirport | String | 出发机场 IATA 三字码,如 "AUA" |
| arrAirport | String | 到达机场 IATA 三字码,如 "CUR" |
| departureTime | String | 出发时间,格式 `YYYYMMDDHHmm`,如 "202604261100" |
| arrivalTime | String | 到达时间,格式 `YYYYMMDDHHmm`,如 "202604261150" |
#### Cabin机舱对象
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| deck | String | 甲板类型,如 "main" 表示主甲板 |
| cabinType | String | 客舱类型,可选值:`Economy`(经济舱)、`Business`(商务舱)、`FirstClass`(头等舱)、`PremiumEconomy`(高端经济舱) |
| cabinLayout | Object | 机舱布局信息 |
| rows | Array\<Row\> | 座位行列表 |
#### CabinLayout机舱布局对象
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| columns | Array<Column> | 列信息数组,描述每列的座位特性 |
| rows | Object | 行范围,包含 `first`(起始行号)和 `last`(结束行号) |
| exitRowPositions | Array<Object> | 紧急出口行位置数组,每个对象包含 `first``last` 行号 |
#### Column对象
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| designator | String | 列标识符,如 "A"、"B"、"C" 等 |
| characteristics | String | 列特性代码(见座位特性说明) |
#### Row座位行对象
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| number | Integer | 行号 |
| seats | Array<Seat> | 该行的座位列表 |
#### Seat座位对象
| 字段名 | 类型 | 示值 | 说明 |
| --- | --- | --- | --- |
| column | String | "A" | 列标识符A、B、C 等) |
| seatStatus | String | "F" | 座位状态<br>**F**Free可用<br>**O**Occupied已占 |
| seatCharacteristics | Array<String> | ["W", "I"] | 座位特性数组(见下文座位特性说明) |
| price | BigDecimal | 15.0 | 座位价格(该座位选座费用) |
| currency | String | "EUR" | 价格币种 |
### 座位特性说明
seatCharacteristics 数组中的特性代码:
| 代码 | 英文 | 中文说明 |
| --- | --- | --- |
| W | Window | 靠窗座位 |
| A | Aisle | 靠过道座位 |
| M | Middle | 中间座位 |
| I | Standard | 标准座位 |
| IE | ExitRow | 紧急出口排 |
| E | ExtraLegroom | 额外腿部空间 |
| L | LimitedRecline | 有限后倾 |
## 常见问题
### 如何理解 seatMapList 的结构?
每个航段Segment都有一个独立的座位图每个座位图可包含多个舱位cabins。例如
- 单程直飞seatMapList 长度为 1该航段可能包含 1 个或多个 cabins如商务舱 + 经济舱)
- 单程转机2 个航段seatMapList 长度为 2每个航段各有独立的 cabins
- 往返程直飞seatMapList 长度为 2去程 + 回程),每个航段各有独立的 cabins
segmentIndex 从 1 开始,与请求中的 outboundSegments/inboundSegments 数组索引对应。cabins 数组中每个 Cabin 对象代表一个舱位区域,通过 cabinType 区分舱位等级。
### 座位状态有哪些?
- **F (Free)**:座位可选,未被占用
- **O (Occupied)**:座位已被占用,不可选择
### 如何识别靠窗/靠过道座位?
通过 seatCharacteristics 数组判断:
- 包含 "W":靠窗座位
- 包含 "A":靠过道座位
- 包含 "M":中间座位(通常在 3-3 或 3-4-3 布局的中间列)
### 紧急出口座位如何识别?
包含以下特性的座位通常是紧急出口排:
- **IE (ExitRow)**:紧急出口排
- **E (ExtraLegroom)**:额外腿部空间
这些座位通常价格更高,腿部空间更大,但可能有年龄限制(如 14 岁以上)。
### 价格为 0 的座位是什么意思?
价格为 0 表示该座位免费可选,不需要额外付费。这种情况常见于:
- 高端舱位(商务舱、头等舱)
- 航司促销活动
- 某些会员权益
## 业务案例
### 单人单程选座查询
#### 请求Request
```json
{
"journeyType": "OW",
"origin": "OTP",
"destination": "CAG",
"departureDate": "20260116",
"adults": 1,
"children": 0,
"infants": 0,
"agent": "AXZ",
"outboundFareFamily": "BASIC",
"outboundSegments": [
{
"carrier": "XZ",
"originAirport": "OTP",
"destinationAirport": "CAG",
"flightNumber": "XZ3115",
"departureDate": "20260116"
}
]
}
```
#### 响应Response
响应包含完整的座位图,每个座位都有:
- 位置信息(行号 + 列号)
- 价格信息price + currency
- 状态信息seatStatusF/O
- 特性信息seatCharacteristics靠窗/靠过道/紧急出口等)
在线查看完整示例https://jsonhero.io/j/XmTLWK94Ae5X