Files
video/docs/03-接口文档.md
T
2026-10-15 20:36:59 +08:00

47 KiB
Raw Blame History

短视频应用接口文档

  • 版本: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 统一响应结构

{
  "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

请求示例

{ "phone": "13800138000", "scene": "register" }

响应示例

{ "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)

请求示例

{ "type": "phone", "phone": "13800138000", "code": "825314", "password": "abc12345", "nickname": "小明" }

响应示例

{
  "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 验证码方式必填

请求示例

{ "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 位,须含字母和数字

请求示例

{ "type": "phone", "phone": "13800138000", "code": "825314", "new_password": "newabc123" }

响应:{ "code": 0, "message": "密码已重置,请重新登录" }

错误码:1004 验证码错误或已过期;1001 账号不存在。


4. 用户模块

4.1 获取个人信息 GET /users/me(需登录)

响应示例

{
  "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(需登录)

响应示例

{
  "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扣回)

响应示例

{
  "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 是 当前登录密码(二次确认)
// 响应
{ "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}(游客可)

{
  "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

响应示例

{
  "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 否 当前播放进度(秒),服务端记录用于续播

响应示例(扣费场景)

{
  "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

错误响应(游客超限)

{ "code": 2002, "message": "今日免费观看次数已用完,登录后继续观看", "data": { "need_login": true } }

错误响应(积分不足)

{ "code": 2001, "message": "积分不足,请充值或开通会员", "data": { "points": 0 } }

5.4 完整观看上报 POST /videos/{video_id}/watch/complete(游客可)

播放进度 ≥95% 或自然播完时调用,用于创作者收益计数(每 1000 次完整观看 = 1 资产)。服务端校验 watch_duration 合理性(不得明显低于视频时长),同一用户/设备同一视频每日仅首次有效。

请求参数

参数 类型 必填 说明
watch_duration int 是 本次实际观看时长(秒)
// 请求
{ "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包)

响应示例

{
  "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] 否 标签,05 个,每个 120 字

请求示例

{ "object_key": "upload/tmp/20261014/uuid.mp4", "title": "海边日落", "description": "拍摄于青岛", "category_id": 3, "tags": ["日落", "海边"] }

响应示例

{
  "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

{ "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)

响应示例

{
  "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(游客可)

{ "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] 标签,05 个,每个 120 字

响应:{ "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,切换式接口(已点赞则取消)。

响应示例

{ "code": 0, "data": { "is_liked": true, "like_count": 457 } }

6.2 收藏/取消 POST /videos/{video_id}/favorite(需登录)

{ "code": 0, "data": { "is_favorited": true, "favorite_count": 91 } }

6.3 评论列表 GET /videos/{video_id}/comments(游客可)

查询参数:page、page_size、parent_id(查二级回复时传父评论 ID)

响应示例

{
  "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

请求示例

{ "content": "这个日落太美了,求定位!" }

响应示例

{
  "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(游客可)

响应示例(价格来自服务端配置,前端不硬编码)

{
  "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(需登录)

{
  "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

请求示例

{ "plan_code": "monthly" }

响应示例

{
  "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(需登录)

{
  "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

请求示例

{ "amount_yuan": 30, "pay_method": 1 }

响应示例(支付宝)

{
  "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)

{
  "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 次。

响应示例

{
  "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(需登录)

响应示例

{
  "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 是 推荐人邀请码
// 请求
{ "invite_code": "K7X2M9" }
// 响应
{ "code": 0, "data": { "bound": true, "status": 0, "status_text": "待激活" } }

错误码:2101(邀请码无效 / 已绑定过 / 绑定自己 / 同设备已注册其他账号)

被推荐人激活(72h 内累计观看 ≥3 个视频且次日有登录)后,推荐人获得 10 积分(可配置,不限量)。被推荐人此后每次充值成功,推荐人获得"充值积分 × 5%"的资产(不限量)。

9.3 资产钱包 GET /assets/me(需登录)

响应示例

{
  "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后台调整)

响应示例

{
  "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 地址)
// 请求
{ "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(需登录)

响应示例

{
  "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 位,自动转大写)
// 请求
{ "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 一致)
// 请求
{ "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 版本号

响应示例

{
  "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

响应示例

{
  "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(需登录)

{ "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 字
// 请求
{ "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

// 请求
{ "username": "admin", "password": "xxxx" }
// 响应
{ "code": 0, "data": { "admin_token": "eyJ...", "expires_in": 43200, "admin": { "id": 1, "name": "超管", "role": "super" } } }

11.2 仪表盘 GET /admin/dashboard

{
  "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 时必填 拒绝原因(回显给作者)
// 请求
{ "action": "approve" }
// 响应
{ "code": 0, "data": { "video_id": 88001, "status": 2, "status_text": "已发布" } }

11.5 下架视频 POST /admin/videos/{video_id}/offline【敏感】

{ "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【敏感】

{ "status": 2, "reason": "发布违规内容" }

status:1 正常 / 2 封禁。封禁后该用户 Token 立即失效(Redis 白名单剔除)。

11.9 积分调整 POST /admin/points/adjust【敏感】

参数 类型 必填 说明
user_id int 是 目标用户
change_amount int 是 正=加,负=减
reason string 是 调整原因
// 响应
{ "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【敏感】

用于"用户已付款但回调未到账"的异常单。核实支付平台/链上确已收款后调用,走与回调相同的幂等入账流程。

{ "reason": "微信回调丢失,商户后台已核实收款", "third_trade_no": "4200001234567890" }

11.13 充值套餐列表 GET /admin/packages

返回全部套餐(含下架),字段同 App 端 8.1 的 packages 项 + status、sort。

11.14 新增套餐 POST /admin/packages

// 请求(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【敏感】

// 请求:赠送体验会员
{ "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 时必填 拒绝原因
// 请求
{ "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 是 处理说明
{ "action": "invalid", "reason": "同设备批量注册小号" }

11.23 平台配置列表 GET /admin/configs

返回 system_configs 全部键值。

{
  "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 是 新配置值
// 请求:关闭注册赠送体验会员
{ "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}【敏感】

{ "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 是 处理说明
// 请求
{ "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。

{ "code": 0, "data": { "total": 120, "list": [ { "id": 1, "word": "违禁词", "created_at": "2026-10-14 10:00:00" } ] } }

11.31 添加敏感词 POST /admin/sensitive-words

// 请求
{ "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 → 跳充值页(带回跳)