# 袋牌模块接口对接文档

## 1. 接口概述

袋牌模块提供了一系列RESTful API接口，用于袋牌的生成、打开、关闭以及与尾程运单号的关联操作。本文档详细描述了这些接口的使用方法、请求参数和响应格式。



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



### 1.1 接口基础信息

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

### 1.2 状态码说明

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

## 2. 接口详细说明

### 2.1 生成袋牌号

**接口路径**：`/generate`
**请求方法**：POST
**功能描述**：根据渠道商名称和数量生成袋牌号

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| ChannelName | string | 是 | 渠道商名称 | "USPS" |
| Count | int | 否 | 生成数量，默认1 | 5 |
| Creator | string | 否 | 创建人，默认"system" | "test_user" |

#### 请求示例

```json
{
  "ChannelName": "USPS",
  "Count": 3,
  "Creator": "test_user"
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": [
    "USPS202601271200000001",
    "USPS202601271200000002",
    "USPS202601271200000003"
  ]
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

### 2.2 打开袋牌

**接口路径**：`/open`
**请求方法**：POST
**功能描述**：将袋牌状态设置为"打开"

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001" |

#### 请求示例

```json
{
  "TagNumber": "USPS202601271200000001"
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "Bag tag opened successfully",
  "data": {
    "waybillCount": 10
  }
}
```

**失败响应**：

```json
{
  "code": 1001,
  "message": "Failed to open bag tag. It may not exist or closed.",
  "data": {}
}
```

### 2.3 关闭袋牌

**接口路径**：`/close`
**请求方法**：POST
**功能描述**：将袋牌状态设置为"关闭"

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001" |

#### 请求示例

```json
{
  "TagNumber": "USPS202601271200000001"
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "Bag tag closed successfully",
  "data": {
    "waybillCount": 10
  }
}
```

**失败响应**：

```json
{
  "code": 1002,
  "message": "Failed to close bag tag. It may not exist or already closed."
}
```

### 2.4 关联尾程运单号

**接口路径**：`/associate-waybill`
**请求方法**：POST
**功能描述**：将尾程运单号与袋牌建立关联

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| TagNumber | string | 是 | 袋牌号 | "USPS202601271200000001" |
| FinalMileTrackingNumber | string | 是 | 尾程运单号 | "1Z999AA10123456789" |
| Creator | string | 否 | 创建人，默认"system" | "test_user" |

#### 请求示例

```json
{
  "TagNumber": "USPS202601271200000001",
  "FinalMileTrackingNumber": "1Z999AA10123456789",
  "Creator": "test_user"
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "Final mile tracking number associated successfully",
  "data": {
    "waybillCount": 10
  }
}
```

**失败响应**：

```json
{
  "code": 10031,
  "message": "Bag tag not found"
}
```

```json
{
  "code": 10032,
  "message": "Bag tag is not in opened status"
}
```

```json
{
  "code": 10033,
  "message": "Channel does not match between bag tag and tracking number"
}
```

### 2.5 获取袋牌信息

**接口路径**：`/{tagNumber}`
**请求方法**：GET
**功能描述**：根据袋牌号获取袋牌详细信息，包含关联的小包数量

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001" |

#### 请求示例

```
GET /api/bagtag/USPS202601271200000001
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "Id": 1,
    "TagNumber": "TESTBAG001",
    "ChannelName": "USPS",
    "Status": "Opened",
    "Creator": "system",
    "CreatedAt": "2026-01-27T12:00:00Z",
    "OpenedAt": "2026-01-27T12:05:00Z",
    "ClosedAt": null,
    "waybillCount": 10
  }
}
```

**失败响应**：

```json
{
  "code": 1004,
  "message": "Bag tag not found"
}
```

### 2.6 获取袋牌关联的尾程运单号

**接口路径**：`/{tagNumber}/waybills`
**请求方法**：GET
**功能描述**：获取指定袋牌关联的所有尾程运单号

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001" |

#### 请求示例

```
GET /api/bagtag/USPS202601271200000001/waybills
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": [
    {
      "Id": 1,
      "TagNumber": "USPS202601271200000001",
      "FinalMileTrackingNumber": "1Z999AA10123456789",
      "CreatedAt": "2026-01-27T12:10:00Z"
    },
    {
      "Id": 2,
      "TagNumber": "USPS202601271200000001",
      "FinalMileTrackingNumber": "1Z999AA10123456790",
      "CreatedAt": "2026-01-27T12:15:00Z"
    }
  ]
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

