Skip to content

9 Action 完整字段表 ​

1.1 captcha —— 图形验证码 ​

前置条件:无 频率限制:同 IP 60s 内 30 次(超出 40101005)

请求:

json
{ "action": "captcha", "payload": {} }

(payload 必须为空对象,多传字段 400)

响应 data:

字段类型说明
captchaIdstring (UUID)凭据,120s 有效,一次性
pngstring真 PNG dataURL(data:image/png;base64,…,V2.0.43+)。前端唯一正解:原生 <image :src="png">
svgstringSVG 源码(含抗指纹扰动)。仅回退/桌面端用途

前端要点:

  • 一次消费即失效(成败皆消费);任何失败分支后重新拉取
  • 不做本地缓存复用;换网后直接刷新
  • ⚠️ 渲染三定律(2026-09-17 真机三层实测,勿再踩):
    1. uni_modules/svg-icon APP 端 renderjs 对动态返回的 svg/dataURL 均渲染失败(空白无报错)— 勿用 svg-icon 承载验证码
    2. Android 原生 image 不渲染 data:image/svg+xml dataURL(V2.0.42 及之前 png 字段名不副实,实为 svg dataURL → 页面空白)
    3. 唯一正解:原生 <image> + png 字段 + 后端 ≥ V2.0.43(真 PNG),三条件缺一不可
  • 前端自查清单:res.data.png 前缀应为 data:image/png;base64,(若是 data:image/svg+xml → 后端版本 < V2.0.43,先升后端)

1.2 sms-send —— 发送短信验证码 ​

前置条件:先成功获取 captcha调用时机:登录页 / 绑定手机页点「获取验证码」

请求 payload:

字段类型必填约束说明
phonestring✅^1[3-9]\d{9}$11 位大陆手机号
captchaIdstring✅8~64 字符1.1 返回的凭据
captchaCodestring✅1~8 字符用户输入(不区分大小写比对)
clientIdstring⬜^[A-Za-z0-9_-]{1,32}$短信码按 (phone, clientId) 隔离存储

响应 data:{ "ok": true }

处理顺序(服务端硬编码,联调排错按此序定位): 图形码校验 → IP 30/min → 手机号 60s/1 → 手机号 24h/10 → 生成 4 位码(10min TTL)→ 腾讯云下发。

⚠️ 验证码只认真实下发:生产环境没有任何固定码 / 万能码绕过,必须走完图形码 + 真实短信才能登录。 联调环境是否开启「固定码」捷径由运维配置(属内部信息)—— 需要时找运维要码,不要假设某个值可用。

错误分支(全量):

层HTTPcode场景前端处置
Zod400—字段缺失/格式错(msg 定位字段)开发期修复
图形码20040101003验证码错误提示 + 重新拉 captcha
图形码20040101004>120s 过期静默刷新 captcha
限流20040101005三层任一(msg 区分:IP/间隔/日上限)按 msg 提示,倒计时保持禁用
下发20040101006短信通道故障 / SMS 凭据未配置期提示稍后再试 + 重新拉 captcha

前端要点:

  • ⚠️ 图形码无论成败即消费 —— 任何失败分支重试前必须重新 captcha
  • 成功即启动 60s 倒计时(服务端 60s/1 条硬限);短信码 4 位、10min 有效、累计错 3 次即作废

1.3 sms-verify —— 预验证短信码(可选) ​

语义:校验短信码是否正确,consume=false 不消费——同一短信码可多次调用(分步表单:第 1 步验码 ✅ → 用户回填其他字段 → 第 2 步真正提交)。 调用时机:绑定手机页等分步场景的「下一步」前置校验;普通登录页跳过。

请求 payload:

字段类型必填约束
phonestring✅^1[3-9]\d{9}$
smsCodestring✅^\d{4}$(严格 4 位数字)
clientIdstring⬜同 1.2(必须与发码/最终提交用同一 clientId)

响应 data:{ "ok": true }

错误分支:

code场景处置
40101001码不存在 / 已过期(10min)/ 已被 3 次错误作废提示重新发码,回 1.2
40101003码错误(msg=「短信验证码错误」)——会累计尝试次数,第 3 次错码作废提示错误;接近 3 次时建议引导重发

前端要点:错误尝试计数跨 sms-verify 与 sms-login 共享(同一个 Redis 计数器)—— 分步场景预验证输错 2 次后,最终提交只剩 1 次机会。


1.4 sms-login —— 手机号验证码登录 ​

前置条件:sms-send 成功 调用时机:登录页点「登录/注册」(新用户自动注册,本接口即 OAuth 主注册通道)

请求 payload:

