# 小包接口文档

## 1. 接口概述

小包模块提供了一系列RESTful API接口，用于标签替换、扫描记录管理以及相关操作。本文档详细描述了这些接口的使用方法、请求参数和响应格式。



**测试环境请求地址：http://172.232.21.79:5002**
**正式环境请求地址：https://lr.tooexp.com**



### 1.1 接口基础信息

- **基础URL**：`http://{服务器地址}:{端口}/api/Label`
- **请求方式**：POST/GET
- **数据格式**：JSON
- **响应格式**：JSON

### 1.2 状态码说明

| 状态码 | 描述 |
|-------|------|
| 200 | 操作成功 |
| 400 | 请求参数错误或操作失败 |
| 401 | 身份验证失败 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |

## 2. 接口详细说明

### 2.1 根据跟踪单号获取标签替换请求记录

**接口路径**：`/label-replace/tracking/{trackingNumber}`
**请求方法**：GET
**功能描述**：根据跟踪单号获取标签替换请求记录

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| trackingNumber | string | 是 | 跟踪单号 | "1Z999AA10123456789" |

#### 请求示例

```
GET /api/Label/label-replace/tracking/1Z999AA10123456789
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "trackingNumber": "1Z999AA10123456789",
  "count": 1,
  "data": [
    {
      "Id": 1,
      "NeutralWaybillNumber": "TEST001",
      "FinalMileTrackingNumber": "1Z999AA10123456789",
      "ReplaceStatus": "Y",
      "CreatedAt": "2026-03-30T10:00:00Z"
    }
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Tracking number is required"
}
```

### 2.2 根据中性面单单号获取标签替换请求记录

**接口路径**：`/label-replace/waybill/{waybillNumber}`
**请求方法**：GET
**功能描述**：根据中性面单单号获取标签替换请求记录

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| waybillNumber | string | 是 | 中性面单单号 | "TEST001" |

#### 请求示例

```
GET /api/Label/label-replace/waybill/TEST001
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "waybillNumber": "TEST001",
  "data": {
    "Id": 1,
    "NeutralWaybillNumber": "TEST001",
    "FinalMileTrackingNumber": "1Z999AA10123456789",
    "ReplaceStatus": "Y",
    "CreatedAt": "2026-03-30T10:00:00Z"
  }
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Waybill number is required"
}
```

### 2.3 根据中性面单单号获取标签文件并返回字节流

**接口路径**：`/label-replace/waybill/{waybillNumber}/download`
**请求方法**：GET
**功能描述**：根据中性面单单号获取标签文件并返回字节流

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| waybillNumber | string | 是 | 中性面单单号 | "TEST001" |

#### 请求示例

```
GET /api/Label/label-replace/waybill/TEST001/download
```

#### 响应格式

**成功响应**：
- 响应类型：`application/pdf`
- 响应内容：标签文件的PDF字节流
- 文件名：`label_TEST001.pdf`

**失败响应**：

```json
{
  "status": "error",
  "message": "Label replace request not found for the provided waybill number"
}
```

### 2.4 获取打印预览页面

**接口路径**：`/print-preview`
**请求方法**：GET
**功能描述**：获取打印预览页面

#### 请求参数

无

#### 请求示例

```
GET /api/Label/print-preview
```

#### 响应格式

**成功响应**：
- 响应类型：`text/html`
- 响应内容：打印预览页面的HTML内容

**失败响应**：
- 404 Not Found

### 2.5 测试讯通回传接口

**接口路径**：`/label-scan/test-xuntong-webhook`
**请求方法**：POST
**功能描述**：测试讯通回传接口

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| WaybillNumber | string | 是 | 中性面单单号 | "TEST001" |
| Success | bool | 否 | 是否成功，默认true | true |
| Description | string | 否 | 描述 | "Test webhook" |

#### 请求示例

```json
{
  "WaybillNumber": "TEST001",
  "Success": true,
  "Description": "Test webhook"
}
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "message": "Test webhook sent successfully"
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Waybill number is required"
}
```

### 2.6 记录标签扫描

**接口路径**：`/label-scan/record`
**请求方法**：POST
**功能描述**：记录标签扫描

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| CustomerId | int | 否 | 客户ID | 1 |
| NeutralWaybillNumber | string | 是 | 中性面单单号 | "TEST001" |
| Result | int | 是 | 扫描结果 | 0 |
| CreatedBy | string | 是 | 创建人 | "system" |
| ReferenceNumber | string | 否 | 参考号 | "REF001" |
| FinalMileTrackingNumber | string | 否 | 尾程跟踪单号 | "1Z999AA10123456789" |
| Description | string | 否 | 描述 | "标签扫描" |

#### 请求示例