### 2.7 查询袋牌关联小包数量

**接口路径**：`/{tagNumber}/waybill-count`
**请求方法**：GET
**功能描述**：查询指定袋牌关联的小包数量

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001" |

#### Mock数据

| 袋牌号 | 返回数量 |
|-------|----------|
| TESTBAG001 | 10 |
| TESTBAG002 | 5 |
| TESTBAG003 | 0 |

#### 请求示例

```
GET /api/bagtag/TESTBAG001/waybill-count
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "tagNumber": "TESTBAG001",
    "waybillCount": 10
  }
}
```

**失败响应**：

```json
{
  "code": 9999,
  "message": "错误信息"
}
```

### 2.8 移除袋牌和小包关联

**接口路径**：`/remove-waybill`
**请求方法**：POST
**功能描述**：移除袋牌和小包的关联关系

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| TagNumber | string | 是 | 袋牌号 | "TESTBAG001" |
| FinalMileTrackingNumber | string | 是 | 尾程运单号 | "TESTWAYBILL001" |

#### Mock数据

| 袋牌号 | 尾程运单号 | 返回结果 |
|-------|-----------|----------|
| TESTBAG001 | TESTWAYBILL001 | 成功 |
| TESTBAG001 | TESTWAYBILL999 | 失败（运单未关联） |
| TESTBAG999 | 任意 | 失败（袋牌不存在） |

#### 请求示例

```json
{
  "TagNumber": "TESTBAG001",
  "FinalMileTrackingNumber": "TESTWAYBILL001"
}
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "Waybill removed from bag tag successfully"
}
```

**失败响应**：

```json
{
  "code": 10031,
  "message": "Bag tag not found"
}
```

```json
{
  "code": 10032,
  "message": "Bag tag is not in opened status"
}
```

```json
{
  "code": 10034,
  "message": "Waybill is not associated with this bag tag"
}
```

### 2.9 根据扫描单号查询袋牌与小包关联信息

**接口路径**：`/waybill/{finalMileTrackingNumber}`
**请求方法**：GET
**功能描述**：根据尾程运单号查询袋牌与小包的关联信息

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| finalMileTrackingNumber | string | 是 | 尾程运单号（路径参数） | "1Z999AA10123456789" |

#### 请求示例

```
GET /api/bagtag/waybill/1Z999AA10123456789
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "Id": 1,
    "TagNumber": "USPS202601271200000001",
    "FinalMileTrackingNumber": "1Z999AA10123456789",
    "Creator": "system",
    "CreatedAt": "2026-01-27T12:10:00Z",
    "Remark": null,
    "bagTag": {
      "ChannelName": "USPS",
      "Status": "Opened",
      "OpenedAt": "2026-01-27T12:05:00Z",
      "ClosedAt": null
    }
  }
}
```

**失败响应**：

```json
{
  "code": 10036,
  "message": "Waybill not associated with any bag tag"
}
```

### 2.10 袋牌标签打印

**接口路径**：`/{tagNumber}/print`
**请求方法**：GET
**功能描述**：打印袋牌标签，返回PDF格式的袋牌字节流

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| tagNumber | string | 是 | 袋牌号（路径参数） | "USPS202601271200000001" |

#### 请求示例

```
GET /api/bagtag/USPS202601271200000001/print
```

#### 响应格式

**成功响应**：
- 响应类型：`application/pdf`
- 响应内容：袋牌标签的PDF字节流
- 文件名：`bag_tag_{tagNumber}.pdf`

**失败响应**：
- 响应类型：`application/pdf`
- 响应内容：空字节流

### 2.11 查询可用袋牌

**接口路径**：`/available`
**请求方法**：GET
**功能描述**：查询指定渠道的可用袋牌（已关闭且未绑定到出库交接单的袋牌）

#### 请求参数

| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|-------|------|------|------|--------|
| channel | string | 是 | 渠道商名称 | "USPS" |

#### 请求示例

```
GET /api/bagtag/available?channel=USPS
```

#### 响应格式

**成功响应**：

```json
{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": 1,
      "tagNumber": "USPS202601271200000001",
      "channelName": "USPS",
      "status": "Closed",
      "creator": "system",
      "createdAt": "2026-01-27T12:00:00Z",
      "openedAt": "2026-01-27T12:05:00Z",
      "closedAt": "2026-01-27T12:30:00Z",
      "waybillCount": 10
    }
  ]
}
```

**失败响应**：

```json
{
  "code": 400,
  "message": "Channel parameter is required"
}
```