字段类型必填约束说明
phonestring✅^1[3-9]\d{9}$
smsCodestring✅^\d{4}$
clientIdstring⬜≤32 白名单会话身份
agreementAcceptedliteral true✅只接受 JSON true协议凭证;传 "true"/1 都报 40101008。前端应在未勾选时禁用按钮
nicknamestring⬜1~30 字符仅注册时生效(如「用户8000」),老用户忽略
deviceInfoobject⬜见下consent 留痕 + 设备元数据

deviceInfo 子字段(全可选):platform(enum ios/android/mini/h5,App 传 "android")、deviceModel(≤64)、deviceFingerprint(≤128)。

响应 data(新老用户统一结构):

json
{
  "tokens": { "access": "<JWT·2h>", "refresh": "<JWT·30d>" },
  "expiresAt": { "access": "2026-09-11T12:00:00.000Z", "refresh": "2026-10-11T..." },
  "user": { /* 全字段见 1.4.1 */ },
  "token_expiring": false
}

1.4.1 user 全字段表(toOAuthUserOutput 真源,共 10 字段) ​

字段类型说明 / 前端用途
idstring (cuid)用户主键,业务 API 的 userId
nicknamestring注册时可传 nickname,否则系统生成
avatarUrlstring | null头像(微信渠道有值;手机号注册为 null)
phonestring | null脱敏(138****8000);仅展示,不可当真值回传
memberLevelnumber会员等级(0=免费),控制会员 UI
onboardingDoneboolean路由分流:false → Onboarding 向导;true → 主页。⚠️ V2 实况(先跑通阶段):sms-login 暂以 isNewUser 替代「注册当次」分流,落库阶段接回本字段真分流
isNewUserbooleanV2 扩展:注册当次 true(仅 sms-login 响应携带;后续登录/rotate 均 false/不携带)→ 前端弹「完善基础资料」弹窗(向导 step1)
profileCompleteLvnumber资料补充等级(1/2/2+),驱动 ProfileLevelCard
profileCompletionPctnumber资料完成度 0~100
hasWechatMobileboolean是否绑定微信(App 渠道)—— 控制「绑定/解绑微信」入口显隐
hasWechatMiniboolean是否绑定微信(小程序渠道)

未返回字段(openid/unionid/openidMobile/openidMini)为服务端内部标识,前端永远拿不到也不需要。

⚠️ V2 实现实况(2026-09-17):sms-login 当前仅返回 id / nickname / phone / isNewUser(V2 两阶段迁移中;上表 avatarUrl / memberLevel / onboardingDone / profileComplete* / hasWechat* 随 user 模块落库阶段补齐 — 参见 user 模块 updateBasicProfile)。

错误分支(全量,按服务端检查顺序):

层HTTPcode场景处置
Zod400—含 agreementAccepted 非 literal true前端禁按钮预防
consent20040101008协议未同意提示勾选
短信码20040101001码不存在/过期/已被 3 次错作废提示重发(回 1.2)
短信码20040101003码错误(msg=「短信验证码错误」)提示错误 + 显示剩余尝试提示(3 次错作废)
封禁403—账号被封禁提示联系客服

注意:短信码「错」与「不存在」是两个不同 code(40101003 vs 40101001),UI 文案应区分(错 → 可继续试;不存在 → 必须重发)。


1.5 callback —— 微信登录回调 ​

前置条件:微信 OpenSDK 授权成功拿到 code(一次性,5min) 调用时机:登录页点微信按钮 → SDK 回调

请求 payload:

字段类型必填约束说明
codestring✅1~128微信授权码
sourcestring✅"app" | "mini"App 端固定 "app"(开放平台移动应用凭据)
clientIdstring⬜≤32 白名单
agreementAcceptedliteral true✅同 1.4
nickname / avatarUrlstring⬜≤30 / URL ≤512微信侧未返回时前端补传
deviceInfoobject⬜同 1.4

响应 data:与 1.4 完全一致(buildAuthResponse 统一结构)。

unionid 合并(前端无感):同微信 unionid 的 app/mini 双渠道自动合并同一账号 —— 用户先在 App 微信登录、后在小程序微信登录,是同一个账号。

错误分支:

code场景处置
40101010微信接口失败 / 凭据未配置提示「微信登录暂不可用」,手机号登录兜底
40101007绑定失败(code 无效/已用)提示重试(重新走 SDK 授权)
40101008协议未同意同 1.4

1.6 rotate —— 刷新 token(全局拦截器核心) ​

鉴权:Authorization: Bearer <refresh_token>(不是 access) 调用时机:① 任何业务请求 401;② token_expiring=true(access 剩余 <30min)主动续期

请求:{ "action": "rotate", "payload": {} }

服务端验证链:RS256 验签 → 按 cid claim 反查 DeviceBinding(oauth:{cid})→ 校验 status=active → 库内密文解出与传入 token 双向比对 → 用户存在且未封禁 → 签发新双 token 并覆盖库内密文(旧 refresh 自然作废)。

