All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m54s
- 重构 Worker 启动流程,引入 bootstrap 模块统一管理依赖注入 - 实现套餐流量重置服务(日/月/年周期重置) - 新增套餐激活排队、加油包绑定、囤货待实名激活逻辑 - 新增订单创建幂等性防重(Redis 业务键 + 分布式锁) - 更新 AGENTS.md/CLAUDE.md:新增注释规范、幂等性规范,移除测试要求 - 添加套餐系统升级完整文档(API文档、使用指南、功能总结、运维指南) - 归档 OpenSpec package-system-upgrade 变更,同步 specs 到主目录 - 新增 queue types 抽象和 Redis 常量定义
278 lines
6.0 KiB
Markdown
278 lines
6.0 KiB
Markdown
# 套餐系统升级 - API 文档
|
||
|
||
## 客户端 API
|
||
|
||
### 查询我的流量使用情况
|
||
|
||
获取当前用户绑定的卡/设备的套餐流量使用情况。
|
||
|
||
**请求**
|
||
|
||
```http
|
||
GET /api/h5/packages/my-usage
|
||
Authorization: Bearer {token}
|
||
```
|
||
|
||
**响应**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "success",
|
||
"data": {
|
||
"main_package": {
|
||
"package_usage_id": 101,
|
||
"package_id": 1,
|
||
"package_name": "月度套餐 30G",
|
||
"data_limit_mb": 30720,
|
||
"data_usage_mb": 15360,
|
||
"status": 1,
|
||
"priority": 1,
|
||
"activated_at": "2025-02-01T00:00:00Z",
|
||
"expires_at": "2025-02-28T23:59:59Z",
|
||
"data_reset_cycle": "monthly",
|
||
"last_reset_at": "2025-02-01T00:00:00Z",
|
||
"next_reset_at": "2025-03-01T00:00:00Z"
|
||
},
|
||
"addon_packages": [
|
||
{
|
||
"package_usage_id": 102,
|
||
"package_id": 5,
|
||
"package_name": "加油包 5G",
|
||
"data_limit_mb": 5120,
|
||
"data_usage_mb": 2048,
|
||
"status": 1,
|
||
"priority": 2,
|
||
"master_usage_id": 101,
|
||
"activated_at": "2025-02-10T00:00:00Z",
|
||
"expires_at": "2025-02-28T23:59:59Z"
|
||
}
|
||
],
|
||
"total": {
|
||
"total_mb": 35840,
|
||
"used_mb": 17408,
|
||
"remaining_mb": 18432
|
||
}
|
||
},
|
||
"timestamp": 1707667200
|
||
}
|
||
```
|
||
|
||
**响应字段说明**
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `main_package` | object | 主套餐信息(可能为 null) |
|
||
| `addon_packages` | array | 加油包列表 |
|
||
| `total.total_mb` | int64 | 总流量(MB) |
|
||
| `total.used_mb` | int64 | 已用流量(MB) |
|
||
| `total.remaining_mb` | int64 | 剩余流量(MB) |
|
||
|
||
**套餐状态 status**
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| 0 | 待生效 |
|
||
| 1 | 生效中 |
|
||
| 2 | 已用完 |
|
||
| 3 | 已过期 |
|
||
| 4 | 已失效 |
|
||
|
||
---
|
||
|
||
## 后台管理 API
|
||
|
||
### 查询套餐流量详单
|
||
|
||
查询指定套餐的每日流量使用记录。
|
||
|
||
**请求**
|
||
|
||
```http
|
||
GET /api/admin/package-usage/{id}/daily-records
|
||
Authorization: Bearer {token}
|
||
```
|
||
|
||
**Query 参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `start_date` | string | 是 | 开始日期(YYYY-MM-DD) |
|
||
| `end_date` | string | 是 | 结束日期(YYYY-MM-DD) |
|
||
|
||
**响应**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "success",
|
||
"data": {
|
||
"package_usage_id": 101,
|
||
"package_name": "月度套餐 30G",
|
||
"records": [
|
||
{
|
||
"date": "2025-02-01",
|
||
"daily_usage_mb": 1024,
|
||
"cumulative_usage_mb": 1024
|
||
},
|
||
{
|
||
"date": "2025-02-02",
|
||
"daily_usage_mb": 512,
|
||
"cumulative_usage_mb": 1536
|
||
},
|
||
{
|
||
"date": "2025-02-03",
|
||
"daily_usage_mb": 2048,
|
||
"cumulative_usage_mb": 3584
|
||
}
|
||
],
|
||
"total_usage_mb": 15360
|
||
},
|
||
"timestamp": 1707667200
|
||
}
|
||
```
|
||
|
||
**错误码**
|
||
|
||
| 错误码 | 说明 |
|
||
|-------|------|
|
||
| 400 | 参数错误(日期格式不正确) |
|
||
| 403 | 无权限访问该套餐 |
|
||
| 404 | 套餐不存在 |
|
||
|
||
---
|
||
|
||
### 创建套餐(扩展字段)
|
||
|
||
创建套餐时支持的新字段。
|
||
|
||
**请求**
|
||
|
||
```http
|
||
POST /api/admin/packages
|
||
Authorization: Bearer {token}
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**
|
||
|
||
```json
|
||
{
|
||
"package_name": "月度套餐 30G",
|
||
"package_type": "main",
|
||
"data_limit_mb": 30720,
|
||
"price": 9900,
|
||
"calendar_type": "natural_month",
|
||
"duration_months": 1,
|
||
"data_reset_cycle": "monthly",
|
||
"enable_realname_activation": false
|
||
}
|
||
```
|
||
|
||
**新增字段说明**
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `calendar_type` | string | 是 | 有效期类型:`natural_month`(自然月)、`by_day`(按天) |
|
||
| `duration_months` | int | 条件必填 | 自然月套餐的月数(calendar_type=natural_month 时必填) |
|
||
| `duration_days` | int | 条件必填 | 按天套餐的天数(calendar_type=by_day 时必填) |
|
||
| `data_reset_cycle` | string | 是 | 流量重置周期:`daily`、`monthly`、`yearly`、`none` |
|
||
| `enable_realname_activation` | bool | 否 | 是否需要实名后激活(默认 false) |
|
||
|
||
**calendar_type 取值**
|
||
|
||
| 值 | 说明 | 有效期计算 |
|
||
|----|------|-----------|
|
||
| `natural_month` | 自然月 | 激活月份 + N 个月,月末过期 |
|
||
| `by_day` | 按天 | 激活日期 + N 天 |
|
||
|
||
**data_reset_cycle 取值**
|
||
|
||
| 值 | 说明 | 重置时间 |
|
||
|----|------|---------|
|
||
| `daily` | 日重置 | 每天 00:00:00 |
|
||
| `monthly` | 月重置 | 自然月套餐:每月1号<br>按天套餐:每30天 |
|
||
| `yearly` | 年重置 | 每年1月1日 |
|
||
| `none` | 不重置 | 不重置 |
|
||
|
||
---
|
||
|
||
### 更新套餐(扩展字段)
|
||
|
||
更新套餐时支持的新字段。
|
||
|
||
**请求**
|
||
|
||
```http
|
||
PUT /api/admin/packages/{id}
|
||
Authorization: Bearer {token}
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**请求体**
|
||
|
||
```json
|
||
{
|
||
"calendar_type": "by_day",
|
||
"duration_days": 30,
|
||
"data_reset_cycle": "none",
|
||
"enable_realname_activation": true
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 查询套餐详情(扩展字段)
|
||
|
||
获取套餐详情时返回的新字段。
|
||
|
||
**响应**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"id": 1,
|
||
"package_name": "月度套餐 30G",
|
||
"package_type": "main",
|
||
"data_limit_mb": 30720,
|
||
"price": 9900,
|
||
"calendar_type": "natural_month",
|
||
"duration_months": 1,
|
||
"duration_days": 0,
|
||
"data_reset_cycle": "monthly",
|
||
"enable_realname_activation": false,
|
||
"status": 1,
|
||
"created_at": "2025-01-01T00:00:00Z",
|
||
"updated_at": "2025-01-15T00:00:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误码汇总
|
||
|
||
| 错误码 | HTTP 状态码 | 说明 |
|
||
|-------|------------|------|
|
||
| `CodePackageActivationConflict` | 409 | 套餐正在激活中,请稍后重试 |
|
||
| `CodeNoMainPackage` | 400 | 必须有主套餐才能购买加油包 |
|
||
| `CodeRealnameRequired` | 403 | 设备/卡必须先完成实名认证才能购买套餐 |
|
||
| `CodeMixedOrderForbidden` | 400 | 同订单不能同时购买正式套餐和加油包 |
|
||
|
||
---
|
||
|
||
## 数据权限
|
||
|
||
### 客户端 API
|
||
|
||
- 只能查询当前用户绑定的卡/设备的套餐信息
|
||
- 用户身份通过 JWT Token 识别
|
||
|
||
### 后台管理 API
|
||
|
||
- 代理商:只能查询自己店铺及下级店铺的套餐
|
||
- 企业用户:只能查询自己企业的套餐
|
||
- 平台用户:可查询所有套餐
|
||
- 越权访问返回 403 错误
|