```json
{
  "CustomerId": 1,
  "NeutralWaybillNumber": "TEST001",
  "Result": 0,
  "CreatedBy": "system",
  "ReferenceNumber": "REF001",
  "FinalMileTrackingNumber": "1Z999AA10123456789",
  "Description": "标签扫描"
}
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "scanRecord": {
    "Id": 1,
    "NeutralWaybillNumber": "TEST001",
    "Result": 0,
    "CreatedBy": "system",
    "CreatedAt": "2026-03-30T12:00:00Z"
  }
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Neutral waybill number is required"
}
```

### 2.7 根据中性面单查询扫描记录列表

**接口路径**：`/label-scan/waybill/{waybillNumber}`
**请求方法**：GET
**功能描述**：根据中性面单查询扫描记录列表

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| waybillNumber | string | 是 | 中性面单单号 | "TEST001" |

#### 请求示例

```
GET /api/Label/label-scan/waybill/TEST001
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "waybillNumber": "TEST001",
  "count": 1,
  "data": [
    {
      "Id": 1,
      "NeutralWaybillNumber": "TEST001",
      "Result": 0,
      "CreatedBy": "system",
      "CreatedAt": "2026-03-30T10:00:00Z"
    }
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Waybill number is required"
}
```

### 2.8 根据客户ID查询扫描记录列表

**接口路径**：`/label-scan/customer/{customerId}`
**请求方法**：GET
**功能描述**：根据客户ID查询扫描记录列表

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| customerId | int | 是 | 客户ID | 1 |

#### 请求示例

```
GET /api/Label/label-scan/customer/1
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "customerId": 1,
  "count": 2,
  "data": [
    {
      "Id": 1,
      "NeutralWaybillNumber": "TEST001",
      "Result": 0,
      "CreatedBy": "system",
      "CreatedAt": "2026-03-30T10:00:00Z"
    },
    {
      "Id": 2,
      "NeutralWaybillNumber": "TEST002",
      "Result": 0,
      "CreatedBy": "system",
      "CreatedAt": "2026-03-30T11:00:00Z"
    }
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during scan record retrieval.",
  "errorDetails": "错误信息"
}
```

### 2.9 获取客户的扫描记录统计

**接口路径**：`/label-scan/stats/customer/{customerId}`
**请求方法**：GET
**功能描述**：获取客户的扫描记录统计

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| customerId | int | 是 | 客户ID | 1 |

#### 请求示例

```
GET /api/Label/label-scan/stats/customer/1
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "customerId": 1,
  "stats": {
    "totalScans": 10,
    "successfulScans": 8,
    "failedScans": 2
  }
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during scan statistics retrieval.",
  "errorDetails": "错误信息"
}
```

### 2.10 批量查询标签替换请求

**接口路径**：`/label-replace/batch`
**请求方法**：GET
**功能描述**：批量查询标签替换请求

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| page | int | 否 | 页码，默认1 | 1 |
| pageSize | int | 否 | 每页数量，默认10 | 10 |
| sortBy | string | 否 | 排序字段，默认CreatedAt | "CreatedAt" |
| sortOrder | string | 否 | 排序方向，默认desc | "desc" |
| billOfLadingNumber | string | 否 | 提单号 | "BOL001" |
| masterPackageNumber | string | 否 | 大包号 | "MP001" |
| referenceNumber | string | 否 | 参考号 | "REF001" |
| neutralWaybillNumber | string | 否 | 中性面单单号 | "TEST001" |
| finalMileTrackingNumber | string | 否 | 尾程跟踪单号 | "1Z999AA10123456789" |
| replaceStatus | string | 否 | 换单状态 | "Y" |
| customerId | int | 否 | 客户ID | 1 |
| callback | string | 否 | JSONP回调函数名 | "callback" |

#### 请求示例

```
GET /api/Label/label-replace/batch?page=1&pageSize=10&sortBy=CreatedAt&sortOrder=desc
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "totalCount": 100,
  "page": 1,
  "pageSize": 10,
  "totalPages": 10,
  "data": [
    {
      "Id": 1,
      "NeutralWaybillNumber": "TEST001",
      "FinalMileTrackingNumber": "1Z999AA10123456789",
      "ReplaceStatus": "Y",
      "CreatedAt": "2026-03-30T10:00:00Z"
    },
    ...
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during batch retrieval.",
  "errorDetails": "错误信息"
}
```

### 2.11 批量查询标签扫描记录

