阅读主题
身份、角色与会话
游戏业务应围绕经过服务器兑换确认的 user.gameUserId 建立映射。登录成功不代表客户端上报的任意角色都可信,也不自动迁移实际游戏的存档。
| 字段 | 当前含义 | 接入处理 |
|---|---|---|
user.id | 本地平台账号 ID | 不用作跨厂商公开玩家标识 |
user.gameUserId | 平台账号与逻辑游戏组合出的游戏身份 | 映射到该游戏自身账号 |
role.id | 本地为演示角色;正式为 unbound_* 兼容投影 | 正式不代表真实角色或存档,使用 /api/roles 的 bindingId 选择目标 |
token | 平台玩家 Bearer 令牌 | 调用当前玩家 API,不是游戏服务器密钥 |
expiresAt | 当前会话到期时间 | 当前签发 12 小时会话,失效后重新登录 |
同一逻辑游戏的 H5/Android/iOS/Windows App ID 返回相同 gameUserId;另一逻辑游戏的身份不同。演示模式有内置角色及共享钱包权益,正式模式没有自动生成的游戏角色,钱包收付关闭。开发者订单查询隔离不等于完整商户独立钱包或结算已完成。
验证当前玩家
在服务器或 SDK 请求中携带玩家令牌:
ts
const response = await fetch(`${accountOrigin}/api/me`, {
headers: { Authorization: `Bearer ${playerToken}` },
signal: AbortSignal.timeout(15000),
});
if (!response.ok) throw new Error(`会话验证失败:${response.status}`);
const { user, role } = await response.json();
// 接下来在你自己的数据库中查找 user.gameUserId 对应的游戏账号。/api/me 返回 {user,role},没有 data 包装,也不会刷新 expiresAt 或返回新 token。当前 User 结构确实包含 phone 与平台 id,不是脱敏 DTO;只按业务需要使用,避免在游戏日志、URL 或分析事件里记录整份响应。返回字段见 API 总览。
会话失效处理
玩家主动退出或远程撤销设备会话后,原 token 立即失效。修改玩家密码保留当前会话并撤销其他会话;短信重置密码撤销全部玩家会话。平台封禁玩家、停用游戏或开发者会撤销相关会话。开发者扩端会使整款应用回到待审批并撤销旧游戏会话,复审后需重新登录。
H5 可以显式注入 sessionStorage,通过 restoreSession() 先请求 /api/me 再恢复界面。存储中的资料在验证完成前不应显示为已登录。401 时清理凭据;网络中断时允许重试验证,不能把未验证缓存视为有效玩家。详细错误见 错误处理。
外部角色接入验收
在你的游戏服务器完成 gameUserId → 游戏账号 → 区服/角色 映射,并针对每次进入角色、下单和发货校验所属账号。已提供 POST /api/server/realms 和 POST /api/server/roles/bind,由游戏密钥与玩家会话双重校验绑定;客户端用 /api/roles 获取本人可信角色。正式会话的 unbound_* 投影不落角色表。存档同步仍由接入方实现,不存在 /roles/sync 接口。
用同一个平台账号登录同游戏两个端,验证映射一致;再用另一游戏和另一账号验证不能读取原角色订单。关闭旧设备后请求 /api/me 应失败,外部游戏会话也须按你自己的会话策略失效。平台不会自动控制未接入撤销协议的外部游戏会话。
实现依据
packages/server/src/platform.ts 的 user()、role()、newSession()、verifyRole();packages/server/src/app.ts 的 player()、GET /api/me;packages/sdk/src/index.ts 的 restoreSession()。角色绑定记录由平台持久化;真实角色资产与存档保存在游戏服务器,不在平台自动生成。