1. 通用约定
1.1 请求头
| Header | 说明 |
Authorization: Bearer <jwt> | 登录后必带;2h 过期,SDK 自动用 refreshToken 续签并重放失败请求 |
X-Ts / X-Nonce / X-Sign | 写接口必带:sign = HMAC(secret, method+path+body+ts+nonce);服务端校验 ts±300s、nonce 于 Redis 去重(防重放) |
X-Cver | 客户端 SDK 版本,灰度与排查用 |
1.2 响应包与错误码
{ "code": 0, "msg": "ok", "data": { ... } } // code!=0 时 data 可空
| code | 含义 | 客户端处理 |
| 0 | 成功 | — |
| 1001 | 参数错误 | 视为 bug 上报 |
| 1401 | token 失效 | SDK 静默刷新/重登后重放 |
| 1403 | 签名/重放校验失败 | 拒绝并埋点(风控信号) |
| 1409 | 存档版本冲突 | data 附服务端最新档,SDK 走冲突策略(04) |
| 1429 | 限频 | 退避重试;领奖类直接提示"今日次数已满" |
| 2001 | 余额/体力不足 | 弹 showUnlockChoice 双通道(05) |
| 2002 | 奖励已领取(幂等拒绝) | 静默刷新状态 |
| 3001 | 订单状态非法 | 轮询 GET /orders 以服务端为准 |
| 4001 | 内容安全不通过 | 提示修改昵称/文本 |
2. 登录时序(code2session)
游戏(分包) game-sdk.js API 服务端 微信/抖音
│ GameSDK.init() │ │ │
│────────────────────▶│ wx.login()/tt.login │ │
│ │──── code ──────────▶│ POST /auth/login │
│ │ │── jscode2session ───▶│
│ │ │◀─ openid/unionid ────│
│ │ │ upsert identities → users
│ │ │ 签发 JWT + refresh │
│ │◀─ token,user,wallet,│ │
│ │ hubSave,isNew ────│ │
│◀── ready(用户/钱包/大厅档) ──│ │ │
| 端点 | 入参 | 出参 | 备注 |
POST /auth/login | platform, appid, code | token, refreshToken, user, wallet, isNew | 静默登录,无需用户授权;isNew 触发新手礼 |
POST /auth/refresh | refreshToken | token | — |
3. 业务端点清单
3.1 用户与配置
| 端点 | 说明 |
GET /me | 用户资料 + 钱包 + streak + 未领任务红点计数(大厅一屏所需聚合) |
PUT /me | 昵称/头像(服务端过 secCheck,4001 拒绝) |
GET /games | 游戏库:status=online 列表 + 每款 config + updated_at(客户端按 updated_at 缓存) |
GET /configs | app_configs 公开子集:公告、分享限额、活动开关、首充弹窗开关 |
3.2 云存档
| 端点 | 入参 → 出参 | 规则 |
GET /saves/{gameId} | slot → {data, version, updatedAt} | 无档返回 version=0 |
PUT /saves/{gameId} | {slot, data, version} → {version+1} | 乐观锁:版本不匹配返回 1409+服务端档;data ≤64KB;写入限频 1 次/10s/游戏(SDK 侧节流合并) |
3.3 钱包 / 体力(服务端权威记账)
| 端点 | 说明 |
GET /wallet | coin/gem/energy(体力按恢复速率惰性补算后返回) |
POST /wallet/consume | {currency, amount, reason, gameId} 消耗(买道具/抽卡/复活);余额不足 2001;写 currency_txns |
POST /energy/spend | 开局扣体力,返回 sessionToken(本局凭证,提交分数时必带——体力闸门与防作弊共用一个凭证) |
POST /energy/refill | {channel: ad | share | pay | item} 按渠道限额恢复(限额配置见 05) |
3.4 排行榜
| 端点 | 说明 |
POST /lb/{gameId}/score | {score, extra, sessionToken}。服务端校验链见 §5;仅保留历史最高分(或按游戏 config 取"本季最高") |
GET /lb/{gameId}?scope=global|province&season=current | top50 + 我的排名(Redis ZSET)。留意 微信好友榜不走本 API——好友关系只能在开放数据域(子域 canvas)内渲染,服务端只提供全服/省榜;抖音同理用平台榜单能力 |
3.5 分享(回流发奖,详见 05)
| 端点 | 说明 |
POST /share | {gameId, scene} → {shareId, copywritingId}:创建 share_records,返回文案模板序号(求助/挑衅 A/B 由服务端配置) |
POST /share/visit | 访客侧上报 {shareId}(从分享卡 query 取得):判重(同好友当日一次)、判新用户、给分享者入账待领奖励,给访客发欢迎奖励 |
GET /share/{shareId} | 分享者轮询:回流人数/是否达成/可领奖励——用于"喊好友帮忙"弹窗的实时反馈 |
3.6 广告奖励
| 端点 | 说明 |
POST /ad/event | {gameId, scene, status: show|complete|abort} 漏斗埋点 |
POST /ad/reward | {gameId, scene} 完播后领奖。留意 小游戏激励视频无服务端回调,凭据只有客户端 onClose(ended)——因此该接口必须叠加:签名 + 每场景每日限额 + 与 ad_events(show→complete) 时序一致性校验 + 风控降权,把伪造收益压到不值得 |
3.7 签到 / 任务 / 埋点
| 端点 | 说明 |
POST /signin | 今日签到:算 streak(昨日未签且无冻结则清零)、按阶梯发奖,幂等(signins PK) |
POST /signin/fix | {channel: ad|pay|item} 补签(消耗断签保护);每周限 1 次广告补签 |
GET /tasks / POST /tasks/{id}/claim | 任务列表(含进度)/ 领奖(幂等) |
POST /events | 批量埋点上报(≤50 条/次);服务端异步驱动 task_progress 与 stats 聚合 |
3.8 支付(M8)
客户端 API 服务端 平台支付
│ POST /pay/order {productId} │ │
│─────────────────────────────▶│ 校验限购→建 orders(created) │
│◀── {orderId, payParams} ─────│ │
│ 调起支付 midas / tt.pay ──────────────────────────────────▶│
│ │◀──── 支付回调(平台签名) ─────│
│ │ 验签→paid→[事务:发货+流水]→delivered→应答
│ GET /orders/{orderId}(轮询/onShow 触发) │
│─────────────────────────────▶│ status=delivered + 最新钱包 │
| 端点 | 说明 |
POST /pay/order | 建单:校验商品上下架/限购(首充一次)/平台可用性(iOS 政策),返回调起支付所需参数 |
POST /callback/wxpay · POST /callback/ttpay | 平台回调:验签失败直接 4xx;重复回调按订单状态机幂等应答;发货全程单事务。红线 本路由不鉴 JWT、只鉴平台签名,且必须与业务路由隔离限频 |
GET /orders/{orderId} / GET /orders | 单笔状态 / 我的订单列表(客服口径) |
3.9 管理端(/admin/v1,模块详见 07)
独立 JWT 与密钥、RBAC 中间件、全写操作落 audit_logs。核心资源:/admin/v1/users · /saves · /orders · /games · /products · /configs · /lb · /stats。
4. 限频总表(Redis 用户级)
| 接口 | 限额 | 超限行为 |
| PUT /saves | 1 次/10s/游戏 | 1429,SDK 本地合并后重试 |
| POST /lb/score | 10 次/小时/游戏 | 1429 |
| POST /ad/reward | 按场景配置(默认 10 次/日/场景) | 2002 话术"今日已达上限" |
| POST /share/visit(同一访客) | 1 次/shareId;3 个不同 shareId/日 | 静默不发奖 |
| POST /signin/fix(ad) | 1 次/周 | 引导付费补签 |
| POST /events | 60 次/分钟 | 丢弃并计数 |
5. 防作弊校验链(提交分数为例)
- 凭证:必须携带开局
POST /energy/spend 签发的 sessionToken(一次性,Redis 存开局时间)。
- 时长:now - 开局时间 ≥
games.config.sessionMinSec(秒杀"瞬间高分"脚本)。
- 上限:score ≤
games.config.scoreMax;超限拒绝并 risk_level+1。
- 速率:分数增幅相对该用户历史分布突变(>P99.9)→ 收下分数但标记 risk,榜单延迟展示待复核(07 后台队列)。
- 签名与重放:X-Sign + nonce 去重。
- 降权:risk_level=2 用户:奖励减半、榜单匿名、进入后台复核列表——不封禁(避免误伤),先隔离影响。
设计底线:单机小游戏防作弊做不到绝对(代码在客户端),目标是让作弊拿不到经济收益、上不了榜:钱包只认服务端记账(作弊改不了钱),榜单有校验链(作弊上不了榜),广告奖励有限额(伪造刷不多)。