Files
junhong_cmp_fiber/docs/前端接口变更说明.md
huang fe4c545308
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m55s
修正数据
2026-04-27 18:10:08 +08:00

1902 lines
55 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.
# 前端接口变更说明
> 最后更新2026-03-20
---
## 目录
1. [接口变更概览](#一接口变更概览)
2. [删除的接口](#二删除的接口)
3. [修改的后台接口](#三修改的后台接口)
4. [新增的后台接口](#四新增的后台接口)
5. [新增的 C 端接口](#五新增的-c-端接口)
6. [认证方式说明](#六认证方式说明)
7. [统一响应格式](#七统一响应格式)
---
## 一、接口变更概览
**C 端接口统一前缀**`/api/c/v1/`
**后台接口统一前缀**`/api/admin/`
### 删除
| 接口 | 说明 |
|------|------|
| `POST /api/personal/login` | 旧个人客户登录,已下线 |
| `POST /api/personal/send-code` | 旧验证码发送,已下线 |
| `POST /api/personal/wechat-oauth-login` | 旧微信登录,已下线 |
| `POST /api/personal/bind-wechat` | 旧微信绑定,已下线 |
| `GET /api/personal/profile` | 旧个人信息,已下线 |
| `/api/h5/*` 下所有路由 | 旧 H5 接口全部下线 |
### 修改(后台)
| 接口 | 变更内容 |
|------|----------|
| `POST /api/admin/shop-package-batch-pricing/batch-update` | 仅支持批量调整成本价(移除 `pricing_target` |
| 所有返回 `PackageResponse` 的套餐接口 | 响应新增 `virtual_ratio``one_time_commission_amount``tier_info``calendar_type``data_reset_cycle``enable_realname_activation` 等字段 |
| `GET /api/admin/iot-cards/standalone` | 响应新增 `virtual_no`(虚拟号)字段 |
| `GET /api/admin/devices` | `device_no` 重命名为 `virtual_no`,新增 `bound_card_count``first_commission_paid``accumulated_recharge` 字段 |
| 运营商创建/编辑接口 | 新增 `realname_link_type``realname_link_template` 字段 |
### 新增(后台)
| 接口 | 说明 |
|------|------|
| `PATCH /api/admin/packages/:id/retail-price` | 代理修改自己的套餐零售价 |
| `PATCH /api/admin/iot-cards/:id/deactivate` | 手动停用 IoT 卡 |
| `PATCH /api/admin/devices/:id/deactivate` | 手动停用设备 |
| `POST /api/admin/exchanges` | 发起换货单 |
| `GET /api/admin/exchanges` | 换货单列表 |
| `GET /api/admin/exchanges/:id` | 换货单详情 |
| `POST /api/admin/exchanges/:id/ship` | 发货 |
| `POST /api/admin/exchanges/:id/complete` | 确认完成 |
| `POST /api/admin/exchanges/:id/cancel` | 取消换货 |
| `POST /api/admin/exchanges/:id/renew` | 旧资产转新generation+1 |
| 微信支付配置管理8 个接口) | `GET/POST/PUT/DELETE /api/admin/wechat-configs``active``activate``deactivate` 子路由 |
| 代理预充值4 个接口) | `/api/admin/agent-recharges` 创建/列表/详情/线下确认 |
| 资产管理11 个接口) | `/api/admin/assets/*` 资产解析、状态刷新、套餐、停复机、钱包概况/流水 |
### 新增C 端)
| 接口 | 说明 |
|------|------|
| `POST /api/c/v1/auth/verify-asset` | 资产验证 |
| `POST /api/c/v1/auth/wechat-login` | 公众号登录 |
| `POST /api/c/v1/auth/miniapp-login` | 小程序登录 |
| `POST /api/c/v1/auth/send-code` | 发送验证码 |
| `POST /api/c/v1/auth/bind-phone` | 绑定手机号 |
| `POST /api/c/v1/auth/change-phone` | 换绑手机号 |
| `POST /api/c/v1/auth/logout` | 退出登录 |
| `GET /api/c/v1/asset/info` | 资产基本信息 |
| `GET /api/c/v1/asset/packages` | 可购套餐列表 |
| `GET /api/c/v1/asset/package-history` | 历史套餐列表 |
| `POST /api/c/v1/asset/refresh` | 手动刷新资产状态 |
| `GET /api/c/v1/wallet/detail` | 钱包详情 |
| `GET /api/c/v1/wallet/transactions` | 钱包流水列表 |
| `GET /api/c/v1/wallet/recharge-check` | 充值预检 |
| `POST /api/c/v1/wallet/recharge` | 创建充值订单 |
| `GET /api/c/v1/wallet/recharges` | 充值记录列表 |
| `POST /api/c/v1/orders/create` | 创建套餐购买订单 |
| `GET /api/c/v1/orders` | 订单列表 |
| `GET /api/c/v1/orders/:id` | 订单详情 |
| `GET /api/c/v1/realname/link` | 获取实名跳转链接 |
| `GET /api/c/v1/device/cards` | 设备卡列表 |
| `POST /api/c/v1/device/reboot` | 设备重启 |
| `POST /api/c/v1/device/factory-reset` | 恢复出厂设置 |
| `POST /api/c/v1/device/wifi` | WiFi 配置 |
| `POST /api/c/v1/device/switch-card` | 切卡 |
| `GET /api/c/v1/exchange/pending` | 查询进行中的换货通知 |
| `POST /api/c/v1/exchange/:id/shipping-info` | 填写收货信息 |
---
## 二、删除的接口
以下接口已全部下线,请停止调用:
**旧 H5 接口(`/api/h5/` 下所有路由)**
**旧个人客户接口(`/api/personal/` 下):**
- `POST /api/personal/login`
- `POST /api/personal/send-code`
- `POST /api/personal/wechat-oauth-login`
- `POST /api/personal/bind-wechat`
- `GET /api/personal/profile`
以上接口由新 C 端认证接口(`/api/c/v1/auth/`)替代。
---
## 三、修改的后台接口
### 批量调价接口移除 `pricing_target` 字段
```
POST /api/admin/shop-package-batch-pricing/batch-update
```
**移除请求字段:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `pricing_target` | string | 否 | 已移除,不再支持通过该接口调整零售价 |
**变更说明**:该接口现仅支持批量调整成本价,零售价调整改为独立接口 `PATCH /api/admin/packages/:id/retail-price`
---
### 套餐响应新增字段(`PackageResponse`
所有返回 `PackageResponse` 的套餐接口,响应体新增字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `retail_price` | int64 | 零售价(分),代理商可见 |
| `profit_margin` | int64 | 利润空间(分),仅代理用户可见 |
| `current_commission_rate` | string | 当前返佣比例,仅代理用户可见 |
| `one_time_commission_amount` | int64 | 一次性佣金金额(分),代理视角 |
| `tier_info` | object | 梯度返佣信息(含 `current_rate` / `next_threshold` / `next_rate`),仅代理可见 |
| `virtual_ratio` | float64 | 虚流量比例(`real_data_mb/virtual_data_mb` |
| `calendar_type` | string | 套餐周期类型:`natural_month` / `by_day` |
| `duration_days` | int | 套餐天数(`calendar_type=by_day` 时有值) |
| `data_reset_cycle` | string | 流量重置周期:`daily` / `monthly` / `yearly` / `none` |
| `enable_realname_activation` | bool | 是否启用实名激活 |
---
### IoT 卡列表响应新增 `virtual_no` 字段
接口:
```
GET /api/admin/iot-cards/standalone
```
响应体新增字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `virtual_no` | string | 卡虚拟号(用于客服查找资产) |
---
### 设备列表字段调整
接口:
```
GET /api/admin/devices
```
字段变更如下:
| 变更类型 | 字段 | 类型 | 说明 |
|----------|------|------|------|
| 重命名 | `device_no``virtual_no` | string | 设备虚拟号/别名 |
| 新增 | `bound_card_count` | int | 绑定卡数量 |
| 新增 | `first_commission_paid` | bool | 一次性佣金是否已发放 |
| 新增 | `accumulated_recharge` | int64 | 累计充值金额(分) |
---
### 运营商管理 DTO 新增实名相关字段
运营商创建/编辑接口新增以下字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `realname_link_type` | string | 实名链接类型:`none`(无需实名)/ `template`(模板实名)/ `gateway`(网关实名) |
| `realname_link_template` | string | 实名链接模板(`realname_link_type``template` 时使用) |
---
## 四、新增的后台接口
### 资产停用
#### 手动停用 IoT 卡
```
PATCH /api/admin/iot-cards/:id/deactivate
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`IoT 卡 ID
- **说明**:将卡的 `asset_status` 设为 4已停用
---
#### 手动停用设备
```
PATCH /api/admin/devices/:id/deactivate
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`(设备 ID
- **说明**:将设备的 `asset_status` 设为 4已停用
---
### 换货管理
#### H1 发起换货单
```
POST /api/admin/exchanges
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `old_asset_type` | string | 是 | 旧资产类型:`iot_card`(物联网卡)/ `device`(设备) |
| `old_identifier` | string | 是 | 旧资产标识符ICCID/虚拟号/IMEI/SN1~100 字符 |
| `exchange_reason` | string | 是 | 换货原因1~100 字符 |
| `remark` | string | 否 | 备注,最多 500 字符 |
---
#### H2 换货单列表
```
GET /api/admin/exchanges
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `page` | int | 否 | 页码,最小 1 |
| `page_size` | int | 否 | 每页数量1~100 |
| `status` | int | 否 | 换货状态1待填写信息/ 2待发货/ 3已发货待确认/ 4已完成/ 5已取消 |
| `identifier` | string | 否 | 资产标识符模糊搜索(旧资产/新资产均可) |
| `created_at_start` | string | 否 | 创建时间起始 |
| `created_at_end` | string | 否 | 创建时间结束 |
**响应体list 中每项)**:见下方 `ExchangeOrderResponse` 字段说明。
---
#### H3 换货单详情
```
GET /api/admin/exchanges/:id
```
**路径参数**`id`(换货单 ID
**响应体(`ExchangeOrderResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | uint | 换货单 ID |
| `exchange_no` | string | 换货单号 |
| `old_asset_type` | string | 旧资产类型 |
| `old_asset_id` | uint | 旧资产 ID |
| `old_asset_identifier` | string | 旧资产标识符 |
| `new_asset_type` | string | 新资产类型 |
| `new_asset_id` | uint | 新资产 ID可为空 |
| `new_asset_identifier` | string | 新资产标识符 |
| `recipient_name` | string | 收件人姓名 |
| `recipient_phone` | string | 收件人电话 |
| `recipient_address` | string | 收货地址 |
| `express_company` | string | 快递公司 |
| `express_no` | string | 快递单号 |
| `migrate_data` | bool | 是否执行全量迁移 |
| `migration_completed` | bool | 迁移是否已完成 |
| `migration_balance` | int64 | 迁移转移金额(分) |
| `exchange_reason` | string | 换货原因 |
| `remark` | string | 备注(可为空) |
| `status` | int | 换货状态1~5 |
| `status_text` | string | 换货状态文本 |
| `shop_id` | uint | 所属店铺 ID可为空 |
| `created_at` | string | 创建时间 |
| `updated_at` | string | 更新时间 |
| `creator` | uint | 创建人 ID |
| `updater` | uint | 更新人 ID |
---
#### H4 发货
```
POST /api/admin/exchanges/:id/ship
```
**路径参数**`id`(换货单 ID
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `express_company` | string | 是 | 快递公司1~100 字符 |
| `express_no` | string | 是 | 快递单号1~100 字符 |
| `new_identifier` | string | 是 | 新资产标识符ICCID/虚拟号/IMEI/SN1~100 字符 |
| `migrate_data` | bool | 是 | 是否执行全量迁移true执行false不执行 |
---
#### H5 确认完成
```
POST /api/admin/exchanges/:id/complete
```
**路径参数**`id`(换货单 ID
**请求体**:无
**说明**:若发货时 `migrate_data=true`,确认完成时会执行全量数据迁移(钱包余额、套餐记录等从旧资产迁移到新资产)。
---
#### H6 取消换货
```
POST /api/admin/exchanges/:id/cancel
```
**路径参数**`id`(换货单 ID
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `remark` | string | 否 | 取消备注,最多 500 字符 |
**限制**:仅 `status=1`(待填写信息)或 `status=2`(待发货)时可取消。
---
#### H7 旧资产转新generation+1
```
POST /api/admin/exchanges/:id/renew
```
**路径参数**`id`(换货单 ID
**请求体**:无
**说明**:将旧资产的 `generation` 字段加 1使其可重新销售。
---
### 换货业务流程
```mermaid
flowchart TD
A["后台发起换货\nH1 POST /admin/exchanges"] --> B[换货单创建\nstatus=1 待填写信息]
B --> C["客户端轮询通知\nG1 GET /exchange/pending"]
C --> D["客户端填写收货信息\nG2 POST /exchange/:id/shipping-info"]
D --> E[status=2 待发货]
E --> F["后台发货\nH4 POST /exchanges/:id/ship\n填写快递信息和新资产标识符"]
F --> G[status=3 已发货待确认]
G --> H["后台确认完成\nH5 POST /exchanges/:id/complete"]
H --> I{migrate_data=true?}
I -->|是| J[执行全量数据迁移\n钱包余额、套餐记录迁移到新资产]
I -->|否| K[直接完成]
J --> L[status=4 已完成]
K --> L
L --> M{需要回收旧资产?}
M -->|是| N["后台转新\nH7 POST /exchanges/:id/renew\n旧资产 generation+1 可重新销售"]
M -->|否| O[流程结束]
N --> O
```
**取消流程:**
```mermaid
flowchart TD
A[status=1 待填写信息] -->|H6 取消| C[status=5 已取消]
B[status=2 待发货] -->|H6 取消| C
```
### 换货状态机
| 状态值 | 状态名 | 可执行操作 |
|--------|--------|-----------|
| 1 | 待填写信息 | 客户端填写收货信息G2、后台取消H6 |
| 2 | 待发货 | 后台发货H4、后台取消H6 |
| 3 | 已发货待确认 | 后台确认完成H5 |
| 4 | 已完成 | 后台转新H7可选 |
| 5 | 已取消 | 无 |
---
### 微信支付配置管理
> 权限:仅超级管理员和平台用户可访问。
#### W1 获取当前生效的支付配置
```
GET /api/admin/wechat-configs/active
```
- **认证**:需要后台 Bearer Token
- **请求参数**:无
**响应体(`WechatConfigResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | uint | 配置ID |
| `name` | string | 配置名称 |
| `description` | string | 配置描述 |
| `provider_type` | string | 支付渠道类型 (`wechat`:微信直连, `fuiou`:富友) |
| `is_active` | bool | 是否激活 |
| `oa_app_id` | string | 公众号AppID |
| `oa_app_secret` | string | 公众号AppSecret已脱敏 |
| `oa_token` | string | 公众号Token已脱敏 |
| `oa_aes_key` | string | 公众号AES加密Key已脱敏 |
| `oa_oauth_redirect_url` | string | OAuth回调地址 |
| `miniapp_app_id` | string | 小程序AppID |
| `miniapp_app_secret` | string | 小程序AppSecret已脱敏 |
| `wx_mch_id` | string | 微信商户号 |
| `wx_api_v3_key` | string | 微信APIv3密钥已脱敏 |
| `wx_api_v2_key` | string | 微信APIv2密钥已脱敏 |
| `wx_cert_content` | string | 微信支付证书内容(配置状态) |
| `wx_key_content` | string | 微信支付密钥内容(配置状态) |
| `wx_serial_no` | string | 微信证书序列号 |
| `wx_notify_url` | string | 微信支付回调地址 |
| `fy_ins_cd` | string | 富友机构号 |
| `fy_mchnt_cd` | string | 富友商户号 |
| `fy_term_id` | string | 富友终端号 |
| `fy_private_key` | string | 富友私钥(配置状态) |
| `fy_public_key` | string | 富友公钥(配置状态) |
| `fy_api_url` | string | 富友API地址 |
| `fy_notify_url` | string | 富友支付回调地址 |
| `created_at` | string | 创建时间 |
| `updated_at` | string | 更新时间 |
**敏感字段说明**
- 短密钥字段(如 `oa_app_secret``wx_api_v3_key`)返回 `xxxx***xxxx` 脱敏形式。
- 长文本密钥/证书字段(如 `wx_cert_content``fy_private_key`)返回 `[已配置]``[未配置]`
---
#### W2 支付配置列表
```
GET /api/admin/wechat-configs
```
- **认证**:需要后台 Bearer Token
**Query 参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `page` | int | 否 | 页码,最小 1 |
| `page_size` | int | 否 | 每页数量1~100 |
| `provider_type` | string | 否 | 支付渠道类型 (`wechat`/`fuiou`) |
| `is_active` | bool | 否 | 是否激活 (`true`:已激活, `false`:未激活) |
**响应体(`WechatConfigListResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `list` | array | 配置列表(每项字段同 `WechatConfigResponse` |
| `total` | int64 | 总数 |
| `page` | int | 当前页 |
| `page_size` | int | 每页数量 |
---
#### W3 创建支付配置
```
POST /api/admin/wechat-configs
```
- **认证**:需要后台 Bearer Token
**请求体(`CreateWechatConfigRequest`**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | string | 是 | 配置名称 |
| `description` | string | 否 | 配置描述 |
| `provider_type` | string | 是 | 支付渠道类型 (`wechat`:微信直连, `fuiou`:富友) |
| `oa_app_id` | string | 否 | 公众号AppID |
| `oa_app_secret` | string | 否 | 公众号AppSecret |
| `oa_token` | string | 否 | 公众号Token |
| `oa_aes_key` | string | 否 | 公众号AES加密Key |
| `oa_oauth_redirect_url` | string | 否 | OAuth回调地址 |
| `miniapp_app_id` | string | 否 | 小程序AppID |
| `miniapp_app_secret` | string | 否 | 小程序AppSecret |
| `wx_mch_id` | string | 否 | 微信商户号 |
| `wx_api_v3_key` | string | 否 | 微信APIv3密钥 |
| `wx_api_v2_key` | string | 否 | 微信APIv2密钥 |
| `wx_cert_content` | string | 否 | 微信支付证书内容(PEM格式) |
| `wx_key_content` | string | 否 | 微信支付密钥内容(PEM格式) |
| `wx_serial_no` | string | 否 | 微信证书序列号 |
| `wx_notify_url` | string | 否 | 微信支付回调地址 |
| `fy_ins_cd` | string | 否 | 富友机构号 |
| `fy_mchnt_cd` | string | 否 | 富友商户号 |
| `fy_term_id` | string | 否 | 富友终端号 |
| `fy_private_key` | string | 否 | 富友私钥(PEM格式) |
| `fy_public_key` | string | 否 | 富友公钥(PEM格式) |
| `fy_api_url` | string | 否 | 富友API地址 |
| `fy_notify_url` | string | 否 | 富友支付回调地址 |
**响应体**`WechatConfigResponse`(字段同 W1敏感字段脱敏返回
---
#### W4 支付配置详情
```
GET /api/admin/wechat-configs/:id
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`配置ID
- **响应体**`WechatConfigResponse`(字段同 W1敏感字段脱敏返回
---
#### W5 更新支付配置
```
PUT /api/admin/wechat-configs/:id
```
- **认证**:需要后台 Bearer Token
**路径参数:** `id`配置ID
**请求体(`UpdateWechatConfigRequest`,全字段可选):**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | string | 否 | 配置名称 |
| `description` | string | 否 | 配置描述 |
| `provider_type` | string | 否 | 支付渠道类型 (`wechat`:微信直连, `fuiou`:富友) |
| `oa_app_id` | string | 否 | 公众号AppID |
| `oa_app_secret` | string | 否 | 公众号AppSecret |
| `oa_token` | string | 否 | 公众号Token |
| `oa_aes_key` | string | 否 | 公众号AES加密Key |
| `oa_oauth_redirect_url` | string | 否 | OAuth回调地址 |
| `miniapp_app_id` | string | 否 | 小程序AppID |
| `miniapp_app_secret` | string | 否 | 小程序AppSecret |
| `wx_mch_id` | string | 否 | 微信商户号 |
| `wx_api_v3_key` | string | 否 | 微信APIv3密钥 |
| `wx_api_v2_key` | string | 否 | 微信APIv2密钥 |
| `wx_cert_content` | string | 否 | 微信支付证书内容(PEM格式) |
| `wx_key_content` | string | 否 | 微信支付密钥内容(PEM格式) |
| `wx_serial_no` | string | 否 | 微信证书序列号 |
| `wx_notify_url` | string | 否 | 微信支付回调地址 |
| `fy_ins_cd` | string | 否 | 富友机构号 |
| `fy_mchnt_cd` | string | 否 | 富友商户号 |
| `fy_term_id` | string | 否 | 富友终端号 |
| `fy_private_key` | string | 否 | 富友私钥(PEM格式) |
| `fy_public_key` | string | 否 | 富友公钥(PEM格式) |
| `fy_api_url` | string | 否 | 富友API地址 |
| `fy_notify_url` | string | 否 | 富友支付回调地址 |
**响应体**`WechatConfigResponse`(字段同 W1敏感字段脱敏返回
---
#### W6 删除支付配置
```
DELETE /api/admin/wechat-configs/:id
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`配置ID
- **请求体**:无
- **响应体**:无(仅返回统一成功响应)
---
#### W7 激活支付配置
```
POST /api/admin/wechat-configs/:id/activate
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`配置ID
- **请求体**:无
- **响应体**`WechatConfigResponse`(字段同 W1敏感字段脱敏返回
---
#### W8 停用支付配置
```
POST /api/admin/wechat-configs/:id/deactivate
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`配置ID
- **请求体**:无
- **响应体**`WechatConfigResponse`(字段同 W1敏感字段脱敏返回
---
### 代理预充值
> 权限:企业账号无权访问。
#### R1 创建代理充值订单
```
POST /api/admin/agent-recharges
```
- **认证**:需要后台 Bearer Token
**请求体(`CreateAgentRechargeRequest`**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `shop_id` | uint | 是 | 目标店铺ID代理只能填自己店铺 |
| `amount` | int64 | 是 | 充值金额范围100元~100万元 |
| `payment_method` | string | 是 | 支付方式 (`wechat`:微信在线支付, `offline`:线下转账仅平台可用) |
**响应体(`AgentRechargeResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | uint | 充值记录ID |
| `recharge_no` | string | 充值单号(ARCH前缀) |
| `shop_id` | uint | 店铺ID |
| `shop_name` | string | 店铺名称 |
| `agent_wallet_id` | uint | 代理钱包ID |
| `amount` | int64 | 充值金额(分) |
| `payment_method` | string | 支付方式 (`wechat`:微信在线支付, `offline`:线下转账) |
| `payment_channel` | string | 实际支付通道 (`wechat_direct`:微信直连, `fuyou`:富友, `offline`:线下转账) |
| `payment_config_id` | uint | 关联支付配置ID线下充值为 `null` |
| `payment_transaction_id` | string | 第三方支付流水号 |
| `status` | int | 状态 (1:待支付, 2:已完成, 3:已取消) |
| `paid_at` | string | 支付时间 |
| `completed_at` | string | 完成时间 |
| `created_at` | string | 创建时间 |
| `updated_at` | string | 更新时间 |
---
#### R2 代理充值订单列表
```
GET /api/admin/agent-recharges
```
- **认证**:需要后台 Bearer Token
**Query 参数(`AgentRechargeListRequest`**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `page` | int | 否 | 页码默认1 |
| `page_size` | int | 否 | 每页条数默认20最大100 |
| `shop_id` | uint | 否 | 按店铺ID过滤 |
| `status` | int | 否 | 按状态过滤 (1:待支付, 2:已完成, 3:已取消) |
| `start_date` | string | 否 | 创建时间起始日期(YYYY-MM-DD) |
| `end_date` | string | 否 | 创建时间截止日期(YYYY-MM-DD) |
**响应体(`AgentRechargeListResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `total` | int64 | 总记录数 |
| `page` | int | 当前页码 |
| `page_size` | int | 每页条数 |
| `list` | array | 充值记录列表(每项字段同 `AgentRechargeResponse` |
---
#### R3 代理充值订单详情
```
GET /api/admin/agent-recharges/:id
```
- **认证**:需要后台 Bearer Token
- **路径参数**`id`充值记录ID
- **响应体**`AgentRechargeResponse`(字段同 R1
---
#### R4 确认线下充值
```
POST /api/admin/agent-recharges/:id/offline-pay
```
- **认证**:需要后台 Bearer Token
**路径参数:** `id`充值记录ID
**请求体(`AgentOfflinePayRequest`**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `operation_password` | string | 是 | 操作密码 |
**响应体**`AgentRechargeResponse`(字段同 R1
---
### 资产管理
#### Z1 通过标识符解析资产
```
GET /api/admin/assets/resolve/:identifier
```
- **认证**:需要后台 Bearer Token
- **路径参数**`identifier`(资产标识符,支持虚拟号/ICCID/IMEI/SN/MSISDN
**响应体(`AssetResolveResponse`**
**基础字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| `asset_type` | string | 资产类型:`card``device` |
| `asset_id` | uint | 资产数据库ID |
| `virtual_no` | string | 虚拟号 |
| `status` | int | 资产状态 |
| `batch_no` | string | 批次号 |
| `shop_id` | uint | 所属店铺ID |
| `shop_name` | string | 所属店铺名称 |
| `series_id` | uint | 套餐系列ID |
| `series_name` | string | 套餐系列名称 |
| `first_commission_paid` | bool | 一次性佣金是否已发放 |
| `accumulated_recharge` | int64 | 累计充值金额(分) |
| `activated_at` | string | 激活时间 |
| `created_at` | string | 创建时间 |
| `updated_at` | string | 更新时间 |
**状态聚合字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| `real_name_status` | int | 实名状态0未实名 1实名中 2已实名 |
| `current_package` | string | 当前套餐名称(无套餐时为空) |
| `current_package_usage_id` | uint | 当前主套餐的套餐使用记录 ID无主套餐时为 null |
| `real_total_mb` | int64 | 当前主套餐真实总量(MB) |
| `real_used_mb` | int64 | 当前主套餐真实已用量(MB) |
| `virtual_total_mb` | int64 | 当前主套餐业务停机阈值(MB) |
| `virtual_used_mb` | float64 | 当前主套餐展示已用量(MB) |
| `reduction_pct` | float64 | 展示增幅比例,公式为 `(real_total_mb / virtual_total_mb) - 1` |
| `device_protect_status` | string | 设备保护期状态:`none`/`stop`/`start`(仅 `asset_type=device` |
**绑定关系字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| `iccid` | string | 卡ICCID`asset_type=card` |
| `bound_device_id` | uint | 绑定设备ID`asset_type=card` |
| `bound_device_no` | string | 绑定设备虚拟号(`asset_type=card` |
| `bound_device_name` | string | 绑定设备名称(`asset_type=card` |
| `bound_card_count` | int | 绑定卡数量(`asset_type=device` |
| `cards` | array | 绑定卡列表(`asset_type=device`,每项字段见下) |
**`cards` 子项(`BoundCardInfo`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `card_id` | uint | 卡ID |
| `iccid` | string | ICCID |
| `msisdn` | string | 手机号 |
| `network_status` | int | 网络状态0停机 1开机 |
| `real_name_status` | int | 实名状态 |
| `slot_position` | int | 插槽位置 |
**设备专属字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| `device_name` | string | 设备名称 |
| `imei` | string | 设备IMEI |
| `sn` | string | 设备序列号 |
| `device_model` | string | 设备型号 |
| `device_type` | string | 设备类型 |
| `max_sim_slots` | int | 最大插槽数 |
| `manufacturer` | string | 制造商 |
**卡专属字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| `carrier_id` | uint | 运营商ID |
| `carrier_type` | string | 运营商类型 |
| `carrier_name` | string | 运营商名称 |
| `msisdn` | string | 手机号 |
| `imsi` | string | IMSI |
| `card_category` | string | 卡业务类型 |
| `supplier` | string | 供应商 |
| `activation_status` | int | 激活状态 |
| `enable_polling` | bool | 是否参与轮询 |
| `network_status` | int | 网络状态0停机 1开机`asset_type=card` |
---
#### Z2 资产实时状态
```
GET /api/admin/assets/:identifier/realtime-status
```
- **认证**:需要后台 Bearer Token
**路径参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符(虚拟号/ICCID/IMEI/SN/MSISDN |
**响应体(`AssetRealtimeStatusResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `asset_type` | string | 资产类型:`card``device` |
| `asset_id` | uint | 资产ID |
| `network_status` | int | 网络状态(`asset_type=card`0停机 1开机 |
| `real_name_status` | int | 实名状态(`asset_type=card` |
| `current_month_usage_mb` | float64 | 本月已用流量MB`asset_type=card` |
| `last_sync_time` | string | 最后同步时间(`asset_type=card` |
| `device_protect_status` | string | 保护期状态(`asset_type=device``none`/`stop`/`start` |
| `cards` | array | 绑定卡状态列表(`asset_type=device`,每项字段同 `BoundCardInfo` |
---
#### Z3 刷新资产状态
```
POST /api/admin/assets/:identifier/refresh
```
- **认证**:需要后台 Bearer Token
- **路径参数**:同 Z2
- **请求体**:无
- **响应体**`AssetRealtimeStatusResponse`(字段同 Z2
---
#### Z4 资产套餐列表
```
GET /api/admin/assets/:identifier/packages
```
- **认证**:需要后台 Bearer Token
- **路径参数**:同 Z2
**响应体(数组,每项为 `AssetPackageResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `package_usage_id` | uint | 套餐使用记录ID |
| `package_id` | uint | 套餐ID |
| `package_name` | string | 套餐名称 |
| `package_type` | string | 套餐类型:`formal`/`addon` |
| `usage_type` | string | 使用类型:`single_card`/`device` |
| `status` | int | 状态0待生效 1生效中 2已用完 3已过期 4已失效 |
| `status_name` | string | 状态名称 |
| `real_total_mb` | int64 | 套餐真实总量(MB) |
| `real_used_mb` | int64 | 套餐真实已用量(MB) |
| `virtual_total_mb` | int64 | 套餐业务停机阈值(MB) |
| `virtual_used_mb` | float64 | 套餐展示已用量(MB) |
| `reduction_pct` | float64 | 展示增幅比例,公式为 `(real_total_mb / virtual_total_mb) - 1` |
| `activated_at` | string | 激活时间(待生效套餐为空) |
| `expires_at` | string | 到期时间(待生效套餐为空) |
| `master_usage_id` | uint | 主套餐ID加油包时有值 |
| `priority` | int | 优先级 |
| `created_at` | string | 创建时间 |
---
#### Z5 当前生效套餐
```
GET /api/admin/assets/:identifier/current-package
```
- **认证**:需要后台 Bearer Token
- **路径参数**:同 Z2
- **响应体**`AssetPackageResponse`(字段同 Z4
- **无主套餐时**:返回 `200 + null`
---
#### Z6 设备停机
```
POST /api/admin/assets/device/:device_id/stop
```
- **认证**:需要后台 Bearer Token
**路径参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `device_id` | uint | 是 | 设备ID |
**响应体(`DeviceSuspendResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `success_count` | int | 成功停机卡数 |
| `fail_count` | int | 失败卡数 |
| `skip_count` | int | 跳过卡数(未实名或已停机) |
| `failed_items` | array | 失败详情(`iccid` / `reason` |
---
#### Z7 设备复机
```
POST /api/admin/assets/device/:device_id/start
```
- **认证**:需要后台 Bearer Token
- **路径参数**`device_id`设备ID
- **请求体**:无
- **响应体**:无(仅返回统一成功响应)
---
#### Z8 单卡停机
```
POST /api/admin/assets/card/:iccid/stop
```
- **认证**:需要后台 Bearer Token
- **路径参数**`iccid`卡ICCID
- **请求体**:无
- **响应体**:无(仅返回统一成功响应)
---
#### Z9 单卡复机
```
POST /api/admin/assets/card/:iccid/start
```
- **认证**:需要后台 Bearer Token
- **路径参数**`iccid`卡ICCID
- **请求体**:无
- **响应体**:无(仅返回统一成功响应)
---
#### Z10 资产钱包概况
```
GET /api/admin/assets/:asset_type/:id/wallet
```
- **认证**:需要后台 Bearer Token
- **路径参数**:同 Z2
**响应体(`AssetWalletResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `wallet_id` | uint | 钱包数据库ID |
| `resource_type` | string | 资源类型:`iot_card``device` |
| `resource_id` | uint | 对应卡或设备的数据库ID |
| `balance` | int64 | 总余额(分) |
| `frozen_balance` | int64 | 冻结余额(分) |
| `available_balance` | int64 | 可用余额 = `balance - frozen_balance`(分) |
| `currency` | string | 币种,目前固定 CNY |
| `status` | int | 钱包状态1-正常 2-冻结 3-关闭 |
| `status_text` | string | 状态文本 |
| `created_at` | string | 创建时间RFC3339 |
| `updated_at` | string | 更新时间RFC3339 |
---
#### Z11 资产钱包流水列表
```
GET /api/admin/assets/:asset_type/:id/wallet/transactions
```
- **认证**:需要后台 Bearer Token
**路径参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `asset_type` | string | 是 | 资产类型:`card``device` |
| `id` | uint | 是 | 资产ID |
**Query 参数:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `page` | int | 否 | 页码默认1 |
| `page_size` | int | 否 | 每页数量默认20最大100 |
| `transaction_type` | string | 否 | 交易类型过滤:`recharge`/`deduct`/`refund` |
| `start_time` | string | 否 | 开始时间RFC3339 |
| `end_time` | string | 否 | 结束时间RFC3339 |
**响应体(`AssetWalletTransactionListResponse`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `list` | array | 流水列表(每项字段见下) |
| `total` | int64 | 总记录数 |
| `page` | int | 当前页码 |
| `page_size` | int | 每页数量 |
| `total_pages` | int | 总页数 |
**`list` 子项(`AssetWalletTransactionItem`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | uint | 流水记录ID |
| `transaction_type` | string | 交易类型:`recharge`/`deduct`/`refund` |
| `transaction_type_text` | string | 交易类型文本:充值/扣款/退款 |
| `amount` | int64 | 变动金额(分),充值为正数,扣款/退款为负数 |
| `balance_before` | int64 | 变动前余额(分) |
| `balance_after` | int64 | 变动后余额(分) |
| `reference_type` | string | 关联业务类型:`recharge``order`(可空) |
| `reference_no` | string | 关联业务编号充值单号CRCH…或订单号ORD…可空 |
| `remark` | string | 备注(可空) |
| `created_at` | string | 流水创建时间RFC3339 |
---
## 五、新增的 C 端接口
所有接口位于 `/api/c/v1/` 下,**认证接口(`/auth/`)无需登录,其余全部需要 JWT 认证**`Authorization: Bearer <token>`)。
---
### 认证(/api/c/v1/auth/
#### A1 资产验证(无需认证)
```
POST /api/c/v1/auth/verify-asset
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符SN/IMEI/虚拟号/ICCID/MSISDN1~50 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `asset_token` | string | 资产令牌5 分钟有效,用于后续登录接口 |
| `expires_in` | int | 过期时间(秒),固定 300 |
---
#### A2 公众号登录(无需认证)
```
POST /api/c/v1/auth/wechat-login
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `code` | string | 是 | 微信 OAuth 授权码 |
| `asset_token` | string | 是 | A1 返回的资产令牌 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `token` | string | 登录 JWT 令牌 |
| `need_bind_phone` | bool | 是否需要绑定手机号true 时引导用户完成 A4+A5 |
| `is_new_user` | bool | 是否新注册用户 |
---
#### A3 小程序登录(无需认证)
```
POST /api/c/v1/auth/miniapp-login
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `code` | string | 是 | 小程序登录凭证 |
| `asset_token` | string | 是 | A1 返回的资产令牌 |
| `nickname` | string | 否 | 用户昵称(前端授权后传入) |
| `avatar_url` | string | 否 | 用户头像 URL前端授权后传入 |
**响应体**:同 A2`token` / `need_bind_phone` / `is_new_user`
---
#### A4 发送验证码(无需认证)
```
POST /api/c/v1/auth/send-code
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `phone` | string | 是 | 手机号,固定 11 位 |
| `scene` | string | 是 | 业务场景:`bind_phone`(绑定手机)/ `change_phone_old`(换绑旧手机验证)/ `change_phone_new`(换绑新手机验证) |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `cooldown_seconds` | int | 冷却秒数,期间不可重复发送 |
---
#### A5 绑定手机号(需 JWT 认证)
```
POST /api/c/v1/auth/bind-phone
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `phone` | string | 是 | 手机号,固定 11 位 |
| `code` | string | 是 | 验证码,固定 6 位 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `phone` | string | 已绑定手机号 |
| `bound_at` | string | 绑定时间 |
---
#### A6 换绑手机号(需 JWT 认证)
```
POST /api/c/v1/auth/change-phone
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `old_phone` | string | 是 | 旧手机号,固定 11 位 |
| `old_code` | string | 是 | 旧手机号验证码,固定 6 位 |
| `new_phone` | string | 是 | 新手机号,固定 11 位 |
| `new_code` | string | 是 | 新手机号验证码,固定 6 位 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `phone` | string | 换绑后手机号 |
| `changed_at` | string | 换绑时间 |
---
#### A7 退出登录(需 JWT 认证)
```
POST /api/c/v1/auth/logout
```
**请求体**:无
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `success` | bool | 是否成功 |
---
### 认证登录完整流程
```mermaid
flowchart TD
A[用户打开客户端] --> B[输入资产标识符\nSN/IMEI/ICCID/虚拟号]
B --> C["A1 POST /auth/verify-asset\n获得 asset_token5分钟有效"]
C --> D{选择登录方式}
D -->|公众号| E["A2 POST /auth/wechat-login\n传入 code + asset_token"]
D -->|小程序| F["A3 POST /auth/miniapp-login\n传入 code + asset_token"]
E --> G{need_bind_phone?}
F --> G
G -->|true 需要绑定| H["A4 POST /auth/send-code\nscene=bind_phone"]
H --> I["A5 POST /auth/bind-phone\n传入 phone + code"]
I --> J[进入主页面]
G -->|false 已绑定| J
```
**换绑手机号流程:**
```mermaid
flowchart TD
A[用户申请换绑] --> B["A4 POST /auth/send-code\nscene=change_phone_old\n发送旧手机验证码"]
B --> C["A4 POST /auth/send-code\nscene=change_phone_new\n发送新手机验证码"]
C --> D["A6 POST /auth/change-phone\n传入 old_phone+old_code+new_phone+new_code"]
D --> E[换绑成功]
```
---
### 资产(/api/c/v1/asset/
#### B1 资产基本信息
```
GET /api/c/v1/asset/info?identifier=xxx
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `asset_type` | string | 资产类型:`card`(卡)/ `device`(设备) |
| `asset_id` | uint | 资产 ID |
| `identifier` | string | 资产标识符 |
| `virtual_no` | string | 虚拟号 |
| `status` | int | 状态0禁用/ 1启用 |
| `real_name_status` | int | 实名状态0未实名/ 1已实名 |
| `carrier_name` | string | 运营商名称 |
| `generation` | string | 制式 |
| `wallet_balance` | int64 | 钱包余额(分) |
---
#### B2 可购套餐列表
```
GET /api/c/v1/asset/packages?identifier=xxx
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
**响应体:**
```json
{
"packages": [
{
"package_id": 1,
"package_name": "月套餐30G",
"package_type": "formal",
"retail_price": 2900,
"cost_price": 2000,
"validity_days": 30,
"is_addon": false,
"data_allowance": 30720,
"data_unit": "MB",
"description": "每月30G流量"
}
]
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `package_id` | uint | 套餐 ID |
| `package_name` | string | 套餐名称 |
| `package_type` | string | 套餐类型:`formal`(正式套餐)/ `addon`(加油包) |
| `retail_price` | int64 | 零售价(分) |
| `cost_price` | int64 | 成本价(分) |
| `validity_days` | int | 有效天数 |
| `is_addon` | bool | 是否加油包 |
| `data_allowance` | int64 | 流量额度 |
| `data_unit` | string | 流量单位 |
| `description` | string | 套餐说明 |
---
#### B3 历史套餐列表
```
GET /api/c/v1/asset/package-history?identifier=xxx&page=1&page_size=20
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符 |
| `page` | int | 是 | 页码,最小 1 |
| `page_size` | int | 是 | 每页数量1~100 |
**响应体**:分页列表,包含 `list` / `total` / `page` / `page_size`
---
#### B4 手动刷新资产状态
```
POST /api/c/v1/asset/refresh
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `refresh_type` | string | 刷新类型:`card`(卡)/ `device`(设备) |
| `accepted` | bool | 是否已受理 |
| `cooldown_seconds` | int | 冷却秒数(期间不可重复刷新) |
---
### 钱包(/api/c/v1/wallet/
#### C1 钱包详情
```
GET /api/c/v1/wallet/detail?identifier=xxx
```
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `wallet_id` | uint | 钱包 ID |
| `resource_type` | string | 资源类型:`iot_card`(物联网卡)/ `device`(设备) |
| `resource_id` | uint | 资源 ID |
| `balance` | int64 | 可用余额(分) |
| `frozen_balance` | int64 | 冻结余额(分) |
| `updated_at` | string | 更新时间 |
---
#### C2 钱包流水列表
```
GET /api/c/v1/wallet/transactions?identifier=xxx&page=1&page_size=20
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符 |
| `transaction_type` | string | 否 | 流水类型筛选 |
| `start_time` | string | 否 | 开始时间 |
| `end_time` | string | 否 | 结束时间 |
| `page` | int | 是 | 页码 |
| `page_size` | int | 是 | 每页数量1~100 |
**响应体list 中每项):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `transaction_id` | uint | 流水 ID |
| `type` | string | 流水类型 |
| `amount` | int64 | 变动金额(分) |
| `balance_after` | int64 | 变动后余额(分) |
| `created_at` | string | 创建时间 |
| `remark` | string | 备注 |
---
#### C3 充值预检
```
GET /api/c/v1/wallet/recharge-check?identifier=xxx
```
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `need_force_recharge` | bool | 是否需要强制充值 |
| `force_recharge_amount` | int64 | 强制充值金额(分) |
| `trigger_type` | string | 触发类型 |
| `min_amount` | int64 | 最小充值金额(分) |
| `max_amount` | int64 | 最大充值金额(分) |
| `message` | string | 提示信息 |
---
#### C4 创建充值订单
```
POST /api/c/v1/wallet/recharge
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
| `amount` | int64 | 是 | 充值金额100~10000000 |
| `payment_method` | string | 是 | 支付方式,目前仅支持 `wechat` |
| `app_type` | string | 是 | 应用类型:`official_account`(公众号)/ `miniapp`(小程序) |
**响应体:**
```json
{
"recharge": {
"recharge_id": 1,
"recharge_no": "RC20260319001",
"amount": 10000,
"status": 0
},
"pay_config": {
"app_id": "wx...",
"timestamp": "1710000000",
"nonce_str": "abc123",
"package": "prepay_id=wx...",
"sign_type": "RSA",
"pay_sign": "..."
}
}
```
`pay_config` 字段直接传给微信 JSAPI 调起支付。
---
#### C5 充值记录列表
```
GET /api/c/v1/wallet/recharges?identifier=xxx&page=1&page_size=20
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符 |
| `status` | int | 否 | 充值状态0待支付/ 1已支付/ 2已关闭 |
| `page` | int | 是 | 页码 |
| `page_size` | int | 是 | 每页数量1~100 |
**响应体list 中每项):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `recharge_id` | uint | 充值 ID |
| `recharge_no` | string | 充值单号 |
| `amount` | int64 | 充值金额(分) |
| `status` | int | 状态0待支付/ 1已支付/ 2已关闭 |
| `payment_method` | string | 支付方式 |
| `created_at` | string | 创建时间 |
| `auto_purchase_status` | string | 自动购包状态 |
---
### 钱包充值流程
```mermaid
flowchart TD
A[用户进入充值页] --> B["C3 GET /wallet/recharge-check\n预检是否需要强充"]
B --> C{need_force_recharge}
C -->|true 需要强充| D[展示强制充值金额\n用户确认]
C -->|false 自由充值| E[用户输入充值金额]
D --> F["C4 POST /wallet/recharge\n创建充值订单"]
E --> F
F --> G[调起微信支付\n使用 pay_config]
G --> H[支付成功]
H --> I[后端回调处理\n余额增加]
I --> J[充值完成]
```
---
### 订单(/api/c/v1/orders/
#### D1 创建套餐购买订单(核心接口)
```
POST /api/c/v1/orders/create
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
| `package_ids` | []uint | 是 | 套餐 ID 列表,至少 1 个 |
| `app_type` | string | 是 | 应用类型:`official_account`(公众号)/ `miniapp`(小程序) |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `order_type` | string | 订单类型:`package`(套餐订单)/ `recharge`(充值订单) |
| `order` | object | 套餐订单信息(`order_type=package` 时有值) |
| `recharge` | object | 充值订单信息(`order_type=recharge` 时有值) |
| `pay_config` | object | 微信支付配置,直接传给 JSAPI |
| `linked_package_info` | object | 关联套餐信息(强充场景下有值) |
`order` 字段结构:
| 字段 | 类型 | 说明 |
|------|------|------|
| `order_id` | uint | 订单 ID |
| `order_no` | string | 订单号 |
| `total_amount` | int64 | 订单总金额(分) |
| `payment_status` | int | 支付状态0待支付/ 1已支付/ 2已取消 |
| `created_at` | string | 创建时间 |
`recharge` 字段结构:
| 字段 | 类型 | 说明 |
|------|------|------|
| `recharge_id` | uint | 充值 ID |
| `recharge_no` | string | 充值单号 |
| `amount` | int64 | 充值金额(分) |
| `status` | int | 状态0待支付/ 1已支付/ 2已关闭 |
| `auto_purchase_status` | string | 自动购包状态 |
`linked_package_info` 字段结构(强充场景):
| 字段 | 类型 | 说明 |
|------|------|------|
| `package_names` | []string | 套餐名称列表 |
| `total_package_amount` | int64 | 套餐总金额(分) |
| `force_recharge_amount` | int64 | 强制充值金额(分) |
| `wallet_credit` | int64 | 钱包抵扣金额(分) |
> **注意**:当余额不足时,后端会自动创建充值订单(`order_type=recharge`),用户支付充值后系统自动购买套餐,前端无需二次调用购买接口。
---
#### D2 订单列表
```
GET /api/c/v1/orders?identifier=xxx&page=1&page_size=20
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符 |
| `payment_status` | int | 否 | 支付状态0待支付/ 1已支付/ 2已取消 |
| `page` | int | 是 | 页码 |
| `page_size` | int | 是 | 每页数量1~100 |
**响应体list 中每项):**
| 字段 | 类型 | 说明 |
|------|------|------|
| `order_id` | uint | 订单 ID |
| `order_no` | string | 订单号 |
| `total_amount` | int64 | 订单总金额(分) |
| `payment_status` | int | 支付状态 |
| `created_at` | string | 创建时间 |
| `package_names` | []string | 套餐名称列表 |
---
#### D3 订单详情
```
GET /api/c/v1/orders/:id
```
**路径参数**`id`(订单 ID
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `order_id` | uint | 订单 ID |
| `order_no` | string | 订单号 |
| `total_amount` | int64 | 订单总金额(分) |
| `payment_status` | int | 支付状态0待支付/ 1已支付/ 2已取消 |
| `payment_method` | string | 支付方式 |
| `created_at` | string | 创建时间 |
| `paid_at` | string | 支付时间(可为空) |
| `completed_at` | string | 完成时间(可为空) |
| `packages` | array | 订单套餐列表 |
`packages` 中每项:
| 字段 | 类型 | 说明 |
|------|------|------|
| `package_id` | uint | 套餐 ID |
| `package_name` | string | 套餐名称 |
| `package_type` | string | 套餐类型:`formal`(正式套餐)/ `addon`(加油包) |
| `price` | int64 | 单价(分) |
| `quantity` | int | 数量 |
---
### 套餐购买流程
```mermaid
flowchart TD
A[用户选择套餐] --> B["D1 POST /orders/create\n传入 identifier + package_ids + app_type"]
B --> C{响应 order_type}
C -->|package 套餐订单| D[调起微信支付\n使用 pay_config]
C -->|recharge 充值订单| E[提示用户需要充值\n显示 linked_package_info 中的金额说明]
E --> F[调起微信支付\n使用 pay_config]
D --> G[支付成功]
F --> G
G --> H[后端支付回调处理]
H -->|套餐订单| I[直接激活套餐]
H -->|充值订单| J[余额到账后自动购买套餐]
I --> K[套餐激活完成]
J --> K
```
> **强充两阶段说明**:当用户钱包余额不足时,后端自动创建充值订单(`order_type=recharge`)。用户支付充值金额后,系统自动扣款购买套餐,前端无需再次调用购买接口。`linked_package_info` 字段包含套餐名称和金额明细,可用于向用户展示说明。
---
### 实名(/api/c/v1/realname/
#### E1 获取实名跳转链接
```
GET /api/c/v1/realname/link?identifier=xxx&iccid=xxx
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
| `iccid` | string | 否 | 物联网卡 ICCID设备场景下指定具体卡 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `realname_mode` | string | 实名模式:`none`(无需实名)/ `template`(模板实名)/ `gateway`(网关实名) |
| `realname_url` | string | 实名跳转链接 |
| `card_info` | object | 卡片简要信息 |
| `expire_at` | string | 链接过期时间(可为空) |
`card_info` 字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `iccid` | string | 物联网卡 ICCID |
| `msisdn` | string | 手机号 |
| `virtual_no` | string | 虚拟号 |
---
### 设备(/api/c/v1/device/
#### F1 设备卡列表
```
GET /api/c/v1/device/cards?identifier=xxx
```
**响应体:**
```json
{
"cards": [
{
"card_id": 1,
"iccid": "898600...",
"msisdn": "1380000...",
"carrier_name": "中国移动",
"network_status": "online",
"real_name_status": 1,
"slot_position": 1,
"is_active": true
}
]
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `card_id` | uint | 卡 ID |
| `iccid` | string | 物联网卡 ICCID |
| `msisdn` | string | 手机号 |
| `carrier_name` | string | 运营商名称 |
| `network_status` | string | 网络状态 |
| `real_name_status` | int | 实名状态0未实名/ 1已实名 |
| `slot_position` | int | 插槽位置 |
| `is_active` | bool | 是否当前激活卡 |
---
#### F2 设备重启
```
POST /api/c/v1/device/reboot
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `accepted` | bool | 是否已受理 |
| `request_id` | string | 请求 ID |
---
#### F3 恢复出厂设置
```
POST /api/c/v1/device/factory-reset
```
**请求体**:同 F2`identifier` 字段)
**响应体**:同 F2`accepted` / `request_id`
---
#### F4 WiFi 配置
```
POST /api/c/v1/device/wifi
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
| `ssid` | string | 是 | WiFi 名称1~32 字符 |
| `password` | string | 是 | WiFi 密码1~64 字符 |
| `enabled` | bool | 是 | 是否启用 WiFi |
**响应体**:同 F2`accepted` / `request_id`
---
#### F5 切卡
```
POST /api/c/v1/device/switch-card
```
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~50 字符 |
| `target_iccid` | string | 是 | 目标 ICCID1~30 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `accepted` | bool | 是否已受理 |
| `target_iccid` | string | 目标 ICCID |
---
### 换货(/api/c/v1/exchange/
#### G1 查询进行中的换货通知
```
GET /api/c/v1/exchange/pending?identifier=xxx
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `identifier` | string | 是 | 资产标识符1~100 字符 |
**响应体:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | uint | 换货单 ID |
| `exchange_no` | string | 换货单号 |
| `status` | int | 换货状态1~5 |
| `status_text` | string | 换货状态文本 |
| `exchange_reason` | string | 换货原因 |
| `created_at` | string | 创建时间 |
> 若无进行中的换货单,返回空数据(非报错)。
---
#### G2 填写收货信息
```
POST /api/c/v1/exchange/:id/shipping-info
```
**路径参数**`id`(换货单 ID
**请求体:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `recipient_name` | string | 是 | 收件人姓名1~50 字符 |
| `recipient_phone` | string | 是 | 收件人电话1~20 字符 |
| `recipient_address` | string | 是 | 收货地址1~500 字符 |
---
## 六、认证方式说明
| 端 | 认证方式 | Header 格式 |
|----|----------|-------------|
| 后台(`/api/admin/` | Bearer TokenRedis 存储) | `Authorization: Bearer <token>` |
| C 端(`/api/c/v1/` | JWT | `Authorization: Bearer <jwt>` |
**C 端 JWT 获取方式**:通过 A2 公众号登录或 A3 小程序登录接口获取,有效期请参考接口返回。
---
## 七、统一响应格式
所有接口均返回以下格式:
```json
{
"code": 0,
"msg": "success",
"data": { ... },
"timestamp": 1710000000
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | int | 业务状态码0 表示成功 |
| `msg` | string | 提示信息 |
| `data` | object | 业务数据 |
| `timestamp` | int64 | 服务器时间戳(秒) |
**常见错误码:**
| 错误码 | 说明 |
|--------|------|
| 1001 | 缺失认证令牌 |
| 1002 | 无效或过期令牌 |
| 1003 | 权限不足 |
| 1200 | 换货单不存在 |
| 1201 | 换货单状态不允许此操作 |
| 1202 | 旧资产不存在或已停用 |
| 1203 | 新资产标识符无效 |
| 1204 | 换货单已取消,无法操作 |
| 1205 | 数据迁移失败 |
| 1206 | 收货信息填写超时 |
| 4000 | 参数错误 |
| 5000 | 服务器内部错误 |