1508 lines
47 KiB
Markdown
1508 lines
47 KiB
Markdown
# 短视频应用接口文档
|
||
|
||
- 版本:v1.0
|
||
- 日期:2026-10-14
|
||
- Base URL:`https://api.example.com/api/v1`
|
||
|
||
> 注意:App 不硬编码 Base URL。启动时优先解析 `txt.256kb.top` 的 DNS TXT 记录获取真实 API 域名;解析失败时按 `md5(yyyyMM) + "_jsnbhh.vip"` 计算兜底域名(详见《01-开发文档》5.5 节)。本文示例域名仅为占位。
|
||
|
||
---
|
||
|
||
## 1. 通用说明
|
||
|
||
### 1.1 请求头
|
||
|
||
| Header | 必填 | 说明 |
|
||
|---|---|---|
|
||
| Content-Type | 是 | `application/json`(文件上传为 `multipart/form-data`) |
|
||
| Authorization | 登录接口必填 | `Bearer <access_token>` |
|
||
| X-Device-ID | 是 | 设备唯一标识(游客计费依赖,首启生成 UUID 持久化) |
|
||
| X-App-Version | 是 | App 版本号(如 1.2.0),用于版本检查与灰度 |
|
||
| X-Platform | 是 | 平台标识:`ios` / `android` |
|
||
| X-Request-ID | 建议 | 客户端请求唯一 ID,用于幂等与链路追踪 |
|
||
|
||
### 1.2 统一响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {},
|
||
"request_id": "8f3c2a1e-..."
|
||
}
|
||
```
|
||
|
||
- `code = 0` 表示成功;非 0 为错误码,`message` 为可展示的错误文案
|
||
- HTTP 状态码:业务错误统一 200 + 业务 code;401/403/429/500 使用标准语义
|
||
|
||
### 1.3 通用错误码
|
||
|
||
| code | 说明 |
|
||
|---|---|
|
||
| 0 | 成功 |
|
||
| 1001 | 参数错误 |
|
||
| 1002 | 未登录或 Token 无效/过期 |
|
||
| 1003 | 无权限(功能需登录/已被封禁) |
|
||
| 1004 | 验证码错误或已过期 |
|
||
| 1005 | 请求过于频繁(限流) |
|
||
| 1006 | 资源不存在 |
|
||
| 1009 | 账号已注销(冻结期内登录可撤销) |
|
||
| 2001 | 积分不足 |
|
||
| 2002 | 今日免费观看次数已用完(游客需登录) |
|
||
| 2003 | 视频不存在或未发布 |
|
||
| 2004 | 已是终身会员,无需再开通 |
|
||
| 3001 | 订单不存在 |
|
||
| 3002 | 订单状态异常(已支付/已关闭) |
|
||
| 3003 | 支付金额不匹配 |
|
||
| 5000 | 服务器内部错误 |
|
||
| 4001 | 无管理员权限或角色不允许该操作 |
|
||
| 4002 | 该操作必须填写原因(reason) |
|
||
| 2101 | 邀请码无效或不可绑定(已绑定/绑定自己/同设备已注册) |
|
||
| 2102 | 资产余额不足 |
|
||
| 2103 | 低于最低提现额度 |
|
||
| 2104 | 已有审核中的提现申请 |
|
||
| 2105 | 内容包含敏感词 |
|
||
| 2106 | 请勿重复举报 |
|
||
| 2107 | 无权操作(非作者本人) |
|
||
|
||
### 1.4 分页约定
|
||
- Feed 流:游标分页。请求 `cursor`(首次不传)+ `limit`;响应返回 `next_cursor`(null 表示没有更多)
|
||
- 普通列表:`page`(从 1 开始)+ `page_size`(默认 20,最大 50),响应含 `total`
|
||
|
||
---
|
||
|
||
## 2. 接口总览
|
||
|
||
| # | 模块 | 方法 | 路径 | 说明 | 登录 |
|
||
|---|---|---|---|---|---|
|
||
| 1 | 认证 | POST | /auth/sms/send | 发送短信验证码 | 否 |
|
||
| 2 | 认证 | POST | /auth/email/send | 发送邮箱验证码 | 否 |
|
||
| 3 | 认证 | POST | /auth/register | 注册(手机/邮箱,可填邀请码,可配置赠送体验会员) | 否 |
|
||
| 4 | 认证 | POST | /auth/login | 登录 | 否 |
|
||
| 5 | 认证 | POST | /auth/token/refresh | 刷新令牌 | 否(带refresh) |
|
||
| 6 | 认证 | POST | /auth/logout | 退出登录 | 是 |
|
||
| 7 | 认证 | POST | /auth/password/reset | 找回密码 | 否 |
|
||
| 8 | 用户 | GET | /users/me | 获取个人信息 | 是 |
|
||
| 9 | 用户 | PUT | /users/me | 修改资料 | 是 |
|
||
| 10 | 用户 | POST | /users/me/avatar | 上传头像 | 是 |
|
||
| 11 | 用户 | GET | /users/me/wallet | 钱包/积分余额 | 是 |
|
||
| 12 | 用户 | GET | /users/me/points/records | 积分明细 | 是 |
|
||
| 13 | 用户 | POST | /users/me/deactivate | 注销账号(7天冻结期) | 是 |
|
||
| 14 | 用户 | GET | /users/{user_id} | 用户公开主页 | 否 |
|
||
| 15 | 用户 | GET | /users/{user_id}/videos | 他人作品列表 | 否 |
|
||
| 16 | 视频 | GET | /videos/feed | 推荐视频流(支持 recommend/latest/hot) | 否 |
|
||
| 17 | 视频 | GET | /videos/{video_id} | 视频详情(登录返回续播进度) | 否 |
|
||
| 18 | 视频 | POST | /videos/{video_id}/watch | 观看上报(计费,可带播放进度) | 否 |
|
||
| 19 | 视频 | POST | /videos/{video_id}/watch/complete | 完整观看上报(创作收益计数) | 否 |
|
||
| 20 | 视频 | POST | /videos/upload/token | 获取上传凭证 | 是 |
|
||
| 21 | 视频 | POST | /videos | 发布视频(上传完成回调) | 是 |
|
||
| 22 | 视频 | PUT | /videos/{video_id} | 编辑视频(仅作者) | 是 |
|
||
| 23 | 视频 | DELETE | /videos/{video_id} | 删除视频(仅作者,软删除) | 是 |
|
||
| 24 | 视频 | GET | /users/me/videos | 我的作品 | 是 |
|
||
| 25 | 视频 | GET | /videos/categories | 分类列表 | 否 |
|
||
| 26 | 视频 | GET | /tags/{tag_name}/videos | 标签视频列表 | 否 |
|
||
| 27 | 视频 | GET | /videos/search | 视频搜索 | 否 |
|
||
| 28 | 视频 | GET | /search/hot | 热搜榜 | 否 |
|
||
| 29 | 互动 | POST | /videos/{video_id}/like | 点赞/取消点赞 | 是 |
|
||
| 30 | 互动 | POST | /videos/{video_id}/favorite | 收藏/取消收藏 | 是 |
|
||
| 31 | 互动 | GET | /videos/{video_id}/comments | 评论列表 | 否 |
|
||
| 32 | 互动 | POST | /videos/{video_id}/comments | 发表评论 | 是 |
|
||
| 33 | 互动 | DELETE | /comments/{comment_id} | 删除评论 | 是 |
|
||
| 34 | 互动 | GET | /users/me/favorites | 我的收藏 | 是 |
|
||
| 35 | 互动 | GET | /users/me/history | 观看历史 | 是 |
|
||
| 36 | 会员 | GET | /membership/plans | 会员套餐列表 | 否 |
|
||
| 37 | 会员 | GET | /membership/me | 我的会员状态 | 是 |
|
||
| 38 | 会员 | POST | /membership/redeem | 积分开通会员 | 是 |
|
||
| 39 | 支付 | GET | /payments/packages | 充值套餐列表(后台可配) | 是 |
|
||
| 40 | 支付 | POST | /payments/recharge | 创建充值订单 | 是 |
|
||
| 41 | 支付 | GET | /payments/orders/{order_no} | 查询订单状态 | 是 |
|
||
| 42 | 支付 | POST | /payments/orders/{order_no}/cancel | 取消订单 | 是 |
|
||
| 43 | 回调 | POST | /callbacks/alipay | 支付宝异步通知 | 平台调用 |
|
||
| 44 | 回调 | POST | /callbacks/wechat | 微信支付异步通知 | 平台调用 |
|
||
| 45 | 激励 | GET | /referral/me | 我的邀请信息 | 是 |
|
||
| 46 | 激励 | POST | /referral/bind | 绑定邀请码 | 是 |
|
||
| 47 | 激励 | GET | /assets/me | 资产钱包 | 是 |
|
||
| 48 | 激励 | GET | /assets/records | 资产流水 | 是 |
|
||
| 49 | 激励 | POST | /assets/withdraw | 申请提现 | 是 |
|
||
| 50 | 激励 | GET | /assets/withdraw/records | 提现记录 | 是 |
|
||
| 51 | 推广归因 | POST | /invite/click | 推广点击埋点(H5 落地页打开即上报) | 否 |
|
||
| 52 | 推广归因 | POST | /invite/match | App 首启归因匹配 | 否 |
|
||
| 53 | 推广归因 | GET | /r/{code} | H5 推广落地页(根路径,非 /api/v1 前缀) | 否 |
|
||
| 54 | 通用 | GET | /app/version | 版本检查 | 否 |
|
||
| 55 | 消息 | GET | /notifications | 通知列表 | 是 |
|
||
| 56 | 消息 | GET | /notifications/unread_count | 未读数 | 是 |
|
||
| 57 | 消息 | POST | /notifications/read | 标记已读 | 是 |
|
||
| 58 | 通用 | POST | /reports | 提交举报 | 是 |
|
||
| 59~90 | 后台管理 | * | /admin/** | 登录、看板、审核、视频/评论管理、用户、积分、订单、补单、套餐、赠送、提现审核、推荐风控、举报处理、敏感词、平台配置、日志,见第 11 章 | 管理员 |
|
||
|
||
---
|
||
|
||
## 3. 认证模块
|
||
|
||
### 3.1 发送短信验证码 `POST /auth/sms/send`
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| phone | string | 是 | 手机号,11 位 |
|
||
| scene | string | 是 | 场景:`register` / `login` / `reset` |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "phone": "13800138000", "scene": "register" }
|
||
```
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{ "code": 0, "message": "ok", "data": { "expire_seconds": 300, "retry_after": 60 } }
|
||
```
|
||
|
||
**限制**:同号码 60 秒 1 条,同号码每天 10 条;注册场景下已注册号码返回错误码 1001("该手机号已注册")。
|
||
|
||
### 3.2 发送邮箱验证码 `POST /auth/email/send`
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| email | string | 是 | 邮箱地址 |
|
||
| scene | string | 是 | `register` / `login` / `reset` |
|
||
|
||
响应同 3.1,`expire_seconds=600`。
|
||
|
||
### 3.3 注册 `POST /auth/register`
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| type | string | 是 | `phone` 或 `email` |
|
||
| phone | string | type=phone 时必填 | 手机号 |
|
||
| email | string | type=email 时必填 | 邮箱 |
|
||
| code | string | 是 | 验证码 |
|
||
| password | string | 是 | 密码,8-32 位,须含字母和数字 |
|
||
| nickname | string | 否 | 昵称,默认"用户+随机尾号" |
|
||
| invite_code | string | 否 | 推荐人邀请码(App 解析分享口令自动预填;未填时服务端取首启模糊归因结果,见 9.7~9.9) |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "type": "phone", "phone": "13800138000", "code": "825314", "password": "abc12345", "nickname": "小明" }
|
||
```
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {
|
||
"user_id": 100023,
|
||
"access_token": "eyJhbGciOi...",
|
||
"refresh_token": "d9f2...",
|
||
"expires_in": 7200,
|
||
"user": { "user_id": 100023, "nickname": "小明", "avatar_url": "", "is_member": true },
|
||
"trial_granted": { "plan_code": "trial", "plan_name": "体验会员", "days": 1, "end_at": "2026-10-15 12:00:00" }
|
||
}
|
||
}
|
||
```
|
||
|
||
- `trial_granted`:注册赠送的体验会员;后台关闭赠送开关(`register_gift_trial.enabled=0`)时为 `null`,`is_member` 相应为 false
|
||
|
||
**错误码**:1004 验证码错误;1001 手机号/邮箱已注册。
|
||
|
||
### 3.4 登录 `POST /auth/login`
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| type | string | 是 | `phone_password` / `phone_code` / `email_password` |
|
||
| phone | string | 手机方式必填 | |
|
||
| email | string | 邮箱方式必填 | |
|
||
| password | string | 密码方式必填 | |
|
||
| code | string | 验证码方式必填 | |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "type": "phone_password", "phone": "13800138000", "password": "abc12345" }
|
||
```
|
||
|
||
**响应**:同 3.3。连续失败 5 次锁定 15 分钟(错误码 1005)。
|
||
|
||
### 3.5 刷新令牌 `POST /auth/token/refresh`
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| refresh_token | string | 是 | 刷新令牌 |
|
||
|
||
**响应**:同 3.3 的 token 部分;refresh_token 旋转(旧值立即失效)。
|
||
|
||
### 3.6 退出登录 `POST /auth/logout`(需登录)
|
||
|
||
无参数。响应 `{ "code": 0 }`。服务端将 access_token 的 jti 加入黑名单并删除 refresh 白名单。
|
||
|
||
### 3.7 找回密码 `POST /auth/password/reset`
|
||
|
||
通过已验证的手机号/邮箱 + 验证码重置密码。重置成功后该用户所有旧 Token(access + refresh)立即失效,需重新登录。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| type | string | 是 | `phone` 或 `email` |
|
||
| phone | string | type=phone 时必填 | 手机号 |
|
||
| email | string | type=email 时必填 | 邮箱 |
|
||
| code | string | 是 | 验证码(scene=`reset`) |
|
||
| new_password | string | 是 | 新密码,8-32 位,须含字母和数字 |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "type": "phone", "phone": "13800138000", "code": "825314", "new_password": "newabc123" }
|
||
```
|
||
|
||
**响应**:`{ "code": 0, "message": "密码已重置,请重新登录" }`
|
||
|
||
**错误码**:1004 验证码错误或已过期;1001 账号不存在。
|
||
|
||
---
|
||
|
||
## 4. 用户模块
|
||
|
||
### 4.1 获取个人信息 `GET /users/me`(需登录)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"user_id": 100023,
|
||
"phone": "138****8000",
|
||
"email": null,
|
||
"nickname": "小明",
|
||
"avatar_url": "https://cdn.example.com/avatar/100023.jpg",
|
||
"bio": "",
|
||
"is_member": true,
|
||
"member_plan": "monthly",
|
||
"member_expire_at": "2026-11-13 12:00:00",
|
||
"points": 86
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 修改资料 `PUT /users/me`(需登录)
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| nickname | string | 否 | 2-20 字 |
|
||
| bio | string | 否 | ≤200 字 |
|
||
| gender | int | 否 | 0/1/2 |
|
||
|
||
响应返回更新后的完整用户对象(同 4.1)。
|
||
|
||
### 4.3 上传头像 `POST /users/me/avatar`(需登录)
|
||
|
||
- `multipart/form-data`,字段名 `file`,jpg/png,≤ 5MB
|
||
- 响应:`{ "code": 0, "data": { "avatar_url": "https://..." } }`
|
||
|
||
### 4.4 钱包信息 `GET /users/me/wallet`(需登录)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"points": 86,
|
||
"total_recharge": 100,
|
||
"total_earned": 6,
|
||
"total_consumed": 20,
|
||
"comment_reward_progress": { "current": 4, "target": 10, "today_rewarded": 1, "daily_limit": 5 }
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.5 积分明细 `GET /users/me/points/records`(需登录)
|
||
|
||
**查询参数**:`page`、`page_size`、`biz_type`(可选:1充值 2观看 3评论奖励 4会员 5赠送 6调整 7扣回)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"total": 35,
|
||
"list": [
|
||
{ "id": 9001, "change_amount": -1, "balance_after": 86, "biz_type": 2, "remark": "观看视频", "created_at": "2026-10-14 12:01:00" },
|
||
{ "id": 8990, "change_amount": 1, "balance_after": 87, "biz_type": 3, "remark": "评论奖励", "created_at": "2026-10-14 11:30:00" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4.6 注销账号 `POST /users/me/deactivate`(需登录)
|
||
|
||
用户主动注销。提交后进入 **7 天冻结期**:期间再次登录即自动撤销注销;到期后账号匿名化(手机号/邮箱置空释放、昵称头像清空、作品全部下架、钱包余额清零作废),Token 立即失效。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| password | string | 是 | 当前登录密码(二次确认) |
|
||
|
||
```json
|
||
// 响应
|
||
{ "code": 0, "data": { "deactivate_at": "2026-10-22 12:00:00", "revoke_before": "2026-10-22 12:00:00" } }
|
||
```
|
||
|
||
**说明**:冻结期内登录返回错误码 1009 并附带 `can_revoke=true`,App 弹窗询问是否撤销注销。
|
||
|
||
### 4.7 用户公开主页 `GET /users/{user_id}`(游客可)
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"user_id": 100023,
|
||
"nickname": "小明",
|
||
"avatar_url": "https://...",
|
||
"bio": "",
|
||
"video_count": 12,
|
||
"total_likes": 3456
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.8 他人作品列表 `GET /users/{user_id}/videos`(游客可)
|
||
|
||
仅返回"已发布"状态作品。
|
||
|
||
**查询参数**:`page`、`page_size`
|
||
|
||
**响应**:`list` 结构同 Feed 单条,含 `total`。
|
||
|
||
---
|
||
|
||
## 5. 视频模块
|
||
|
||
### 5.1 推荐视频流 `GET /videos/feed`(游客可)
|
||
|
||
**查询参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| cursor | string | 否 | 上一页返回的 next_cursor |
|
||
| limit | int | 否 | 默认 10,最大 20 |
|
||
| category_id | int | 否 | 分类筛选 |
|
||
| type | string | 否 | 策略:`recommend`(默认,个性化)/ `latest` / `hot` |
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"next_cursor": "eyJwIjoxNzYwfQ==",
|
||
"list": [
|
||
{
|
||
"video_id": 88001,
|
||
"title": "海边日落",
|
||
"cover_url": "https://cdn.example.com/hls/88001/cover.jpg",
|
||
"video_url": "https://cdn.example.com/hls/88001/index.m3u8",
|
||
"duration": 32,
|
||
"author": { "user_id": 100023, "nickname": "小明", "avatar_url": "https://..." },
|
||
"view_count": 12034,
|
||
"like_count": 456,
|
||
"comment_count": 78,
|
||
"favorite_count": 90,
|
||
"tags": ["日落", "海边"],
|
||
"is_liked": false,
|
||
"is_favorited": false
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
> `is_liked/is_favorited` 仅登录用户返回真实值,游客恒为 false。
|
||
>
|
||
> **recommend 策略**:以"当天日期 + 用户/设备"为随机种子每日重排(同一用户每天的推荐顺序不同、同一天内多次刷新顺序稳定);当日已观看的视频尽量不再出现(候选不足时放开过滤兜底);个性化基于近 7 天观看/点赞/收藏视频的标签偏好加权,游客及新用户退化为热度排序。
|
||
|
||
### 5.2 视频详情 `GET /videos/{video_id}`(游客可)
|
||
|
||
响应字段同 Feed 单条,另含 `description`、`category`、`published_at`。
|
||
登录用户额外返回 `my_position`(本人上次观看进度,秒;无记录为 0),用于断点续播。
|
||
错误码:2003 视频不存在或未发布。
|
||
|
||
### 5.3 观看上报(计费接口)`POST /videos/{video_id}/watch`(游客可)
|
||
|
||
开始播放时调用。客户端本地按 `video_id+日期` 去重,同日同视频只上报一次。
|
||
|
||
**请求参数**(身份取自 Token 或 X-Device-ID)
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| position | int | 否 | 当前播放进度(秒),服务端记录用于续播 |
|
||
|
||
**响应示例(扣费场景)**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"cost_type": 1,
|
||
"cost_points": 1,
|
||
"remaining_points": 86,
|
||
"free_remaining_today": 0
|
||
}
|
||
}
|
||
```
|
||
|
||
**cost_type 说明**
|
||
|
||
| 值 | 含义 | cost_points |
|
||
|---|---|---|
|
||
| 0 | 占用今日免费额度 | 0 |
|
||
| 1 | 积分扣减 | 1 |
|
||
| 2 | 会员免费 | 0 |
|
||
| 3 | 重复观看/本人作品,不计费 | 0 |
|
||
|
||
**错误响应(游客超限)**
|
||
|
||
```json
|
||
{ "code": 2002, "message": "今日免费观看次数已用完,登录后继续观看", "data": { "need_login": true } }
|
||
```
|
||
|
||
**错误响应(积分不足)**
|
||
|
||
```json
|
||
{ "code": 2001, "message": "积分不足,请充值或开通会员", "data": { "points": 0 } }
|
||
```
|
||
|
||
### 5.4 完整观看上报 `POST /videos/{video_id}/watch/complete`(游客可)
|
||
|
||
播放进度 ≥95% 或自然播完时调用,用于创作者收益计数(每 1000 次完整观看 = 1 资产)。服务端校验 `watch_duration` 合理性(不得明显低于视频时长),同一用户/设备同一视频每日仅首次有效。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| watch_duration | int | 是 | 本次实际观看时长(秒) |
|
||
|
||
```json
|
||
// 请求
|
||
{ "watch_duration": 31 }
|
||
// 响应
|
||
{ "code": 0, "data": { "credited": true } }
|
||
```
|
||
|
||
`credited=false`:今日已计数、观看的是本人作品、或时长校验未通过。
|
||
|
||
### 5.5 获取上传凭证 `POST /videos/upload/token`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| file_name | string | 是 | 原始文件名 |
|
||
| file_size | int | 是 | 字节数,≤ 配置上限 |
|
||
| upload_mode | string | 否 | `raw`(默认,服务端转码) / `hls`(已转码的m3u8包) |
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"upload_type": "oss_sts",
|
||
"sts": { "access_key_id": "STS.xxx", "access_key_secret": "xxx", "security_token": "xxx", "expiration": "2026-10-14T13:00:00Z" },
|
||
"object_key": "upload/tmp/20261014/uuid.mp4",
|
||
"bucket": "video-upload",
|
||
"endpoint": "https://oss-cn-hangzhou.aliyuncs.com"
|
||
}
|
||
}
|
||
```
|
||
|
||
> 小部署环境可返回 `upload_type: "server"`,客户端改用 `POST /videos/upload/file`(multipart)经服务端中转。
|
||
|
||
### 5.6 发布视频 `POST /videos`(需登录)
|
||
|
||
上传完成后调用,创建视频记录并进入转码/审核流程。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| object_key | string | 是 | 5.4 返回的 object_key(raw 模式) |
|
||
| m3u8_url | string | hls 模式必填 | 已上传 m3u8 的地址 |
|
||
| title | string | 是 | 1-100 字 |
|
||
| description | string | 否 | ≤500 字 |
|
||
| category_id | int | 是 | 分类 ID |
|
||
| duration | int | hls 模式必填 | 时长(秒) |
|
||
| tags | array[string] | 否 | 标签,0~5 个,每个 1~20 字 |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "object_key": "upload/tmp/20261014/uuid.mp4", "title": "海边日落", "description": "拍摄于青岛", "category_id": 3, "tags": ["日落", "海边"] }
|
||
```
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": { "video_id": 88001, "status": 0, "status_text": "转码中", "is_priority": true }
|
||
}
|
||
```
|
||
|
||
`status`:0转码中 1待审核 2已发布 3拒绝 4下架 5转码失败。会员 `is_priority=true` 进入优先转码队列。
|
||
|
||
### 5.7 我的作品 `GET /users/me/videos`(需登录)
|
||
|
||
查询参数:`page`、`page_size`、`status`(可选)。
|
||
响应列表项同 Feed 单条,另含 `status`、`status_text`、`reject_reason`。
|
||
|
||
### 5.8 分类列表 `GET /videos/categories`
|
||
|
||
```json
|
||
{ "code": 0, "data": [ { "category_id": 1, "name": "生活" }, { "category_id": 2, "name": "美食" } ] }
|
||
```
|
||
|
||
### 5.9 标签视频列表 `GET /tags/{tag_name}/videos`(游客可)
|
||
|
||
播放页点击标签后跳转页面调用本接口。
|
||
|
||
**路径参数**:`tag_name` — 标签名(URL 编码)
|
||
|
||
**查询参数**:`page`、`page_size`、`sort`(`hot` 默认 / `latest`)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"tag": "日落",
|
||
"total": 236,
|
||
"list": [
|
||
{
|
||
"video_id": 88001,
|
||
"title": "海边日落",
|
||
"tags": ["日落", "海边"],
|
||
"cover_url": "https://cdn.example.com/hls/88001/cover.jpg",
|
||
"video_url": "https://cdn.example.com/hls/88001/index.m3u8",
|
||
"author": { "user_id": 100023, "nickname": "小明", "avatar_url": "https://..." },
|
||
"view_count": 12034, "like_count": 456, "comment_count": 78, "favorite_count": 90
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.10 视频搜索 `GET /videos/search`(游客可)
|
||
|
||
**查询参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| keyword | string | 是 | 关键词,1-30 字;命中敏感词返回空结果 |
|
||
| sort | string | 否 | `hot`(默认)/ `latest` |
|
||
| page | int | 否 | 页码 |
|
||
| page_size | int | 否 | 默认 20,最大 50 |
|
||
|
||
**响应**:`list` 结构同 Feed 单条,另含 `total`;搜索行为计入热搜统计(Redis `search:hot`)。
|
||
|
||
### 5.11 热搜榜 `GET /search/hot`(游客可)
|
||
|
||
```json
|
||
{ "code": 0, "data": { "words": ["日落", "美食教程", "猫咪"] } }
|
||
```
|
||
|
||
返回 Top 10 热搜词,来源于 Redis ZSet `search:hot`(搜索计数,定时衰减)。
|
||
|
||
### 5.12 编辑视频 `PUT /videos/{video_id}`(需登录,仅作者)
|
||
|
||
**请求参数**(均可选,传哪个改哪个)
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| title | string | 1-100 字 |
|
||
| description | string | ≤500 字 |
|
||
| category_id | int | 分类 ID |
|
||
| tags | array[string] | 标签,0~5 个,每个 1~20 字 |
|
||
|
||
**响应**:`{ "code": 0, "data": { "video_id": 88001 } }`
|
||
|
||
**错误码**:2107 无权操作(非作者本人);2003 视频不存在。
|
||
|
||
### 5.13 删除视频 `DELETE /videos/{video_id}`(需登录,仅作者)
|
||
|
||
软删除,立即下架不可见;互动计数保留用于后台审计。
|
||
|
||
**响应**:`{ "code": 0 }`
|
||
|
||
**错误码**:2107 无权操作(非作者本人);2003 视频不存在。
|
||
|
||
---
|
||
|
||
## 6. 互动模块
|
||
|
||
### 6.1 点赞/取消 `POST /videos/{video_id}/like`(需登录)
|
||
|
||
无 body,切换式接口(已点赞则取消)。
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{ "code": 0, "data": { "is_liked": true, "like_count": 457 } }
|
||
```
|
||
|
||
### 6.2 收藏/取消 `POST /videos/{video_id}/favorite`(需登录)
|
||
|
||
```json
|
||
{ "code": 0, "data": { "is_favorited": true, "favorite_count": 91 } }
|
||
```
|
||
|
||
### 6.3 评论列表 `GET /videos/{video_id}/comments`(游客可)
|
||
|
||
**查询参数**:`page`、`page_size`、`parent_id`(查二级回复时传父评论 ID)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"total": 78,
|
||
"list": [
|
||
{
|
||
"comment_id": 55001,
|
||
"user": { "user_id": 100030, "nickname": "阿花", "avatar_url": "https://..." },
|
||
"content": "拍得真好",
|
||
"like_count": 12,
|
||
"reply_count": 3,
|
||
"created_at": "2026-10-14 10:00:00"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.4 发表评论 `POST /videos/{video_id}/comments`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| content | string | 是 | 1-500 字;≥5 字才计入积分奖励进度 |
|
||
| parent_id | int | 否 | 回复某评论时传其 ID |
|
||
| reply_to_user_id | int | 否 | 被回复人 ID |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "content": "这个日落太美了,求定位!" }
|
||
```
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"comment_id": 55010,
|
||
"reward_progress": { "current": 5, "target": 10, "rewarded_this_time": false }
|
||
}
|
||
}
|
||
```
|
||
|
||
当 `current` 满 10 时服务端自动发放 1 积分并清零进度,此时返回 `rewarded_this_time: true, reward_points: 1`。
|
||
|
||
### 6.5 删除评论 `DELETE /comments/{comment_id}`(需登录)
|
||
|
||
本人评论或本人视频下的评论可删。已计入奖励进度的评论删除时进度回退(奖励已发的扣回)。
|
||
响应:`{ "code": 0, "data": { "reward_progress": { "current": 4, "target": 10 } } }`
|
||
|
||
### 6.6 我的收藏 `GET /users/me/favorites`(需登录)
|
||
|
||
分页列表,结构同 Feed 单条。
|
||
|
||
### 6.7 观看历史 `GET /users/me/history`(需登录)
|
||
|
||
分页列表,每项:`video`(同 Feed 单条)+ `watched_at` + `cost_type`。
|
||
|
||
---
|
||
|
||
## 7. 会员模块
|
||
|
||
### 7.1 套餐列表 `GET /membership/plans`(游客可)
|
||
|
||
**响应示例**(价格来自服务端配置,前端不硬编码)
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": [
|
||
{ "plan_code": "trial", "name": "体验会员", "days": 1, "points": 5, "enabled": true, "desc": "1天体验,活动同享" },
|
||
{ "plan_code": "monthly", "name": "月卡", "days": 30, "points": 300, "enabled": true, "desc": "30天无限观看" },
|
||
{ "plan_code": "yearly", "name": "年卡", "days": 365, "points": 3650, "enabled": true, "desc": "365天无限观看" },
|
||
{ "plan_code": "lifetime", "name": "终身卡", "days": 0, "points": 10000, "enabled": true, "desc": "永久无限观看" }
|
||
],
|
||
"benefits": ["无限观看视频", "优先上传(转码/审核优先)"]
|
||
}
|
||
```
|
||
|
||
### 7.2 我的会员 `GET /membership/me`(需登录)
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"is_member": true,
|
||
"is_lifetime": false,
|
||
"current_plan": "monthly",
|
||
"plan_name": "月卡",
|
||
"expire_at": "2026-11-13 12:00:00",
|
||
"remaining_days": 30,
|
||
"history": [
|
||
{ "order_no": "M20261014120001", "plan_name": "月卡", "points_cost": 300, "start_at": "2026-10-14 12:00:00", "end_at": "2026-11-13 12:00:00", "source": 1 }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.3 积分开通会员 `POST /membership/redeem`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| plan_code | string | 是 | trial/monthly/yearly/lifetime |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "plan_code": "monthly" }
|
||
```
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"data": {
|
||
"order_no": "M20261014120001",
|
||
"plan_name": "月卡",
|
||
"points_cost": 300,
|
||
"remaining_points": 86,
|
||
"expire_at": "2026-11-13 12:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
**规则**:有效期内重复开通时长叠加;终身卡用户调用返回错误码 2004;积分不足返回 2001。
|
||
|
||
---
|
||
|
||
## 8. 支付模块
|
||
|
||
### 8.1 充值套餐 `GET /payments/packages`(需登录)
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"packages": [
|
||
{ "id": 1, "amount_yuan": 10, "points": 100, "bonus": 0 },
|
||
{ "id": 2, "amount_yuan": 30, "points": 300, "bonus": 0 },
|
||
{ "id": 3, "amount_yuan": 100, "points": 1000, "bonus": 50 },
|
||
{ "id": 4, "amount_yuan": 200, "points": 2000, "bonus": 150 }
|
||
],
|
||
"custom": { "enabled": true, "min_yuan": 1, "max_yuan": 10000, "points_per_yuan": 10 },
|
||
"pay_methods": [
|
||
{ "method": 1, "name": "支付宝" },
|
||
{ "method": 2, "name": "微信支付" },
|
||
{ "method": 3, "name": "USDT (TRC20)" }
|
||
],
|
||
"usdt_rate": 7.2
|
||
}
|
||
}
|
||
```
|
||
|
||
> 充值档位由管理后台实时维护(增删改/上下架/排序),前端不硬编码;`points = amount_yuan × points_per_yuan`,自定义金额同样按此汇率换算。
|
||
|
||
### 8.2 创建充值订单 `POST /payments/recharge`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| amount_yuan | int | 是 | 充值金额(元),须为后台已上架档位,或 `custom.enabled=true` 时的自定义金额 |
|
||
| pay_method | int | 是 | 1支付宝 2微信 3USDT |
|
||
|
||
**请求示例**
|
||
|
||
```json
|
||
{ "amount_yuan": 30, "pay_method": 1 }
|
||
```
|
||
|
||
**响应示例(支付宝)**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"order_no": "R20261014123000001",
|
||
"pay_method": 1,
|
||
"amount_yuan": 30,
|
||
"points": 300,
|
||
"expire_at": "2026-10-14 13:00:00",
|
||
"pay_params": { "order_string": "alipay_sdk=alipay-sdk-php-dynamic&app_id=..." }
|
||
}
|
||
}
|
||
```
|
||
|
||
**响应示例(微信)**:`pay_params` 含 `appid/partnerid/prepayid/package/noncestr/timestamp/sign`,供 App SDK 调起。
|
||
|
||
**响应示例(USDT)**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"order_no": "R20261014123000002",
|
||
"pay_method": 3,
|
||
"amount_yuan": 30,
|
||
"points": 300,
|
||
"usdt_rate": 7.2,
|
||
"usdt_amount": "4.167",
|
||
"receive_address": "TXYz...abc",
|
||
"network": "TRC20",
|
||
"expire_at": "2026-10-14 13:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
> USDT 金额含随机尾差用于订单匹配;用户须按显示金额**精确转账**,满 19 个区块确认后自动到账。
|
||
|
||
### 8.3 查询订单 `GET /payments/orders/{order_no}`(需登录)
|
||
|
||
App 调起支付后每 2 秒轮询,直至 `status != 0` 或超过 30 次。
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"order_no": "R20261014123000001",
|
||
"status": 1,
|
||
"status_text": "已支付",
|
||
"points": 300,
|
||
"paid_at": "2026-10-14 12:35:20",
|
||
"wallet_points": 386
|
||
}
|
||
}
|
||
```
|
||
|
||
`status`:0待支付 1已支付 2已关闭 3已退款。
|
||
|
||
### 8.4 取消订单 `POST /payments/orders/{order_no}/cancel`(需登录)
|
||
|
||
仅"待支付"可取消。响应 `{ "code": 0 }`。
|
||
|
||
### 8.5 支付宝回调 `POST /callbacks/alipay`(平台 → 服务端)
|
||
|
||
- Content-Type:`application/x-www-form-urlencoded`
|
||
- 服务端处理:RSA2 验签 → 校验 `out_trade_no`/`total_amount` → 幂等入账 → 返回纯文本 `success`
|
||
- App 不直接调用本接口
|
||
|
||
### 8.6 微信支付回调 `POST /callbacks/wechat`(平台 → 服务端)
|
||
|
||
- V3 回调:验签(`Wechatpay-Signature` 头)→ AES-GCM 解密 `resource` → 幂等入账 → 返回 `{ "code": "SUCCESS" }`
|
||
|
||
### 8.7 USDT 到账说明
|
||
|
||
USDT 无支付平台回调,由服务端每 15 秒轮询 TronGrid:
|
||
匹配条件 = 收款地址一致 + 金额(含尾差)精确相等 + 转账时间在订单有效期内 + 确认数 ≥ 19。
|
||
匹配成功即入账(`tx_hash` 写入 `third_trade_no`,唯一索引保证幂等);超时未匹配订单自动关闭。
|
||
|
||
---
|
||
|
||
## 9. 激励模块
|
||
|
||
资产体系:**10 资产 = 1 元**,资产存放于资产钱包,可申请提现(后台人工审核打款)。推荐奖励与充值返利仅在**推荐人为会员**时发放(发放时点校验会员身份)。
|
||
|
||
### 9.1 我的邀请 `GET /referral/me`(需登录)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"invite_code": "K7X2M9",
|
||
"invite_url": "https://app.example.com/r/K7X2M9",
|
||
"eligible": true,
|
||
"total_invitees": 12,
|
||
"activated_count": 8,
|
||
"reward_points_total": 80,
|
||
"rebate_assets_total": 150.0
|
||
}
|
||
}
|
||
```
|
||
|
||
- `eligible`:当前是否会员(false 时被推荐人仍可绑定,但不产生奖励)
|
||
|
||
### 9.2 绑定邀请码 `POST /referral/bind`(需登录)
|
||
|
||
注册时未填邀请码的用户,注册后 24 小时内可补绑一次(每人仅能绑定一次)。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| invite_code | string | 是 | 推荐人邀请码 |
|
||
|
||
```json
|
||
// 请求
|
||
{ "invite_code": "K7X2M9" }
|
||
// 响应
|
||
{ "code": 0, "data": { "bound": true, "status": 0, "status_text": "待激活" } }
|
||
```
|
||
|
||
**错误码**:2101(邀请码无效 / 已绑定过 / 绑定自己 / 同设备已注册其他账号)
|
||
|
||
> 被推荐人激活(72h 内累计观看 ≥3 个视频且次日有登录)后,推荐人获得 10 积分(可配置,不限量)。被推荐人此后每次充值成功,推荐人获得"充值积分 × 5%"的资产(不限量)。
|
||
|
||
### 9.3 资产钱包 `GET /assets/me`(需登录)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"assets": 236.5,
|
||
"assets_value_yuan": 23.65,
|
||
"total_earned": 400.0,
|
||
"total_withdrawn": 163.5,
|
||
"min_withdraw_assets": 100,
|
||
"has_pending_withdraw": false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.4 资产流水 `GET /assets/records`(需登录)
|
||
|
||
**查询参数**:`page`、`page_size`、`biz_type`(可选:1充值返利 2完整观看收益 3点赞收益 4提现 5提现退回 6返利扣回 7后台调整)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"total": 21,
|
||
"list": [
|
||
{ "id": 301, "change_amount": 1.0, "balance_after": 236.5, "biz_type": 2, "remark": "视频完整观看收益(视频88001)", "created_at": "2026-10-14 15:00:00" },
|
||
{ "id": 300, "change_amount": 15.0, "balance_after": 235.5, "biz_type": 1, "remark": "推荐用户充值返利", "created_at": "2026-10-14 14:20:00" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.5 申请提现 `POST /assets/withdraw`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| assets | number | 是 | 提现资产数,≥100(可配置),按 10 资产 = 1 元折算 |
|
||
| channel | int | 是 | 1支付宝 2微信 3USDT |
|
||
| account | string | 是 | 收款账号(支付宝账号/微信号/USDT 地址) |
|
||
|
||
```json
|
||
// 请求
|
||
{ "assets": 150, "channel": 1, "account": "user@example.com" }
|
||
// 响应
|
||
{ "code": 0, "data": { "withdraw_no": "W20261014153000001", "assets": 150.0, "amount_yuan": 15.0, "status": 0, "status_text": "待审核" } }
|
||
```
|
||
|
||
**错误码**:2102 资产余额不足;2103 低于最低提现额度;2104 已有审核中的提现申请。
|
||
|
||
> 提交即冻结扣减资产,后台人工审核后打款;审核拒绝资产自动退回资产钱包。
|
||
|
||
### 9.6 提现记录 `GET /assets/withdraw/records`(需登录)
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"total": 2,
|
||
"list": [
|
||
{ "withdraw_no": "W20261014153000001", "assets": 150.0, "amount_yuan": 15.0, "channel": 1, "status": 0, "status_text": "待审核", "created_at": "2026-10-14 15:30:00" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.7 推广点击埋点 `POST /invite/click`(无需登录)
|
||
|
||
H5 推广落地页(9.9)打开时自动调用,记录「邀请码 + IP + UA」用于后续归因。同 IP+code 60 秒内重复上报自动去重。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| code | string | 是 | 推广链接中的邀请码(8 位,自动转大写) |
|
||
|
||
```json
|
||
// 请求
|
||
{ "code": "K7X2M9AB" }
|
||
// 响应
|
||
{ "code": 0, "data": { "recorded": true } }
|
||
```
|
||
|
||
> IP 取自 `X-Real-IP` 头(Nginx 反代透传)或直连来源;点击记录存 Redis 24h 有效。
|
||
|
||
### 9.8 首启归因匹配 `POST /invite/match`(无需登录)
|
||
|
||
App 首次启动且剪贴板无分享口令时调用一次(每安装仅一次)。服务端按 IP 取最近 24h 内最近点击的邀请码,命中则按 device_id 缓存 7 天;用户注册时自动消费该缓存完成推荐绑定(客户端无需也无法回传)。
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| device_id | string | 是 | 设备指纹(与 X-Device-ID 一致) |
|
||
|
||
```json
|
||
// 请求
|
||
{ "device_id": "a1b2c3d4-..." }
|
||
// 响应(未命中)
|
||
{ "code": 0, "data": { "matched": false } }
|
||
// 响应(命中)
|
||
{ "code": 0, "data": { "matched": true, "invite_code": "K7X2M9AB" } }
|
||
```
|
||
|
||
> 命中后重复调用直接返回缓存结果(幂等);注册绑定优先级:显式 invite_code(口令/手填)> 本接口归因缓存。
|
||
|
||
### 9.9 H5 推广落地页 `GET /r/{code}`(浏览器访问,HTML)
|
||
|
||
分享推广链接指向的落地页(根路径,**非** /api/v1 前缀),返回 HTML:
|
||
|
||
- 页面展示邀请人昵称、"复制邀请口令"按钮(口令格式 `#短视频邀请码{code}#`,供被邀请人首启剪贴板解析)
|
||
- system_configs `app.download_url` 已配置时展示"下载 APP"按钮
|
||
- 页面加载即自动调用 9.7 完成点击埋点
|
||
|
||
无效邀请码正常渲染通用页面(不报错),保证分享链接永可用。
|
||
|
||
---
|
||
|
||
## 10. 通用与消息模块
|
||
|
||
### 10.1 版本检查 `GET /app/version`(游客可)
|
||
|
||
App 启动时调用,检查版本更新与公告。
|
||
|
||
**查询参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| platform | string | 是 | `ios` / `android` |
|
||
| version_code | int | 是 | 当前 App 版本号 |
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"latest_version": "1.2.0",
|
||
"latest_version_code": 12,
|
||
"force_update": false,
|
||
"update_url": "https://app.example.com/download",
|
||
"notice": "新版本优化了播放体验"
|
||
}
|
||
}
|
||
```
|
||
|
||
`force_update=true` 时 App 弹强制更新弹窗(不可跳过)。
|
||
|
||
### 10.2 通知列表 `GET /notifications`(需登录)
|
||
|
||
**查询参数**:`type`(可选:1审核结果 2提现进度 3系统公告 4评论回复)、`page`、`page_size`
|
||
|
||
**响应示例**
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"total": 3,
|
||
"list": [
|
||
{ "id": 701, "type": 1, "title": "视频审核通过", "content": "你发布的《海边日落》已通过审核", "biz_id": "88001", "is_read": false, "created_at": "2026-10-14 15:00:00" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 10.3 未读数 `GET /notifications/unread_count`(需登录)
|
||
|
||
```json
|
||
{ "code": 0, "data": { "unread": 3 } }
|
||
```
|
||
|
||
App 我的页消息入口红点依赖本接口(直接读 Redis `notif:unread:{user_id}`)。
|
||
|
||
### 10.4 标记已读 `POST /notifications/read`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| ids | array[int] | 否 | 通知 ID 数组;与 all 二选一 |
|
||
| all | bool | 否 | true 表示全部标记已读 |
|
||
|
||
**响应**:`{ "code": 0 }`
|
||
|
||
### 10.5 提交举报 `POST /reports`(需登录)
|
||
|
||
**请求参数**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| target_type | int | 是 | 1视频 2评论 |
|
||
| target_id | int | 是 | 举报对象 ID |
|
||
| reason_type | int | 是 | 1色情低俗 2暴力血腥 3侵权 4广告营销 5其他 |
|
||
| remark | string | 否 | 补充说明,≤200 字 |
|
||
|
||
```json
|
||
// 请求
|
||
{ "target_type": 1, "target_id": 88001, "reason_type": 1, "remark": "包含不适内容" }
|
||
// 响应
|
||
{ "code": 0, "message": "已收到举报,我们会尽快处理" }
|
||
```
|
||
|
||
**错误码**:2106 请勿重复举报(同一用户对同一对象仅一次有效举报,唯一索引 `uk_user_target` 保证);限流 10 次/天。
|
||
|
||
---
|
||
|
||
## 11. 管理后台接口
|
||
|
||
通用约定:
|
||
- 前缀 `/api/v1/admin`,统一响应结构同 App 接口
|
||
- 认证:`Authorization: Bearer <admin_token>`(Token payload `type="admin"`,有效期 12h,与 App 用户体系互不相通)
|
||
- 角色:`super`(全部)/ `reviewer`(仅审核)/ `operator`(套餐、活动、看板);越权返回 4001
|
||
- 所有写操作记录操作日志;标注【敏感】的接口 `reason` 必填,缺失返回 4002
|
||
|
||
### 11.1 管理员登录 `POST /admin/auth/login`
|
||
|
||
```json
|
||
// 请求
|
||
{ "username": "admin", "password": "xxxx" }
|
||
// 响应
|
||
{ "code": 0, "data": { "admin_token": "eyJ...", "expires_in": 43200, "admin": { "id": 1, "name": "超管", "role": "super" } } }
|
||
```
|
||
|
||
### 11.2 仪表盘 `GET /admin/dashboard`
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"today": { "dau": 1520, "new_users": 86, "recharge_yuan": 4600, "points_issued": 46000, "points_consumed": 12300, "views": 30211 },
|
||
"pending_review_count": 17,
|
||
"total": { "users": 50210, "videos": 8200, "recharge_yuan": 128000 }
|
||
}
|
||
}
|
||
```
|
||
|
||
### 11.3 待审核视频列表 `GET /admin/videos/pending`
|
||
|
||
查询参数:`page`、`page_size`。响应列表项含视频全部字段(含 `video_url` 供在线预览)+ 作者信息。
|
||
|
||
### 11.4 审核视频 `POST /admin/videos/{video_id}/review`
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| action | string | 是 | `approve` / `reject` |
|
||
| reason | string | reject 时必填 | 拒绝原因(回显给作者) |
|
||
|
||
```json
|
||
// 请求
|
||
{ "action": "approve" }
|
||
// 响应
|
||
{ "code": 0, "data": { "video_id": 88001, "status": 2, "status_text": "已发布" } }
|
||
```
|
||
|
||
### 11.5 下架视频 `POST /admin/videos/{video_id}/offline`【敏感】
|
||
|
||
```json
|
||
{ "reason": "内容违规" }
|
||
```
|
||
|
||
### 11.6 用户列表 `GET /admin/users`
|
||
|
||
查询参数:`keyword`(ID/手机号/邮箱)、`status`、`page`、`page_size`。
|
||
响应列表项:用户基础信息 + `points` + `is_member` + `video_count`。
|
||
|
||
### 11.7 用户详情 `GET /admin/users/{user_id}`
|
||
|
||
响应:用户信息 + 钱包 + 会员状态 + 近 10 条积分流水 + 作品数/获赞数。
|
||
|
||
### 11.8 封禁/解封用户 `PUT /admin/users/{user_id}/status`【敏感】
|
||
|
||
```json
|
||
{ "status": 2, "reason": "发布违规内容" }
|
||
```
|
||
|
||
`status`:1 正常 / 2 封禁。封禁后该用户 Token 立即失效(Redis 白名单剔除)。
|
||
|
||
### 11.9 积分调整 `POST /admin/points/adjust`【敏感】
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| user_id | int | 是 | 目标用户 |
|
||
| change_amount | int | 是 | 正=加,负=减 |
|
||
| reason | string | 是 | 调整原因 |
|
||
|
||
```json
|
||
// 响应
|
||
{ "code": 0, "data": { "user_id": 100023, "change_amount": 100, "balance_after": 486 } }
|
||
```
|
||
|
||
### 11.10 积分流水查询 `GET /admin/points/records`
|
||
|
||
查询参数:`user_id`、`biz_type`、`page`、`page_size`。响应结构同 App 端积分明细。
|
||
|
||
### 11.11 充值订单查询 `GET /admin/orders`
|
||
|
||
查询参数:`order_no`、`user_id`、`pay_method`、`status`、`start_date`、`end_date`、`page`。
|
||
响应列表项:订单全字段(含 usdt_amount / third_trade_no)。
|
||
|
||
### 11.12 人工补单 `POST /admin/orders/{order_no}/resettle`【敏感】
|
||
|
||
用于"用户已付款但回调未到账"的异常单。核实支付平台/链上确已收款后调用,走与回调相同的幂等入账流程。
|
||
|
||
```json
|
||
{ "reason": "微信回调丢失,商户后台已核实收款", "third_trade_no": "4200001234567890" }
|
||
```
|
||
|
||
### 11.13 充值套餐列表 `GET /admin/packages`
|
||
|
||
返回全部套餐(含下架),字段同 App 端 8.1 的 packages 项 + `status`、`sort`。
|
||
|
||
### 11.14 新增套餐 `POST /admin/packages`
|
||
|
||
```json
|
||
// 请求(points 由服务端按汇率计算,也可显式传入覆盖)
|
||
{ "amount_yuan": 50, "bonus_points": 20, "sort": 10 }
|
||
// 响应
|
||
{ "code": 0, "data": { "id": 5, "amount_yuan": 50, "points": 500, "bonus_points": 20, "sort": 10, "status": 1 } }
|
||
```
|
||
|
||
### 11.15 修改套餐 `PUT /admin/packages/{package_id}`
|
||
|
||
可改 `amount_yuan` / `bonus_points` / `sort` / `status`,实时生效。
|
||
|
||
### 11.16 删除套餐 `DELETE /admin/packages/{package_id}`
|
||
|
||
物理删除或下架(存在历史订单引用的套餐仅允许下架)。
|
||
|
||
### 11.17 赠送会员/积分 `POST /admin/gift`【敏感】
|
||
|
||
```json
|
||
// 请求:赠送体验会员
|
||
{ "user_ids": [100023, 100024], "gift_type": "membership", "plan_code": "trial", "reason": "国庆活动" }
|
||
// 请求:赠送积分
|
||
{ "user_ids": [100023], "gift_type": "points", "points": 100, "reason": "客服补偿" }
|
||
// 响应
|
||
{ "code": 0, "data": { "success": 2, "failed": 0 } }
|
||
```
|
||
|
||
赠送会员写入 membership_orders(source=2,points_cost=0);赠送积分写积分流水(biz_type=5)。
|
||
|
||
### 11.18 操作日志 `GET /admin/logs`
|
||
|
||
查询参数:`admin_id`、`action`、`page`。仅 super 可查。
|
||
|
||
### 11.19 提现列表 `GET /admin/withdrawals`
|
||
|
||
查询参数:`status`、`user_id`、`page`、`page_size`。
|
||
响应列表项:提现单全字段 + 用户昵称。
|
||
|
||
### 11.20 提现审核 `POST /admin/withdrawals/{withdraw_no}/review`【敏感】
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| action | string | 是 | `approve`(已完成线下打款,确认)/ `reject`(拒绝并退回资产) |
|
||
| reason | string | reject 时必填 | 拒绝原因 |
|
||
|
||
```json
|
||
// 请求
|
||
{ "action": "reject", "reason": "收款账号信息有误" }
|
||
// 响应
|
||
{ "code": 0, "data": { "withdraw_no": "W20261014153000001", "status": 2, "refunded_assets": 150.0 } }
|
||
```
|
||
|
||
### 11.21 推荐关系列表 `GET /admin/referrals`
|
||
|
||
查询参数:`inviter_id`、`status`、`risk_flag`、`page`、`page_size`。
|
||
响应列表项:推荐关系全字段 + 双方用户昵称。
|
||
|
||
### 11.22 推荐风控处理 `POST /admin/referrals/{referral_id}/review`【敏感】
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| action | string | 是 | `release`(解冻,恢复待激活流程)/ `invalid`(判无效,奖励不发放) |
|
||
| reason | string | 是 | 处理说明 |
|
||
|
||
```json
|
||
{ "action": "invalid", "reason": "同设备批量注册小号" }
|
||
```
|
||
|
||
### 11.23 平台配置列表 `GET /admin/configs`
|
||
|
||
返回 system_configs 全部键值。
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"list": [
|
||
{ "config_key": "register_gift_trial.enabled", "config_value": "1", "description": "注册赠送体验会员开关(1开/0关)", "updated_at": "2026-10-14 10:00:00" },
|
||
{ "config_key": "register_gift_trial.days", "config_value": "1", "description": "注册赠送体验会员天数", "updated_at": "2026-10-14 10:00:00" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 11.24 修改平台配置 `PUT /admin/configs/{config_key}`
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| value | string | 是 | 新配置值 |
|
||
|
||
```json
|
||
// 请求:关闭注册赠送体验会员
|
||
{ "value": "0" }
|
||
// 响应
|
||
{ "code": 0, "data": { "config_key": "register_gift_trial.enabled", "config_value": "0" } }
|
||
```
|
||
|
||
> 修改实时生效(服务端配置缓存 60s 自动失效),操作写入 admin_logs。
|
||
|
||
### 11.25 视频列表 `GET /admin/videos`
|
||
|
||
查询参数:`keyword`(ID/标题)、`status`、`author_id`、`page`、`page_size`。
|
||
响应列表项:视频全字段 + 作者昵称。
|
||
|
||
### 11.26 评论列表 `GET /admin/comments`
|
||
|
||
查询参数:`video_id`、`user_id`、`keyword`(评论内容)、`page`、`page_size`。
|
||
响应列表项:评论全字段 + 用户昵称 + 视频标题。
|
||
|
||
### 11.27 删除评论 `DELETE /admin/comments/{comment_id}`【敏感】
|
||
|
||
```json
|
||
{ "reason": "垃圾广告" }
|
||
```
|
||
|
||
删除后触发评论奖励回退(已计入进度回退、已发奖励扣回),与作者自删逻辑一致。
|
||
|
||
### 11.28 举报列表 `GET /admin/reports`
|
||
|
||
查询参数:`status`、`target_type`、`page`、`page_size`。
|
||
响应列表项:举报全字段 + 举报人昵称 + 被举报对象摘要(视频标题/评论内容)。
|
||
|
||
### 11.29 举报处理 `POST /admin/reports/{report_id}/review`【敏感】
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| action | string | 是 | `offline_video`(下架视频)/ `delete_comment`(删除评论)/ `reject`(驳回举报) |
|
||
| reason | string | 是 | 处理说明 |
|
||
|
||
```json
|
||
// 请求
|
||
{ "action": "offline_video", "reason": "核实违规,下架处理" }
|
||
// 响应
|
||
{ "code": 0, "data": { "report_id": 301, "status": 1, "status_text": "已处理" } }
|
||
```
|
||
|
||
处理结果通过站内通知(type=1)告知举报人;下架/删除动作复用对应业务流程(含作者通知、评论奖励回退)。
|
||
|
||
### 11.30 敏感词列表 `GET /admin/sensitive-words`
|
||
|
||
查询参数:`keyword`、`page`、`page_size`。
|
||
|
||
```json
|
||
{ "code": 0, "data": { "total": 120, "list": [ { "id": 1, "word": "违禁词", "created_at": "2026-10-14 10:00:00" } ] } }
|
||
```
|
||
|
||
### 11.31 添加敏感词 `POST /admin/sensitive-words`
|
||
|
||
```json
|
||
// 请求
|
||
{ "word": "新违禁词" }
|
||
// 响应
|
||
{ "code": 0, "data": { "id": 121, "word": "新违禁词" } }
|
||
```
|
||
|
||
重复添加返回错误码 1001;添加后 Redis 词库缓存(`words:sensitive`)失效重建,实时生效。
|
||
|
||
### 11.32 删除敏感词 `DELETE /admin/sensitive-words/{id}`
|
||
|
||
响应 `{ "code": 0 }`,同样触发词库缓存重建。
|
||
|
||
---
|
||
|
||
## 12. App 端关键调用时序
|
||
|
||
### 12.1 启动与域名发现
|
||
|
||
```
|
||
App 启动 → 解析 txt.256kb.top 的 DNS TXT 记录(DoH)
|
||
├─ 成功 → 以 TXT 内容作为 API Base URL(写入本地缓存)
|
||
└─ 失败/为空 → 计算 md5(yyyyMM) + "_jsnbhh.vip" 作为 Base URL
|
||
→ 进入首页拉取 Feed;缓存域名连续请求失败达阈值时重新执行发现流程
|
||
```
|
||
|
||
### 12.2 播放计费
|
||
|
||
```
|
||
App 滑入视频 → 本地查"今日已上报"集合
|
||
├─ 已上报 → 直接播放
|
||
└─ 未上报 → POST /videos/{id}/watch
|
||
├─ code=0 → 记录已上报;若 cost_type=1 弹 Toast"本次消耗 1 积分"
|
||
├─ code=2002 → 弹登录引导(游客)
|
||
└─ code=2001 → 弹"积分不足"(去充值 / 开通会员)
|
||
```
|
||
|
||
### 12.3 充值
|
||
|
||
```
|
||
选套餐+支付方式 → POST /payments/recharge → 按 pay_method:
|
||
支付宝/微信 → 调起 SDK → 返回 App → 轮询 GET /payments/orders/{order_no} → 成功刷新钱包
|
||
USDT → 展示金额/地址/二维码+倒计时 → 用户转账 → 轮询订单 → 到账刷新钱包
|
||
```
|
||
|
||
### 12.4 开通会员
|
||
|
||
```
|
||
GET /membership/plans → 选择套餐 → POST /membership/redeem
|
||
├─ code=0 → 刷新 /users/me 与会员状态
|
||
└─ code=2001 → 跳充值页(带回跳)
|
||
```
|