阅读主题
玩家注册、登录与手机绑定
本页对应 H5 SDK v0.4.0。客户端须升级包含 registerAccount()、bindPhone() 与可选 mountAuth() 的新安装包;仅更新服务器不会给旧安装包增加方法。v0.3.0 与更早的下载工件保持原有内容。
玩家先独立注册账号,再主动登录。注册成功不会返回平台会话,不会执行 PKCE 兑换,不会自动创建游戏角色。手机为可选绑定信息;没有手机也可以用账号和密码注册、登录。
账号、手机与游戏身份
| 项目 | 规则 |
|---|---|
| 用户名 | 3~32 位 ASCII 字母、数字、下划线,以字母开头;按小写归一化,不区分大小写 |
| 密码 | 10~128 位,至少包含一个英文字母和一个数字;确认密码必须一致 |
| 手机 | 当前接受中国大陆手机号;只有经过相应用途短信验证后才算已绑定 |
| 密码登录 | account 可以是用户名或这个账号已验证绑定的手机号,指向同一账号 |
| 游戏身份 | 同一账号、同一逻辑游戏的 gameUserId 保持一致;不同游戏有各自身份映射 |
| 冲突处理 | 已绑定其他账号的手机不能再绑定,不自动合并账号、资产或存档 |
已有手机账号和旧 test_ 联调账号保留原身份。不要按手机号在游戏数据库额外创建一份角色;游戏后端使用可信交换返回的 user.gameUserId 建立映射。
1. 读取实际能力
ts
const config = await sdk.init();
const auth = config.auth;
// registration: 'password' / 'testing_password' / 'unavailable'
// smsLogin / smsRegistration / phoneBinding 表示实际短信相关能力。
// 展示 registrationReason、passwordResetReason 等原因,不用假按钮模拟完成。账号注册受当前应用的注册开关、应用状态、维护状态与来源策略控制。正式环境已经可以执行纯用户名密码注册;真实短信供应商尚未接通,短信登录、注册时验证手机、登录后绑定手机、短信找回均不可用,发码返回 503 SMS_NOT_CONFIGURED。不要因为短信不可用而禁止纯账号密码注册。
本地受控联调来源只创建该游戏的限时测试身份,详见后文。待审核游戏可通过该联调通道测试;正式普通账号接入仍受应用审核规则控制。
2. 独立注册
协议先展示给玩家,由玩家主动确认。以下字段来自表单,不在代码或日志中保存密码。
ts
const requestId = crypto.randomUUID(); // 同一注册提交的网络重试复用
const created = await sdk.registerAccount({
username,
password,
confirmPassword,
consentVersion: '2026-09',
requestId,
});
// created: { account, username, userId, testing, expiresAt, replayed }
// 没有 token;不要把 created 作为 SessionResponse 保存。
showRegistrationSuccess(created.account);
showLoginForm({ account: created.account });成功首次响应为 HTTP 201,幂等重试为 200 且 replayed: true。同一请求标识对应的内容必须保持一致;用户修改了账号、密码或手机验证内容后,生成新 requestId。
注册成功后清空密码表单,只把返回的规范账号带回登录页。不要在注册回调中自动调用登录;等待玩家明确点击登录。
3. 用户名或已绑定手机登录
ts
const session = await sdk.login({
method: 'password',
account, // 用户名,或该账号已经验证绑定的手机号
password,
consentVersion: '2026-09',
});
// SDK 已完成 PKCE / state 检查并调用游戏后端 exchange。
// 游戏后端用 session.user.gameUserId 恢复角色及业务会话。用户名与手机号是同一账号的登录标识。切换标识登录不应迁移角色、生成另一个平台用户或合并账号。游戏原生登录/注册页面需由 SDK 入口接管,不能在旧表单外层再嵌套另一套账号卡片;挂载方式见账号 UI 与宿主职责。
验证码登录也只登录已经注册并绑定的账号:
ts
const challenge = await sdk.sendSms(phone, 'login');
const session = await sdk.login({
method: 'sms', account: phone,
challengeId: challenge.challengeId, code,
consentVersion: '2026-09',
});未注册手机号返回 401 ACCOUNT_NOT_REGISTERED,引导用户显式注册,不会首次短信登录自动创建账号。上述短信示例当前仅在短信能力可用的演示/联调环境执行;正式环境禁用该入口。
4. 注册时可选验证手机
只有 config.auth.smsRegistration 为真时才开放此流程。用户不填写手机时,不提交手机、挑战标识或验证码字段。
ts
const challenge = await sdk.sendSms(phone, 'register');
const created = await sdk.registerAccount({
username, password, confirmPassword,
consentVersion: '2026-09', requestId,
phone, challengeId: challenge.challengeId, code,
});phone、challengeId、code 必须三项齐全。验证码的用途为 register,并绑定发码时的 App ID;登录、找回密码或其他游戏取得的验证码不能代替。手机号已属于其他账号时返回 PHONE_ALREADY_BOUND,整个注册不会新建另一份身份。
5. 登录后绑定手机
玩家登录后,在账号安全页提供可选绑定入口,先检查 config.auth.phoneBinding。发码使用当前玩家会话,服务端同时校验 App ID 与用户身份。
ts
const challenge = await sdk.sendSms(phone, 'bind');
const result = await sdk.bindPhone({
phone, challengeId: challenge.challengeId, code,
currentPassword,
requestId: crypto.randomUUID(),
});
// result: { ok: true, user, replayed }
// 更新页面用户资料;原 userId、gameUserId、角色映射不变。
showBoundPhone(result.user.phone);必须同时验证当前账号密码和专用 bind 验证码。手机号被别人占用返回 409 PHONE_ALREADY_BOUND;已有手机号再换成另一个号码返回 409 PHONE_CHANGE_NOT_SUPPORTED,当前接口不是换绑或账号合并接口。绑定结果使用返回的 user 更新界面,不能假定本地缓存已经同步。
本地游戏注册限制
在开发者控制台的「接入配置 → 环境管理」启用本地联调并登记精确来源。注册调用仍使用 registerAccount();服务端根据真实来源和应用配置决定测试身份,不接受客户端自行声明正式或测试身份。
- 新账号只属于当前逻辑游戏,默认 24 小时有效,同游戏最多 10 个有效联调账号。
- 用户名在该游戏联调作用域内唯一;返回
testing: true和expiresAt。新账号不要求可见用户名带test_前缀,应以服务端身份类型判断。 - 不绑定真实手机,不获得平台币、礼包或支付权限,不计入代理注册业绩。
- 不改变游戏本身的数据隔离方式;测试角色应放在游戏的测试库或专用测试账号中。
- 开发者后台创建的一次性随机
test_账号仍可使用;这与玩家在 SDK 注册页自行设置测试用户名是两个入口。
测试到期、撤销或关闭联调后,需要清理失效会话。不得把登录成功等同于真实支付、短信或发行渠道已经验收。
HTTP 接口与错误处理
| 接口 | 鉴权及响应 |
|---|---|
POST /api/auth/register | 公开应用来源;输入上述注册字段及 App ID;只返回注册结果,不返回会话 |
POST /api/auth/login | 公开认证请求;完成后返回一次性授权码与 state,由 SDK 进行可信交换 |
POST /api/auth/sms/send | register 需要 App ID;bind 需要当前玩家 Bearer、App ID,挑战绑定当前用户 |
POST /api/account/phone/bind | 当前玩家 Bearer;验证密码、手机号和专用验证码后返回公开 user |
| 错误码 | 界面处理 |
|---|---|
VALIDATION_ERROR | 修正账号、密码确认、手机字段组合或协议版本 |
USERNAME_EXISTS | 提示登录已有账号或选择另一个用户名 |
ACCOUNT_NOT_REGISTERED | 引导显式注册,不能把短信登录当成注册 |
PHONE_ALREADY_BOUND | 不自动合并身份;让用户使用正确账号或进入人工核验 |
PHONE_CHANGE_NOT_SUPPORTED | 当前绑定接口不支持换绑 |
INVALID_SMS_CODE | 重新获取对应手机号、用途、App ID 和当前用户的验证码 |
SMS_NOT_CONFIGURED | 隐藏/禁用短信能力,保留纯账号密码注册与登录 |
APP_FEATURE_DISABLED | 刷新配置并显示该游戏尚未开放注册/登录等对应功能 |
TEST_PLAYER_PHONE_DISABLED | 联调账号不能绑定真实手机 |
IDEMPOTENCY_CONFLICT | 同一操作重试保留内容;新内容必须使用新请求标识 |
注册、绑定及登录都应显示处理中、成功或错误反馈,防止重复提交。日志只保留时间、接口、错误码和脱敏请求标识,不记录密码、验证码或会话令牌。