在线状态订阅与推送令牌
订阅关注用户的在线状态变化(上线/离线/被踢/注销),以及登记、查询、注销设备推送令牌。令牌只是台账,厂商通道投递能力请见推送专题。
进程模型:main(客户端 + 本地库,单写者)/ preload(contextBridge 具名方法)/ renderer(薄代理)。renderer 不直连网络与数据库。
接口一览
| 操作 | 语义 | 传输 | 返回 |
|---|---|---|---|
subscribePresence | 订阅用户在线状态(IDL rev20;客户端 REST `POST /api/apps/{appkey}/users/{userId}/presence/subscriptions`,userId 取自当前登录用户)。被订阅用户上线/离线/被踢/注销时通过长连接收到 `presence_changed`。订阅自己 1001;目标用户不存在/属于其它 app 1004;订阅总数上限 500(超限 1001);幂等(重复订阅不重复入列)。成功返回变更后的完整订阅列表 `{subscribed:[...]}`。好友关系本身已默认订阅对方在线状态,无需额外调用。 | REST(客户端) | {subscribed:string[]} |
unsubscribePresence | 取消订阅用户在线状态(IDL rev20;客户端 REST `POST .../presence/subscriptions` 的 `unsubscribe` 分支)。取消未订阅的用户幂等成功(不报错);订阅自己 1001;目标用户不存在 1004。成功返回变更后的完整订阅列表 `{subscribed:[...]}`。仅停止接收该用户的实时在线状态帧,好友关系不受影响。 | REST(客户端) | {subscribed:string[]} |
getPresenceSubscriptions | 查询当前用户的在线状态订阅列表(IDL rev20;客户端 REST `GET /api/apps/{appkey}/users/{userId}/presence/subscriptions`)→ `{userId,subscribed:[...]}`。只读、幂等、不产生事件。 | REST(客户端) | {userId:string, subscribed:string[]} |
registerPushToken | 注册设备推送 token(IDL rev21 C23 收口;客户端 REST `POST /api/apps/{appkey}/push/tokens`,服务端 rev20 已实现,本 op 补 SDK 语义面)→ PushToken。幂等键 `(userId, platform, token)`:重复注册返回既有 tokenId 并重新置 active=true;`token` 8..=512 字符、`platform` ∈ ios|android|web|huawei|xiaomi|oppo|vivo|fcm、未知平台/长度非法 1001、每用户 20 个活跃 token 上限(超限 1001)、注销/封禁用户 1016;同一 (platform, token) 被其它用户注册时旧记录置 active=false(设备换绑)。 | REST(客户端) | PushToken |
unregisterPushToken | 注销本人设备推送 token(IDL rev21 C23;客户端 REST `DELETE /api/apps/{appkey}/push/tokens/{tokenId}`):软删除 active=false 并保留历史供审计 → `{tokenId,userId,platform,deleted,active:false,alreadyInactive}`。非本人或不存在 1001(不泄露他人 token);重复注销幂等成功(alreadyInactive=true)。 | REST(客户端) | {tokenId:string, userId:string, platform:string, deleted:bool, active:bool, alreadyInactive:bool} |
getPushTokens | 查询本人设备推送 token(IDL rev21 C23;客户端 REST `GET /api/apps/{appkey}/push/tokens`)→ `{userId,tokens:[PushToken],total,activeTotal,platforms}`;含 active=false 历史,按 createdAt 倒序。只读、幂等、不产生事件。 | REST(客户端) | {userId:string, tokens:PushToken[], total:uint32, activeTotal:uint32, platforms:string[]} |
本页 6 个操作,其中 6 个在本平台绑定中声明了方法签名。
跨端方法名
| 操作 | Android | Web | Electron | macOS | Flutter | Native (C ABI) | iOS |
|---|---|---|---|---|---|---|---|
subscribePresence | subscribePresence | subscribePresence | subscribePresence | subscribePresence | subscribePresence | — | func |
unsubscribePresence | unsubscribePresence | unsubscribePresence | unsubscribePresence | unsubscribePresence | unsubscribePresence | — | func |
getPresenceSubscriptions | getPresenceSubscriptions | getPresenceSubscriptions | getPresenceSubscriptions | getPresenceSubscriptions | getPresenceSubscriptions | — | func |
registerPushToken | registerPushToken | registerPushToken | registerPushToken | registerPushToken | registerPushToken | — | func |
unregisterPushToken | unregisterPushToken | unregisterPushToken | unregisterPushToken | unregisterPushToken | unregisterPushToken | — | func |
getPushTokens | getPushTokens | getPushTokens | getPushTokens | getPushTokens | getPushTokens | — | func |
方法名在 GA 平台之间保持一致(规则 A);Native C ABI 只覆盖部分操作,其余操作以 — 标注。
subscribePresence
订阅用户在线状态(IDL rev20;客户端 REST `POST /api/apps/{appkey}/users/{userId}/presence/subscriptions`,userId 取自当前登录用户)。被订阅用户上线/离线/被踢/注销时通过长连接收到 `presence_changed`。订阅自己 1001;目标用户不存在/属于其它 app 1004;订阅总数上限 500(超限 1001);幂等(重复订阅不重复入列)。成功返回变更后的完整订阅列表 `{subscribed:[...]}`。好友关系本身已默认订阅对方在线状态,无需额外调用。
subscribePresence(userIds: string[]): Promise<RcResult<{subscribed: string[]}>>| 参数 | 类型 | 说明 |
|---|---|---|
userIds | string[] | 必填;用户 ID 列表(批量接口通常有上限) |
{subscribed:string[]} 成功返回的数据;失败时按错误码处理
const res = await client.subscribePresence(['user2']);
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
1004 | USER_NOT_FOUND | 客户端 / 参数 / 权限 | 404 | 否 | 用户不存在 |
unsubscribePresence
取消订阅用户在线状态(IDL rev20;客户端 REST `POST .../presence/subscriptions` 的 `unsubscribe` 分支)。取消未订阅的用户幂等成功(不报错);订阅自己 1001;目标用户不存在 1004。成功返回变更后的完整订阅列表 `{subscribed:[...]}`。仅停止接收该用户的实时在线状态帧,好友关系不受影响。
unsubscribePresence(userIds: string[]): Promise<RcResult<{subscribed: string[]}>>| 参数 | 类型 | 说明 |
|---|---|---|
userIds | string[] | 必填;用户 ID 列表(批量接口通常有上限) |
{subscribed:string[]} 成功返回的数据;失败时按错误码处理
const res = await client.unsubscribePresence(['user2']);
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
1004 | USER_NOT_FOUND | 客户端 / 参数 / 权限 | 404 | 否 | 用户不存在 |
getPresenceSubscriptions
查询当前用户的在线状态订阅列表(IDL rev20;客户端 REST `GET /api/apps/{appkey}/users/{userId}/presence/subscriptions`)→ `{userId,subscribed:[...]}`。只读、幂等、不产生事件。
getPresenceSubscriptions(): Promise<RcResult<{userId: string, subscribed: string[]}>>{userId:string, subscribed:string[]} 成功返回的数据;失败时按错误码处理
const res = await client.getPresenceSubscriptions();
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
registerPushToken
注册设备推送 token(IDL rev21 C23 收口;客户端 REST `POST /api/apps/{appkey}/push/tokens`,服务端 rev20 已实现,本 op 补 SDK 语义面)→ PushToken。幂等键 `(userId, platform, token)`:重复注册返回既有 tokenId 并重新置 active=true;`token` 8..=512 字符、`platform` ∈ ios|android|web|huawei|xiaomi|oppo|vivo|fcm、未知平台/长度非法 1001、每用户 20 个活跃 token 上限(超限 1001)、注销/封禁用户 1016;同一 (platform, token) 被其它用户注册时旧记录置 active=false(设备换绑)。
registerPushToken(options: RegisterPushTokenOptions): Promise<RcResult<PushToken>>| 参数 | 类型 | 说明 |
|---|---|---|
options | {platform:string, token:string, deviceId?:string, appVersion?:string} | 必填;选项对象(字段见类型列):{ platform:string, token:string, deviceId?:string, appVersion?:string } |
PushToken 成功返回的数据;失败时按错误码处理
const res = await client.registerPushToken({ platform: 'android', token: 'TOKEN' });
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1002 | INVALID_TOKEN | 客户端 / 参数 / 权限 | 401 | 否 | Token 无效或已过期 |
1016 | USER_BANNED | 客户端 / 参数 / 权限 | 403 | 否 | 账号已被封禁 |
unregisterPushToken
注销本人设备推送 token(IDL rev21 C23;客户端 REST `DELETE /api/apps/{appkey}/push/tokens/{tokenId}`):软删除 active=false 并保留历史供审计 → `{tokenId,userId,platform,deleted,active:false,alreadyInactive}`。非本人或不存在 1001(不泄露他人 token);重复注销幂等成功(alreadyInactive=true)。
unregisterPushToken(tokenId: string): Promise<RcResult<UnregisterPushTokenResult>>| 参数 | 类型 | 说明 |
|---|---|---|
tokenId | string | 必填;字段含义见类型定义 |
{tokenId:string, userId:string, platform:string, deleted:bool, active:bool, alreadyInactive:bool} 成功返回的数据;失败时按错误码处理
const res = await client.unregisterPushToken('pt_1001');
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1002 | INVALID_TOKEN | 客户端 / 参数 / 权限 | 401 | 否 | Token 无效或已过期 |
getPushTokens
查询本人设备推送 token(IDL rev21 C23;客户端 REST `GET /api/apps/{appkey}/push/tokens`)→ `{userId,tokens:[PushToken],total,activeTotal,platforms}`;含 active=false 历史,按 createdAt 倒序。只读、幂等、不产生事件。
getPushTokens(): Promise<RcResult<PushTokenListResult>>{userId:string, tokens:PushToken[], total:uint32, activeTotal:uint32, platforms:string[]} 成功返回的数据;失败时按错误码处理
const res = await client.getPushTokens();
if (res.code !== 0) throw new Error(res.msg);
const data = res.data;| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1002 | INVALID_TOKEN | 客户端 / 参数 / 权限 | 401 | 否 | Token 无效或已过期 |
相关文档
- 功能列表:103 个操作与签名
- 状态码:错误码与重试策略
- API 参考:类与成员
- IMLib 集成指南