Files
mipu-open/docs/04-03_booking-query.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

425 lines
11 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: booking-query -->
# booking/query - 订单查询
# 订单查询(booking/query) API 说明文档
## 使用场景
> 1. 查询订单的详细信息和当前状态
> 2. 在支付完成后查询订单确认状态
> 3. 在客服系统中查询订单详情
> 4. 获取订单的完整行程、乘客和费用信息
## 错误场景(不应该使用本接口的场景)
> 1. 查询不存在的订单 ID
> 2. 查询不属于当前客户的订单clientCode 不匹配)
## 性能指标
> - 响应速度98% 的请求响应速度 < 500ms
> - 接口成功率:> 99.5%
## 请求说明
| **请求地址** | https://${endpoint}/booking/query |
| --- | --- |
| **请求方法** | POST |
## 请求参数
### Header
| **参数名称** | **类型** | **是否必选** | **示例值** | **说明** |
| --- | --- | --- | --- | --- |
| Content-Type | String | 是 | application/json | 固定值,指定请求体格式为 JSON |
| Accept-Encoding | String | 是 | gzip, deflate, br | 必须要填写,否则服务器会拒绝 |
| client-key | String | 是 | xxxxx | 联系我们获取生产环境 key |
| client-secret | String | 是 | xxxxx | 联系我们获取生产环境 secret |
###
### 请求体
```json
{
"orderId": "abbc4b57fb75"
}
```
#### 参数详情
| **参数名称** | **类型** | **是否必选** | **示例值(默认值)** | **说明** |
| --- | --- | --- | --- | --- |
| orderId | String | **是** | abbc4b57fb75 | 客户的订单号,用于查询订单详情 |
## 返回参数
### 成功响应
```json
{
"orderId": "abbc4b57fb75",
"requestId": "req-12345",
"agentCode": "u2web",
"status": "CONFIRMED",
"payStatus": "PAID",
"origin": "MIL",
"destination": "CAG",
"journeyType": "OW",
"pnr": "ABC123",
"pnrExpiryTime": "2025-12-25T12:00:00Z",
"feeItems": {
"baseFare": 100.00,
"taxes": 50.50,
"total": 150.50,
"currency": "EUR"
},
"passengers": [
{
"lastName": "Rossi",
"firstName": "Mario",
"passengerType": "ADT",
"adult": true,
"child": false,
"infant": false,
"dateOfBirth": "1980-01-15",
"gender": "M",
"documentType": "PASSPORT",
"documentNumber": "AA1234567",
"ancillaries": []
}
],
"segments": [
{
"airline": "AZ",
"flightNo": "AZ1234",
"dptAirport": "MIL",
"arrAirport": "CAG",
"dptTime": "2025-11-18T10:30:00Z",
"arrTime": "2025-11-18T12:15:00Z",
"equipment": "A320"
}
],
"credential": null,
"promoCode": "SAVE10",
"createTime": "2024-11-15T10:00:00Z",
"updateTime": "2024-11-15T10:30:00Z",
"retryCount": 3,
"retriedCount": 0
}
```
## 错误码说明
本接口可能返回以下错误码:
| **错误码** | **错误名称** | **说明** | **处理建议** |
| --- | --- | --- | --- |
| 42005 | BOOKING_NOT_FOUND | 订单不存在 | 请检查 orderId 是否正确,或订单是否属于当前客户 |
| 41003 | PRICE_CHANGED | 票价高于预期 | 航司侧价格已变动,请检查响应中的 feeItems 获取最新价格,引导用户确认是否继续 |
### 失败响应
#### 订单不存在 (42005)
```json
{
"code": 42005,
"msg": "Booking not found"
}
```
#### 票价变动 (41003)
```json
{
"code": 41003,
"msg": "Price changed. Please check the latest price in feeItems.",
"data": {
"orderId": "abbc4b57fb75",
"feeItems": {
"baseFare": 110.00,
"taxes": 52.50,
"total": 162.50,
"currency": "EUR"
}
}
}
```
### 响应字段说明
#### 基本字段
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| orderId | String | 客户的订单号 |
| requestId | String | 请求 ID |
| agentCode | String | 代理商代码 |
| status | String | 订单状态(见下方状态说明) |
| payStatus | String | 支付状态(见下方支付状态说明) |
| origin | String | 出发地 IATA 3 字码 |
| destination | String | 到达地 IATA 3 字码 |
| journeyType | String | 行程类型<br>**OW**:单程<br>**RT**:往返 |
#### PNR 相关
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| pnr | String | 航司 PNR 码(订座记录编号) |
| pnrExpiryTime | String | PNR 有效期ISO 8601 格式UTC 0 时区) |
#### 费用信息
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| feeItems | Map | 费用明细(原始 JSON 对象)<br>详见:[feeItems 实体定义](/api-doc?doc=entity-fee-items) |
#### 乘客和航班
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| passengers | Array\<BookingPassenger\> | 乘客信息列表(见 BookingPassenger 定义) |
| segments | Array\<BookingSegment\> | 航班段列表(见 BookingSegment 定义) |
#### 其他信息
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| credential | Object | 订单凭据信息 |
| promoCode | String | 促销码 |
| createTime | DateTime | 订单创建时间ISO 8601 格式 |
| updateTime | DateTime | 订单最后更新时间ISO 8601 格式 |
| retryCount | Integer | 可重试的次数 |
| retriedCount | Integer | 已经重试的次数 |
## 状态说明
### 订单状态 (status)
| **状态** | **说明** |
| --- | --- |
| PENDING | 订单处理中,等待航司确认 |
| CONFIRMED | 订单已确认PNR 已生成 |
| CANCELLED | 订单已取消 |
| FAILED | 订单失败 |
### 支付状态 (payStatus)
| **状态** | **说明** |
| --- | --- |
| UNPAID | 未支付 |
| PENDING | 支付处理中 |
| PAID | 已支付 |
| REFUNDED | 已退款 |
| FAILED | 支付失败 |
## 数据来源说明
本接口返回的数据优先从 `responseJson` 字段解析,如果 `responseJson` 为空或解析失败code 不是 0 且 feeItems/passengers/segments 均为空),则从 `holdResponse` 字段回退获取。
## 业务流程
### 订单查询场景
```
1. 客户下单booking/hold→ 获取 orderId
2. 客户选择支付方式并支付booking/payment
3. 查询订单状态booking/query→ 确认订单状态
4. 如需要可以取消订单booking/cancel
```
## 常见问题
### 如果订单不存在会返回什么?
接口会返回错误响应code 为 40401msg 为 "Booking not found"。这种情况通常由以下原因造成:
1. orderId 错误或不存在
2. 订单属于其他客户clientCode 不匹配)
3. 订单已过期或被删除
### status 和 payStatus 有什么区别?
- **status**订单的整体状态PENDING/CONFIRMED/CANCELLED/FAILED
- **payStatus**订单的支付状态UNPAID/PENDING/PAID/REFUNDED/FAILED
### feeItems 返回什么结构?
`feeItems` 是一个原始的 Map 对象,直接从航司响应的 JSON 中解析。
详细的字段说明请参考:[feeItems 实体定义](/api-doc?doc=entity-fee-items)
### passengers 和 segments 的详细定义是什么?
#### BookingPassenger乘客信息
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| lastName | String | 乘客姓 |
| firstName | String | 乘客名 |
| passengerType | String | 乘客类型ADT/CHD/INF |
| adult | Boolean | 是否为成人 |
| child | Boolean | 是否为儿童 |
| infant | Boolean | 是否为婴儿 |
| dateOfBirth | String | 出生日期 |
| gender | String | 性别M/F |
| documentType | String | 证件类型(如 PASSPORT |
| documentNumber | String | 证件号码 |
| ancillaries | Array | 附加服务列表 |
#### BookingSegment航班段信息
| **参数名称** | **类型** | **说明** |
| --- | --- | --- |
| airline | String | 航司代码IATA 2 字码) |
| flightNo | String | 航班号(如 AZ1234 |
| dptAirport | String | 出发机场 IATA 3 字码 |
| arrAirport | String | 到达机场 IATA 3 字码 |
| dptTime | String | 出发时间ISO 8601 格式 |
| arrTime | String | 到达时间ISO 8601 格式 |
| equipment | String | 机型(如 A320、B737 |
### 什么时候会从 holdResponse 回退数据?
`responseJson` 满足以下任一条件时,会从 `holdResponse` 回退 feeItems/passengers/segments
1. `responseJson` 为空
2. `responseJson` 解析失败
3. `code` 不是 0 且 feeItems/passengers/segments 均为空
这确保了即使订单最终状态失败,也能获取到 hold 阶段的数据。
### 遇到票价变动错误 (PRICE_CHANGED) 怎么办?
当接口返回错误码 41003 (PRICE_CHANGED) 时,表示航司侧票价高于预期。这种情况通常发生在:
1. 下单后到支付前,航司调整了票价
2. 库存紧张导致票价上涨
3. 促销活动价格已过期
**处理流程:**
```
1. 接收到 41003 错误响应
2. 从响应的 data.feeItems 中获取最新价格
3. 向用户展示价格变动信息
4. 询问用户是否继续
5a. 用户同意 → 重新调用 booking/hold 使用新价格
5b. 用户拒绝 → 取消订单流程
```
**关键点:**
- 错误响应中的 `feeItems` 包含最新的价格明细
- 需要用户明确确认后才能继续交易
## 业务案例
### 查询已确认的订单
#### 请求Request
```json
{
"orderId": "abbc4b57fb75"
}
```
#### 响应Response
```json
{
"orderId": "abbc4b57fb75",
"agentCode": "u2web",
"status": "CONFIRMED",
"payStatus": "PAID",
"origin": "MIL",
"destination": "CAG",
"journeyType": "OW",
"pnr": "ABC123",
"passengers": [
{
"lastName": "Rossi",
"firstName": "Mario",
"passengerType": "ADT"
}
],
"segments": [
{
"airline": "AZ",
"flightNo": "AZ1234",
"dptAirport": "MIL",
"arrAirport": "CAG",
"dptTime": "2025-11-18T10:30:00Z",
"arrTime": "2025-11-18T12:15:00Z"
}
],
"createTime": "2024-11-15T10:00:00Z",
"updateTime": "2024-11-15T10:30:00Z"
}
```
### 查询往返程订单
#### 请求Request
```json
{
"orderId": "rt-order-12345"
}
```
#### 响应Response
```json
{
"orderId": "rt-order-12345",
"journeyType": "RT",
"origin": "MIL",
"destination": "CAG",
"status": "CONFIRMED",
"payStatus": "PAID",
"pnr": "XYZ789",
"passengers": [
{
"lastName": "Rossi",
"firstName": "Mario",
"passengerType": "ADT"
},
{
"lastName": "Bianchi",
"firstName": "Luca",
"passengerType": "ADT"
}
],
"segments": [
{
"airline": "AZ",
"flightNo": "AZ1234",
"dptAirport": "MIL",
"arrAirport": "CAG",
"dptTime": "2025-11-18T10:30:00Z",
"arrTime": "2025-11-18T12:15:00Z"
},
{
"airline": "AZ",
"flightNo": "AZ5678",
"dptAirport": "CAG",
"arrAirport": "MIL",
"dptTime": "2025-11-25T14:00:00Z",
"arrTime": "2025-11-25T15:45:00Z"
}
],
"createTime": "2024-11-15T10:00:00Z",
"updateTime": "2024-11-15T10:30:00Z"
}
```