**接口路径**：`/label-scan/batch`
**请求方法**：GET
**功能描述**：批量查询标签扫描记录

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| page | int | 否 | 页码，默认1 | 1 |
| pageSize | int | 否 | 每页数量，默认10 | 10 |
| sortBy | string | 否 | 排序字段，默认CreatedAt | "CreatedAt" |
| sortOrder | string | 否 | 排序方向，默认desc | "desc" |
| customerId | int | 否 | 客户ID | 1 |
| referenceNumber | string | 否 | 参考号 | "REF001" |
| neutralWaybillNumber | string | 否 | 中性面单单号 | "TEST001" |
| finalMileTrackingNumber | string | 否 | 尾程跟踪单号 | "1Z999AA10123456789" |
| result | int | 否 | 扫描结果 | 0 |
| callback | string | 否 | JSONP回调函数名 | "callback" |

#### 请求示例

```
GET /api/Label/label-scan/batch?page=1&pageSize=10&sortBy=CreatedAt&sortOrder=desc
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "totalCount": 50,
  "page": 1,
  "pageSize": 10,
  "totalPages": 5,
  "data": [
    {
      "Id": 1,
      "NeutralWaybillNumber": "TEST001",
      "Result": 0,
      "CreatedBy": "system",
      "CreatedAt": "2026-03-30T10:00:00Z"
    },
    ...
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during batch retrieval.",
  "errorDetails": "错误信息"
}
```

### 2.12 导出标签替换请求为Excel

**接口路径**：`/label-replace/export-excel`
**请求方法**：GET
**功能描述**：导出标签替换请求为Excel

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| billOfLadingNumber | string | 否 | 提单号 | "BOL001" |
| masterPackageNumber | string | 否 | 大包号 | "MP001" |
| referenceNumber | string | 否 | 参考号 | "REF001" |
| neutralWaybillNumber | string | 否 | 中性面单单号 | "TEST001" |
| finalMileTrackingNumber | string | 否 | 尾程跟踪单号 | "1Z999AA10123456789" |
| replaceStatus | string | 否 | 换单状态 | "Y" |
| customerId | int | 否 | 客户ID | 1 |

#### 请求示例

```
GET /api/Label/label-replace/export-excel?customerId=1&replaceStatus=Y
```

#### 响应格式

**成功响应**：
- 响应类型：`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
- 响应内容：Excel文件字节流
- 文件名：`LabelReplaceRequests_20260330_120000.xlsx`

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during export.",
  "errorDetails": "错误信息"
}
```

### 2.13 批量取消订单

**接口路径**：`/label-replace/batch-cancel`
**请求方法**：POST
**功能描述**：批量取消订单

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| CustomerCode | string | 是 | 客户代码 | "TEST" |
| ApiKey | string | 是 | API密钥 | "api_key_123" |
| WaybillNumbers | array | 是 | 中性面单单号列表 | ["TEST001", "TEST002"] |

#### 请求示例

```json
{
  "CustomerCode": "TEST",
  "ApiKey": "api_key_123",
  "WaybillNumbers": ["TEST001", "TEST002"]
}
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "successCount": 2,
  "failedCount": 0,
  "failedItems": [],
  "message": "Batch cancel completed successfully"
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "Waybill numbers are required"
}
```

### 2.14 导出标签扫描记录为Excel

**接口路径**：`/label-scan/export-excel`
**请求方法**：GET
**功能描述**：导出标签扫描记录为Excel

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| customerId | int | 否 | 客户ID | 1 |
| referenceNumber | string | 否 | 参考号 | "REF001" |
| neutralWaybillNumber | string | 否 | 中性面单单号 | "TEST001" |
| finalMileTrackingNumber | string | 否 | 尾程跟踪单号 | "1Z999AA10123456789" |
| result | int | 否 | 扫描结果 | 0 |

#### 请求示例

```
GET /api/Label/label-scan/export-excel?customerId=1&result=0
```

#### 响应格式

**成功响应**：
- 响应类型：`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
- 响应内容：Excel文件字节流
- 文件名：`LabelScanRecords_20260330_120000.xlsx`

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during export.",
  "errorDetails": "错误信息"
}
```

### 2.15 获取客户列表

**接口路径**：`/customers`
**请求方法**：GET
**功能描述**：获取客户列表

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| callback | string | 否 | JSONP回调函数名 | "callback" |

#### 请求示例

```
GET /api/Label/customers
```

#### 响应格式

**成功响应**：

```json
{
  "status": "ok",
  "timestamp": "2026-03-30T12:00:00Z",
  "data": [
    {
      "Id": 1,
      "CustomerCode": "TEST",
      "CustomerName": "测试客户"
    },
    ...
  ]
}
```

**失败响应**：

```json
{
  "status": "error",
  "message": "An unexpected error occurred during customers retrieval.",
  "errorDetails": "错误信息"
}
```

### 2.16 批量查询换单状态

**接口路径**：`/label-replace/status`
**请求方法**：POST
**功能描述**：批量查询换单状态

#### 请求参数

**请求头**：
| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| customerCode | string | 是 | 客户代码 | "TEST" |
| apiKey | string | 是 | API密钥 | "api_key_123" |