```json
{
  "code": 9999,
  "message": "错误信息"
}
```


## 3. 接口调用示例

### 3.1 使用cURL调用

#### 生成袋牌号

```bash
curl -X POST "http://localhost:5002/api/bagtag/generate" \
  -H "Content-Type: application/json" \
  -d '{"ChannelName": "USPS", "Count": 2}'
```

#### 打开袋牌

```bash
curl -X POST "http://localhost:5002/api/bagtag/open" \
  -H "Content-Type: application/json" \
  -d '{"TagNumber": "USPS202601271200000001"}'
```

#### 关联尾程运单号

```bash
curl -X POST "http://localhost:5002/api/bagtag/associate-waybill" \
  -H "Content-Type: application/json" \
  -d '{"TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789"}'
```

#### 打印袋牌标签

```bash
curl -X GET "http://localhost:5002/api/bagtag/USPS202601271200000001/print" \
  -o "bag_tag_USPS202601271200000001.pdf"
```

### 3.2 使用PowerShell调用

#### 生成袋牌号

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/bagtag/generate" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{"ChannelName": "USPS", "Count": 2}'
```

#### 打开袋牌

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/bagtag/open" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{"TagNumber": "USPS202601271200000001"}'
```

#### 关联尾程运单号

```powershell
Invoke-RestMethod -Uri "http://localhost:5002/api/bagtag/associate-waybill" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{"TagNumber": "USPS202601271200000001", "FinalMileTrackingNumber": "1Z999AA10123456789"}'
```

#### 打印袋牌标签

```powershell
Invoke-WebRequest -Uri "http://localhost:5002/api/bagtag/USPS202601271200000001/print" `
  -Method GET `
  -OutFile "bag_tag_USPS202601271200000001.pdf"
```

## 4. 业务流程示例

### 4.1 完整业务流程

1. **生成袋牌**：根据渠道商生成袋牌号
2. **打开袋牌**：将袋牌状态设置为"打开"
3. **关联尾程运单号**：将尾程运单号与袋牌建立关联
4. **关闭袋牌**：当袋牌使用完毕后，将其状态设置为"关闭"

### 4.2 流程示例

```
# 1. 生成袋牌
POST /api/bagtag/generate
{"ChannelName": "UPS", "Count": 1}

# 2. 打开袋牌
POST /api/bagtag/open
{"TagNumber": "UPS202601271200000001"}

# 3. 关联尾程运单号
POST /api/bagtag/associate-waybill
{"TagNumber": "UPS202601271200000001", "FinalMileTrackingNumber": "1Z888BB20234567890"}

# 4. 关闭袋牌
POST /api/bagtag/close
{"TagNumber": "UPS202601271200000001"}

# 5. 打印袋牌标签
GET /api/bagtag/UPS202601271200000001/print
```

## 5. 注意事项

### 5.1 袋牌状态管理

- 只有状态为"Generated"的袋牌才能被打开
- 只有状态为"Opened"的袋牌才能关联尾程运单号
- 只有状态为"Opened"的袋牌才能被关闭
- 已关闭的袋牌不能再次打开或关联尾程运单号

### 5.2 袋牌号唯一性

- 系统确保生成的袋牌号唯一
- 袋牌号格式：`{渠道商名称}{时间戳}{序号}`
- 时间戳精确到秒，序号为4位数字

### 5.3 数据验证

- 渠道商名称不能为空
- 袋牌号不能为空且必须存在
- 尾程运单号不能为空
- 生成数量必须为正整数

### 5.4 性能考虑

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

## 6. 常见问题

### 6.1 生成袋牌失败

**可能原因**：
- 渠道商名称为空
- 生成数量为负数或零

**解决方案**：
- 确保渠道商名称不为空
- 确保生成数量为正整数

### 6.2 打开袋牌失败

**可能原因**：
- 袋牌不存在
- 袋牌已被打开
- 袋牌已被关闭

**解决方案**：
- 检查袋牌号是否正确
- 检查袋牌当前状态

### 6.3 关联尾程运单号失败

**可能原因**：
- 袋牌不存在
- 袋牌未被打开
- 袋牌已被关闭

**解决方案**：
- 检查袋牌号是否正确
- 确保袋牌状态为"Opened"

### 6.4 关闭袋牌失败

**可能原因**：
- 袋牌不存在
- 袋牌未被打开
- 袋牌已被关闭

**解决方案**：
- 检查袋牌号是否正确
- 确保袋牌状态为"Opened"

## 7. 接口版本管理

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

## 8. 联系信息

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