响应 data:与 1.4 的 tokens/expiresAt 同构 + user + token_expiring。

错误分支:

code场景处置
40101011验签失败 / binding 非 active / 密文缺失 / 用户不存在清空本地会话 → 登录页,禁止重试
40101012签名合法但与库内不匹配 = 旧 refresh 二次使用⚠️ 服务端已连坐吊销该设备会话,前端唯一动作:清会话进登录页

1.7 logout —— 登出 ​

鉴权:Authorization: Bearer <access_token>

请求 payload:

字段类型必填约束说明
scopestring⬜enum device(默认)| all
clientIdstring⬜≤32 白名单scope=device 时必传(见下方语义)

响应 data:{ "ok": true, "scope": "all", "revoked": 3 }(revoked = 吊销会话数)

scope 语义(精确):

scope服务端动作连坐范围
device吊销 oauth:{clientId ?? 'default'} 这一个会话⚠️ 不传 clientId 时吊销的是 oauth:default —— 如果多设备都用缺省值,会一起被登出。传 clientId 才是「只登本设备」
all吊销该用户全部 oauth:* 会话所有设备的 OAuth 会话全下线;不影响设备厂商绑定(garmin:/honor: 等非 oauth: vendor)

前端要点:无论成败(含 401),本地一律清空 token 进登录页(登出语义本地优先)。


1.8 bind-phone / unbind —— 绑定 / 解绑手机号与微信 ​

bind-phone(Bearer access) ​

微信登录用户补手机号。payload = phone(^1[3-9]\d{9}$)+ smsCode(^\d{4}$)+ clientId(可选)。先走 1.2 发码。 响应:{ "ok": true, "token_expiring": false }

code场景处置
40101001短信码不存在/过期重发
40101003短信码错误(3 次错作废规则同)提示
Zod 400phone/smsCode 格式错修正表单

unbind(Bearer access) ​

请求 payload:

字段类型必填说明
targetstring⬜enum "mobile" | "mini";缺省 = mobile+mini 两者全解(⚠️ 不是「按当前账号判断」)

硬约束:解绑后必须仍保留至少一种登录方式(手机号或任一微信渠道),否则 40101007。 响应:{ "ok": true, "token_expiring": false }


1.9 mySessions —— 登录设备/会话列表(V2.0.40+) ​

前置条件:Authorization: Bearer <access_token>频率限制:无特殊限制

请求:

json
{ "action": "mySessions", "payload": {} }

响应 data(⚠️ 实测结构:sessions 包一层数组):

json
{
  "sessions": [
    {
      "clientId": "android:550e8400-e29b-41d4-a716-446655440000",
      "deviceName": "Xiaomi 23049RAD8C",
      "lastActiveAt": "2026-09-17T00:23:48.586222",
      "expiresAt": "2026-12-16T00:23:48.586222",
      "current": true
    }
  ]
}
字段类型说明
clientIdstring会话标识(复合格式 类型:设备UUID;存量旧格式无 : 为类型级共享)
deviceNamestring|null登录时 deviceName 传入的会话展示名(旧会话可能为 null)
lastActiveAtstring (ISO)最近活跃时间(rotate 或登录时间)
expiresAtstring|null设备信任 90 天滑动窗口到期
currentboolean当前设备标记(字段名是 current,不是 isCurrent)

前端要点:

  • 设备上限 10 台(LRU 自动淘汰最旧,当前设备豁免)— UI 建议展示该上限提示
  • 列表按 lastActiveAt 降序返回
  • current=true 的设备不可(也不应)对自己 revokeSession

1.10 revokeSession —— 踢下线指定会话(V2.0.40+) ​

前置条件:Authorization: Bearer <access_token>(⚠️ 是 access,不是 refresh)

请求:

json
{ "action": "revokeSession", "payload": { "target": "android:550e8400-..." } }
字段类型必填说明
targetstring✅目标会话的 clientId(权威键;clientId 为兼容旧键,二选一)

响应 data:{ "revoked": "android:550e8400-..." }

错误分支:

codeHTTP场景
40001001400payload 缺 target(V2.0.41 及之前会误返 40201007 兜底)
40101015401目标会话不存在或已下线(业务性 401 — 前端 toast 即止,勿触发 rotate/登出逻辑)

前端要点:

  • 被踢设备下次任意请求 → 其 refresh 已 revoke → 40101011/40101012 → 强登出
  • 操作者自身会话不受影响(设备级隔离)
  • UI 必须二次确认(踢下线是不可逆动作,对端需重新完整登录)

前端要点:hasWechatMobile + hasWechatMini + phone 三个字段决定解绑入口显隐与 target 传法 —— 只绑了一个渠道时解绑它会被拒(40101007),UI 应提前禁用并解释。