docs: 同步更新各平台 SDK 集成文档(V2 简化登录)

- Android: 移除 UserSig 续签章节,更新登录示例
- iOS: 移除过期检测章节,更新登录示例
- RN: 更新登录示例
- Vue3: 更新登录示例
- HarmonyOS: 更新登录示例
- Server API: 更新 /api/im/auth/login 参数说明与签名规则
这个提交包含在:
XuqmGroup 2026-05-01 22:18:58 +08:00
父节点 7b7989525f
当前提交 27d298a622
共有 6 个文件被更改,包括 72 次插入60 次删除

查看文件

@ -1,12 +1,12 @@
# Android SDK 接入指南 # Android SDK 接入指南
**版本**0.4.xUserSig 鉴权)· **最低 Android 版本**API 24 (Android 7.0) · **语言**Kotlin **版本**0.5.xUserSig 鉴权 · 简化登录)· **最低 Android 版本**API 24 (Android 7.0) · **语言**Kotlin
## 功能模块 ## 功能模块
| 模块 | Artifact | 功能 | | 模块 | Artifact | 功能 |
|------|----------|------| |------|----------|------|
| sdk-core | `com.xuqm:sdk-core` | 初始化、网络、鉴权、UserSig 续签 | | sdk-core | `com.xuqm:sdk-core` | 初始化、网络、鉴权 |
| sdk-im | `com.xuqm:sdk-im` | 单聊、群聊、消息收发、会话、好友、群组 | | sdk-im | `com.xuqm:sdk-im` | 单聊、群聊、消息收发、会话、好友、群组 |
| sdk-push | `com.xuqm:sdk-push` | 自动检测厂商、设备 Token 注册(华为/小米/OPPO/vivo/荣耀/FCM | | sdk-push | `com.xuqm:sdk-push` | 自动检测厂商、设备 Token 注册(华为/小米/OPPO/vivo/荣耀/FCM |
| sdk-update | `com.xuqm:sdk-update` | App 更新检查、下载安装 | | sdk-update | `com.xuqm:sdk-update` | App 更新检查、下载安装 |
@ -52,13 +52,11 @@ XuqmSDK.initialize(
```kotlin ```kotlin
// 登录(协程 suspend 函数) // 登录(协程 suspend 函数)
// 只需要 userId + userSig,不需要 nickname / avatar / expiresAt
lifecycleScope.launch { lifecycleScope.launch {
XuqmSDK.login( XuqmSDK.login(
userId = "user_001", userId = "user_001",
userSig = "your_user_sig_jwt", // 由业务服务端签发 userSig = "your_user_sig_jwt", // 由业务服务端签发
nickname = "张三",
avatar = "https://...",
userSigExpiresAt = 1893456000000L, // UserSig 过期时间戳(毫秒),可选
) )
} }
@ -118,20 +116,15 @@ ImSDK.deleteConversation(targetId, "SINGLE")
### 6. Push 多厂商接入 ### 6. Push 多厂商接入
SDK 在登录后会自动检测手机厂商并初始化对应 Push 服务。业务层通常无需手动调用,但可根据需要主动控制: SDK 在 `XuqmSDK.login()` 成功后会自动检测手机厂商、初始化对应 Push SDK、获取 Token 并上报到 Push 服务端。业务层**无需手动调用**任何 Push 注册 API。
如需主动控制,可调用:
```kotlin ```kotlin
// 手动检测当前设备厂商 // 检测当前设备厂商
val vendor = PushSDK.detectVendor() val vendor = PushSDK.detectVendor()
// 返回HUAWEI / XIAOMI / OPPO / VIVO / HONOR / FCM // 返回HUAWEI / XIAOMI / OPPO / VIVO / HONOR / FCM
// 手动初始化各厂商 Push SDK通常由 onSdkLogin 自动调用)
PushSDK.initializeVendors(context)
// 手动绑定/解绑 IM 用户与 Push Token
PushSDK.bindImUser(context, userId = "user_001")
PushSDK.unbindImUser(userId = "user_001")
// 开启或关闭推送接收 // 开启或关闭推送接收
PushSDK.setReceivePush(context, enabled = false) PushSDK.setReceivePush(context, enabled = false)
``` ```
@ -147,26 +140,27 @@ PushSDK.setReceivePush(context, enabled = false)
| 荣耀 | `com.hihonor.mcs:mcs-push` | 需在荣耀开发者服务平台配置 | | 荣耀 | `com.hihonor.mcs:mcs-push` | 需在荣耀开发者服务平台配置 |
| FCM | `com.google.firebase:firebase-messaging` | 模拟器无 Google Play 服务时会 fallback | | FCM | `com.google.firebase:firebase-messaging` | 模拟器无 Google Play 服务时会 fallback |
### 7. UserSig 续签 ### 7. 多模块统一登录
`UserSig` 即将过期(默认提前 5 分钟时,SDK 会触发续签回调。业务层应在回调中向自己的服务端申请新的 UserSig,然后重新调用 `XuqmSDK.login()` 刷新 Token 和定时器。 无论集成了哪些模块IM、Push、Update,**初始化和登录永远只做一次**
```kotlin ```kotlin
// 设置续签监听器(建议在初始化后、登录前设置) // 初始化Application.onCreate
XuqmSDK.setUserSigRefreshListener { XuqmSDK.initialize(context, appKey = "your_app_key")
// 异步获取新 UserSig
lifecycleScope.launch { // 登录(业务登录成功后调用一次)
val newUserSig = yourBackend.refreshUserSig("user_001") XuqmSDK.login(userId = "user_001", userSig = "jwt_token")
XuqmSDK.login( // ↓ 自动触发
userId = "user_001", // · ImSDK.onSdkLogin → 连接 WebSocket
userSig = newUserSig, // · PushSDK.onSdkLogin → 注册厂商 Token 并上报
userSigExpiresAt = newExpiryTimeMs, // · UpdateSDK.onSdkLogin → 无需额外操作(检查时自动携带凭证)
)
} // 登出(业务退出时调用一次)
} XuqmSDK.logout()
// ↓ 自动触发所有模块清理
``` ```
> **注意**`userSigExpiresAt` 为 Unix 时间戳(毫秒)。若登录时不传该值,则不会启动续签定时器 > **注意**`userSig` 一旦获取即永久有效,SDK 侧不做过期检查与续签。如需撤销权限,业务侧可在租户平台重置 `appSecret` 或拉黑账号
### 8. 版本更新 ### 8. 版本更新

查看文件

@ -54,9 +54,11 @@ export default class EntryAbility extends UIAbility {
### 2. IM 登录 ### 2. IM 登录
```typescript ```typescript
import { ImSDK } from '@xuqm/harmony-sdk' import { XuqmSDK, ImSDK } from '@xuqm/harmony-sdk'
await ImSDK.login('user_001', '张三') // 只需要 userId + userSig
await XuqmSDK.login('user_001', 'your_user_sig_jwt')
// 如果集成了 ImSDK,XuqmSDK.login 会自动触发 WebSocket 连接
``` ```
### 3. 监听消息 ### 3. 监听消息

查看文件

@ -6,7 +6,7 @@
| 模块 | 功能 | | 模块 | 功能 |
|------|------| |------|------|
| XuqmCore | 初始化、网络、鉴权、UserSig 过期检测 | | XuqmCore | 初始化、网络、鉴权 |
| XuqmIM | 单聊、群聊、消息收发15 种类型)、连接状态监听 | | XuqmIM | 单聊、群聊、消息收发15 种类型)、连接状态监听 |
| XuqmPush | APNs 设备 Token 注册、FCM 备选、通知处理 | | XuqmPush | APNs 设备 Token 注册、FCM 备选、通知处理 |
| XuqmUpdate | App 版本检查、App Store 跳转 | | XuqmUpdate | App 版本检查、App Store 跳转 |
@ -61,12 +61,10 @@ XuqmSDK.shared.initialize(config: config)
```swift ```swift
import XuqmIM import XuqmIM
// 方式一:使用 UserSig 登录(推荐生产环境) // 使用 UserSig 登录(推荐生产环境)
// 只需要 userId + userSig,不需要 nickname / avatar / expiresAt
try await XuqmSDK.shared.login(userId: "user_001", userSig: "your_user_sig_jwt") try await XuqmSDK.shared.login(userId: "user_001", userSig: "your_user_sig_jwt")
// 方式二Demo 环境快速登录
try await ImSDK.shared.loginWithDemo(userId: "user_001", password: "123456")
// 设置事件代理 // 设置事件代理
ImSDK.shared.setDelegate(self) ImSDK.shared.setDelegate(self)
@ -187,24 +185,25 @@ func application(_ application: UIApplication, didRegisterForRemoteNotifications
try await PushSDK.shared.registerFcmToken(fcmToken, userId: "user_001") try await PushSDK.shared.registerFcmToken(fcmToken, userId: "user_001")
``` ```
### 9. UserSig 过期检测 ### 9. 多模块统一登录
`XuqmSDK` 会在登录时解析 UserSig JWT 的 `exp` 字段,并在过期前 5 分钟触发 `onUserSigExpired` 回调。业务层应在此回调中重新获取 UserSig 并登录。 无论集成了哪些模块IM、Push、Update,**初始化和登录永远只做一次**
```swift ```swift
// 设置过期回调(建议在初始化后设置) // 初始化
XuqmSDK.shared.onUserSigExpired = { [weak self] in XuqmSDK.shared.initialize(config: config)
Task {
let newUserSig = await self?.yourBackend.refreshUserSig() // 登录(业务登录成功后调用一次)
try? await XuqmSDK.shared.login(userId: "user_001", userSig: newUserSig) try await XuqmSDK.shared.login(userId: "user_001", userSig: userSig)
} // ↓ 自动触发
} // · ImSDK 连接 WebSocket
// · PushSDK 注册 APNs Token 并上报
// 登出(业务退出时调用一次)
XuqmSDK.shared.logout()
``` ```
> **注意** > **注意**`userSig` 一旦获取即永久有效,SDK 侧不做过期检测与续签。
> - 回调触发时机为 `exp - 300s`(提前 5 分钟)。
> - 调用 `logout()` 后内部 Timer 会被自动 `invalidate`
> - 若 UserSig 已过期(`exp <= now`),回调会立即触发。
### 10. 检查更新 ### 10. 检查更新

查看文件

@ -60,18 +60,21 @@ await XuqmSDK.initialize({
> SDK 内部自动处理服务器地址、WebSocket 连接、文件服务等配置,开发者无需关心。 > SDK 内部自动处理服务器地址、WebSocket 连接、文件服务等配置,开发者无需关心。
### 2. IM 登录 ### 2. 统一登录
```ts ```ts
import { XuqmSDK } from '@xuqm/rn-common'
import { ImSDK } from '@xuqm/rn-im' import { ImSDK } from '@xuqm/rn-im'
// 登录userId + 用户信息) // 登录只需要 userId + userSig
// v0.3.x传入用户信息,本地 DB 按 userId 自动隔离 // nickname / avatar 不再通过登录接口传入
await ImSDK.login('user_001', 'nickname', 'https://avatar.url') await XuqmSDK.login({
userId: 'user_001',
userSig: 'your_user_sig_jwt',
})
// 推荐提前在您的服务端生成 UserSigv0.4.0 正式采用) // 如果集成了 rn-im,XuqmSDK.login 会自动触发 ImSDK 连接
// const userSig = await yourApi.getUserSig(userId) // 业务侧无需单独调用 ImSDK.login
// await ImSDK.login('user_001', userSig)
``` ```
### 3. 消息收发 ### 3. 消息收发

查看文件

@ -30,14 +30,28 @@ POST /api/im/auth/login
|------|------|------| |------|------|------|
| `appId` | 是 | 应用 ID | | `appId` | 是 | 应用 ID |
| `userId` | 是 | 用户 ID | | `userId` | 是 | 用户 ID |
| `nickname` | 是 | 昵称 |
**请求头**
| 头 | 必填 | 说明 |
|----|------|------|
| `X-App-Timestamp` | 是 | 当前时间戳(毫秒) |
| `X-App-Nonce` | 是 | 随机字符串 |
| `X-App-Signature` | 是 | HmacSHA256 签名 |
**签名 Payload**(已简化,不再包含 nickname/avatar
```
{appId}\n{userId}\n{timestamp}\n{nonce}
```
**响应** **响应**
```json ```json
{ "token": "eyJ..." } { "token": "eyJ...", "expiresAt": 9223372036854775807 }
``` ```
> `expiresAt` 为极大值(约 100 年),表示 token 永久有效。SDK 侧不做过期检查。
--- ---
### WebSocket 连接 ### WebSocket 连接
@ -255,7 +269,7 @@ Content-Type: application/json
| HTTP 状态 | code | 说明 | | HTTP 状态 | code | 说明 |
|-----------|------|------| |-----------|------|------|
| 400 | 400 | 请求参数错误 | | 400 | 400 | 请求参数错误 |
| 401 | 401 | Token 无效或过期 | | 401 | 401 | Token 无效或签名验证失败 |
| 403 | 403 | 无权限操作(如撤回他人消息)| | 403 | 403 | 无权限操作(如撤回他人消息)|
| 404 | 404 | 资源不存在 | | 404 | 404 | 资源不存在 |
| 500 | 500 | 服务器内部错误 | | 500 | 500 | 服务器内部错误 |

查看文件

@ -51,7 +51,7 @@ import { useIm } from '@xuqm/vue3-sdk'
const { messages, connected, login, sendMessage, revokeMessage } = useIm() const { messages, connected, login, sendMessage, revokeMessage } = useIm()
onMounted(() => login('user_001', '张三')) onMounted(() => login('user_001', 'your_user_sig_jwt'))
</script> </script>
<template> <template>