**请求体**：
| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| numbers | array | 是 | 单号列表（中性面单或尾程单号） | ["TEST001", "1Z999AA10123456789"] |

#### 请求示例

```json
{
  "numbers": ["TEST001", "1Z999AA10123456789"]
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 200,
  "timestamp": "2026-03-30T12:00:00Z",
  "count": 2,
  "data": [
    {
      "number": "TEST001",
      "status": "Y",
      "message": "Success"
    },
    {
      "number": "1Z999AA10123456789",
      "status": "Y",
      "message": "Success"
    }
  ]
}
```

**失败响应**：

```json
{
  "code": 400,
  "message": "customerCode and apiKey are required in headers"
}
```

## 3. 接口调用示例

### 3.1 使用cURL调用

#### 根据跟踪单号获取标签替换请求记录

```bash
curl -X GET "http://localhost:5002/api/Label/label-replace/tracking/1Z999AA10123456789"
```

#### 根据中性面单单号获取标签文件

```bash
curl -X GET "http://localhost:5002/api/Label/label-replace/waybill/TEST001/download" -o "label_TEST001.pdf"
```

#### 记录标签扫描

```bash
curl -X POST "http://localhost:5002/api/Label/label-scan/record" \
  -H "Content-Type: application/json" \
  -d '{"NeutralWaybillNumber": "TEST001", "Result": 0, "CreatedBy": "system"}'
```

#### 批量查询换单状态

```bash
curl -X POST "http://localhost:5002/api/Label/label-replace/status" \
  -H "Content-Type: application/json" \
  -H "customerCode: TEST" \
  -H "apiKey: api_key_123" \
  -d '{"numbers": ["TEST001", "1Z999AA10123456789"]}'
```

### 3.2 使用PowerShell调用

#### 根据跟踪单号获取标签替换请求记录

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/Label/label-replace/tracking/1Z999AA10123456789" `
  -Method GET
```

#### 根据中性面单单号获取标签文件

```powershell
Invoke-WebRequest -Uri "http://localhost:5002/api/Label/label-replace/waybill/TEST001/download" `
  -Method GET `
  -OutFile "label_TEST001.pdf"
```

#### 记录标签扫描

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/Label/label-scan/record" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{"NeutralWaybillNumber": "TEST001", "Result": 0, "CreatedBy": "system"}'
```

#### 批量查询换单状态

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/Label/label-replace/status" `
  -Method POST `
  -ContentType "application/json" `
  -Headers @{"customerCode"="TEST"; "apiKey"="api_key_123"} `
  -Body '{"numbers": ["TEST001", "1Z999AA10123456789"]}'
```

## 4. 业务流程示例

### 4.1 标签下载流程

1. **查询标签替换记录**：根据中性面单单号查询标签替换记录
2. **下载标签文件**：获取标签文件并返回字节流
3. **记录扫描**：记录标签扫描操作

### 4.2 流程示例

```
# 1. 查询标签替换记录
GET /api/Label/label-replace/waybill/TEST001

# 2. 下载标签文件
GET /api/Label/label-replace/waybill/TEST001/download

# 3. 记录扫描
POST /api/Label/label-scan/record
{"NeutralWaybillNumber": "TEST001", "Result": 0, "CreatedBy": "system"}
```

## 5. 注意事项

### 5.1 接口调用限制

- 批量操作时，建议单次处理数量不超过100个
- 频繁的接口调用可能会影响系统性能，建议合理控制调用频率

### 5.2 数据验证

- 中性面单单号不能为空
- 跟踪单号不能为空
- 批量操作时，单号列表不能为空

### 5.3 认证要求

- 部分接口需要在请求头中提供customerCode和apiKey进行认证
- 请确保使用正确的API凭证进行调用

## 6. 常见问题

### 6.1 标签下载失败

**可能原因**：
- 中性面单单号不存在
- 标签数据不可用
- 订单被冻结

**解决方案**：
- 检查中性面单单号是否正确
- 确认订单状态是否正常
- 联系系统管理员获取帮助

### 6.2 认证失败

**可能原因**：
- customerCode或apiKey不正确
- 认证信息未在请求头中提供

**解决方案**：
- 确保在请求头中提供正确的customerCode和apiKey
- 联系系统管理员获取正确的API凭证

### 6.3 批量操作失败

**可能原因**：
- 单号列表为空
- 部分单号不存在或状态异常

**解决方案**：
- 确保单号列表不为空
- 检查单号是否正确且状态正常

## 7. 接口版本管理

| 版本 | 变更内容 | 发布日期 |
|------|----------|----------|
| v1.0 | 初始版本，包含所有基础接口 | 2026-03-30 |

## 8. 联系信息

如有接口使用问题，请联系系统管理员或开发团队。