docs: SDK设计规范 迁移到 XuqmGroup-Docs,此文件改为指针
权威来源:XuqmGroup-Docs/design/06-sdk-cross-platform-spec.md RN SDK 实现遵循跨平台规范,不在此独立维护设计决策。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
8fb59bb5f2
当前提交
bed221f536
541
docs/SDK设计规范.md
541
docs/SDK设计规范.md
@ -1,539 +1,8 @@
|
|||||||
# XuqmGroup SDK 设计规范
|
# XuqmGroup SDK 设计规范
|
||||||
|
|
||||||
> 版本:v2.0
|
> ⚠️ 本文档已迁移到跨平台文档仓库,此文件仅作指引。
|
||||||
> 生效范围:**全平台** — Android、iOS、React Native、Flutter、HarmonyOS、微信小程序、Vue3、Java / Python / Go 服务端 SDK
|
>
|
||||||
> 状态:需求确认,待各平台落地实现
|
> **权威来源**:`XuqmGroup-Docs/design/06-sdk-cross-platform-spec.md`
|
||||||
|
> Git 仓库:`https://xuqinmin.com/xuqmGroup/XuqmGroup-Docs`
|
||||||
|
|
||||||
---
|
RN SDK 的实现须严格遵循上述跨平台规范,不得在此文件中维护独立设计决策。
|
||||||
|
|
||||||
## 一、设计原则
|
|
||||||
|
|
||||||
1. **App 零感知初始化**:配置文件方式下,App 无需写任何初始化代码。
|
|
||||||
2. **一次认证,全局生效**:`setUserInfo()` 一次调用,所有子 SDK(Push、IM、License 等)自动同步状态。
|
|
||||||
3. **失败即失败**:初始化失败、认证失败均抛出错误,不静默降级。
|
|
||||||
4. **服务按需激活**:哪些服务(IM、推送、License 等)由租户平台配置决定,SDK 根据返回配置自动激活对应能力,App 层无需判断。
|
|
||||||
5. **子 SDK 独立性**:各子 SDK 之间通过 `common` 共享上下文(appKey、baseUrl、userId 等),不互相硬依赖。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 二、XuqmSDK(核心 — @xuqm/rn-common)
|
|
||||||
|
|
||||||
### 2.1 初始化方式(仅两种)
|
|
||||||
|
|
||||||
#### 方式 A:配置文件自动初始化(推荐)
|
|
||||||
|
|
||||||
App 在构建阶段将加密配置文件(`.xuqmconfig`)放置到指定路径,SDK 在模块加载时自动读取并初始化。App 无需调用任何初始化代码。
|
|
||||||
|
|
||||||
```
|
|
||||||
配置文件路径(RN):src/assets/xuqm/config.xuqmconfig
|
|
||||||
配置文件格式:见 docs/配置文件规范.md
|
|
||||||
```
|
|
||||||
|
|
||||||
配置文件内容(加密前)包含:
|
|
||||||
- `appKey`:应用标识
|
|
||||||
- `platformUrl`:平台地址(从哪里拉取服务配置)
|
|
||||||
|
|
||||||
SDK 读取配置文件后,自动调用 **方式 B** 完成完整初始化(拉取远程服务配置)。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 方式 B:手动初始化
|
|
||||||
|
|
||||||
App 主动调用,适用于无法提前写入配置文件或需要动态切换环境的场景。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 使用默认公有平台(www.51szyx.com)
|
|
||||||
await XuqmSDK.initialize({ appKey: 'your-app-key', debug: __DEV__ })
|
|
||||||
|
|
||||||
// 使用私有化部署平台
|
|
||||||
await XuqmSDK.initialize({ appKey: 'your-app-key', platformUrl: 'https://your-server.com' })
|
|
||||||
```
|
|
||||||
|
|
||||||
**签名**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface XuqmInitOptions {
|
|
||||||
appKey: string
|
|
||||||
platformUrl?: string // 平台地址,可选;不传则使用内置默认公有平台地址
|
|
||||||
debug?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
XuqmSDK.initialize(options: XuqmInitOptions): Promise<void>
|
|
||||||
```
|
|
||||||
|
|
||||||
**行为**:
|
|
||||||
1. `platformUrl` 未传时使用内置默认公有平台地址(`DEFAULT_TENANT_PLATFORM_URL`)
|
|
||||||
2. 请求 `{platformUrl}/api/sdk/config?appKey={appKey}`
|
|
||||||
3. 平台根据 appKey 和租户服务开通情况,返回该 App 专属的服务配置:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"apiUrl": "...", // 通用 API 地址
|
|
||||||
"imWsUrl": "...", // IM WebSocket 地址(未开通则为 null)
|
|
||||||
"fileServiceUrl": "...", // 文件服务地址
|
|
||||||
"pushEnabled": true, // 是否开通推送服务
|
|
||||||
"licenseEnabled": false, // 是否开通 License 服务
|
|
||||||
"imEnabled": true // 是否开通 IM 服务
|
|
||||||
}
|
|
||||||
```
|
|
||||||
4. SDK 将服务配置保存,供所有子 SDK 使用。
|
|
||||||
5. **失败时直接抛出错误**,不降级。调用方必须处理异常。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 已移除(不再提供)
|
|
||||||
|
|
||||||
| 方法 | 移除原因 |
|
|
||||||
|------|---------|
|
|
||||||
| `XuqmSDK.initializeFromLicense(file, options?)` | License 是独立小服务,不承担 SDK 初始化职责 |
|
|
||||||
| `XuqmSDK.init(options): void` | 同步 init 不拉取服务配置,行为不完整;用方式 A 或方式 B 替代 |
|
|
||||||
| `XuqmSDK.initWithConfigFile(encrypted)` | 由自动初始化机制内部调用,不对外暴露 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2.2 用户认证:setUserInfo(核心枢纽)
|
|
||||||
|
|
||||||
`setUserInfo` 是所有子 SDK 用户状态同步的入口。**登录成功后调用一次,所有子 SDK 自动激活**。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface XuqmUserInfo {
|
|
||||||
userId: string // 必填
|
|
||||||
userSig?: string // IM 服务必填;租户未开通 IM 时可不传
|
|
||||||
name?: string
|
|
||||||
phone?: string
|
|
||||||
avatar?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
XuqmSDK.setUserInfo(info: XuqmUserInfo): void
|
|
||||||
```
|
|
||||||
|
|
||||||
**调用后的内部行为(自动、静默)**:
|
|
||||||
|
|
||||||
| 子 SDK | 触发动作 |
|
|
||||||
|--------|---------|
|
|
||||||
| PushSDK | 自动执行设备注册流程(见第三节) |
|
|
||||||
| ImSDK | 若 `userSig` 存在且平台开通了 IM,自动登录 IM 服务 |
|
|
||||||
| LicenseSDK | 更新用户上下文,供 License 验证使用 |
|
|
||||||
| UpdateSDK | 更新 userId,用于租户平台配置的灰度/定向更新 |
|
|
||||||
|
|
||||||
**登出时**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
XuqmSDK.setUserInfo(null)
|
|
||||||
```
|
|
||||||
|
|
||||||
触发所有子 SDK 登出:PushSDK 解绑 token,ImSDK 断开连接,清除所有用户上下文。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2.3 其他方法(保留)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
XuqmSDK.getUserId(): string | null
|
|
||||||
XuqmSDK.getUserInfo(): XuqmUserInfo | null
|
|
||||||
XuqmSDK.awaitInitialization(): Promise<void> // 等待初始化完成
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、PushSDK(推送 — @xuqm/rn-push)
|
|
||||||
|
|
||||||
### 3.1 初始化方式
|
|
||||||
|
|
||||||
**无需显式初始化**。当 `XuqmSDK.setUserInfo(info)` 被调用时,PushSDK 自动执行以下流程:
|
|
||||||
|
|
||||||
```
|
|
||||||
setUserInfo(info)
|
|
||||||
└─ PushSDK 内部触发:
|
|
||||||
1. detectPushVendor() — 自动检测当前设备厂商(华为/小米/OPPO/vivo/荣耀/FCM/APNs)
|
|
||||||
2. fetchVendorConfig(vendor) — 从平台获取该厂商推送配置(AppID、Secret 等)
|
|
||||||
3. registerWithVendorSDK() — 调用厂商 SDK 完成设备注册
|
|
||||||
4. onTokenReceived(token) — 收到 token 后自动上报绑定到平台
|
|
||||||
```
|
|
||||||
|
|
||||||
App 层无需关心设备厂商类型,也无需手动调用注册流程。
|
|
||||||
|
|
||||||
### 3.2 App 层可调用的 API
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 设置离线推送开关
|
|
||||||
PushSDK.setOfflinePushEnabled(enabled: boolean): Promise<void>
|
|
||||||
|
|
||||||
// 设置免打扰时间段(24小时制)
|
|
||||||
PushSDK.setQuietHours(start: string, end: string): Promise<void>
|
|
||||||
// 示例:PushSDK.setQuietHours('22:00', '08:00')
|
|
||||||
|
|
||||||
// 清除免打扰设置
|
|
||||||
PushSDK.clearQuietHours(): Promise<void>
|
|
||||||
|
|
||||||
// 登出(通常不需要手动调用,setUserInfo(null) 会自动触发)
|
|
||||||
PushSDK.logout(): Promise<void>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 已移除
|
|
||||||
|
|
||||||
| 方法 | 移除原因 |
|
|
||||||
|------|---------|
|
|
||||||
| `PushSDK.initialize(userId?)` | 由 `setUserInfo` 触发,不对外暴露 |
|
|
||||||
| `PushSDK.requestNativeRegistration()` | 内部流程,不对外暴露 |
|
|
||||||
| `PushSDK.registerToken(userId, token, vendor?)` | 内部流程,不对外暴露 |
|
|
||||||
| `PushSDK.onPushToken(callback)` | 内部流程,不对外暴露 |
|
|
||||||
| `PushSDK.unregisterToken(userId)` | 由 `setUserInfo(null)` 触发 |
|
|
||||||
| `PushSDK.setPendingToken / getPendingToken` | 内部状态,不对外暴露 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 四、ImSDK(即时通讯 — @xuqm/rn-im)
|
|
||||||
|
|
||||||
### 4.1 初始化与登录
|
|
||||||
|
|
||||||
**无需显式初始化**。依赖 `XuqmSDK.initialize()` 完成服务配置获取后即可工作。
|
|
||||||
|
|
||||||
**登录**:通过 `XuqmSDK.setUserInfo({ userId, userSig })` 自动触发,不需要 App 直接调用 `ImSDK.login()`。
|
|
||||||
|
|
||||||
**userSig 获取方式**:
|
|
||||||
- App 登录成功后,由 App 服务端根据业务逻辑生成并返回
|
|
||||||
- userSig 通常有时效性(建议 7 天),App 应在登录响应中一并返回
|
|
||||||
- App 在调用 `setUserInfo` 时传入,无需关心 IM 内部实现
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// App 登录后的标准流程
|
|
||||||
const loginResult = await api.login(phone, code)
|
|
||||||
XuqmSDK.setUserInfo({
|
|
||||||
userId: loginResult.userId,
|
|
||||||
userSig: loginResult.userSig, // 服务端随登录一并返回
|
|
||||||
name: loginResult.name,
|
|
||||||
phone: loginResult.phone,
|
|
||||||
})
|
|
||||||
// → PushSDK 自动注册
|
|
||||||
// → ImSDK 自动登录(若租户开通了 IM)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 userSig 刷新
|
|
||||||
|
|
||||||
当 userSig 过期或需要主动刷新时:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const newSig = await api.refreshUserSig()
|
|
||||||
ImSDK.refreshToken(newSig): Promise<void>
|
|
||||||
```
|
|
||||||
|
|
||||||
或通过重新调用 `setUserInfo` 携带新 userSig。
|
|
||||||
|
|
||||||
### 4.3 IM 与 Push 共用用户上下文
|
|
||||||
|
|
||||||
Push 和 IM 共享 `XuqmSDK` 的用户上下文(userId),两者通过 `setUserInfo` 统一管理:
|
|
||||||
- 同一个 userId 用于 Push 设备绑定和 IM 登录
|
|
||||||
- `setUserInfo(null)` 统一触发 Push 解绑和 IM 断连
|
|
||||||
|
|
||||||
### 4.4 可用方法
|
|
||||||
|
|
||||||
ImSDK 的具体 API 方法(消息收发、群组、好友等)保持现有设计不变,见 `docs/SDK-API参考.md` 第 5 节。
|
|
||||||
|
|
||||||
仅以下方法调整:
|
|
||||||
|
|
||||||
| 方法 | 变化 |
|
|
||||||
|------|------|
|
|
||||||
| `ImSDK.login(userId, userSig)` | 保留,但通常不需要 App 直接调用(由 setUserInfo 触发) |
|
|
||||||
| `ImSDK.refreshToken(userSig)` | **新增**,用于 userSig 过期刷新 |
|
|
||||||
| `ImSDK.disconnect()` | 保留,通常不需要直接调用(setUserInfo(null) 触发) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 五、UpdateSDK(更新 — @xuqm/rn-update)
|
|
||||||
|
|
||||||
### 5.1 插件注册
|
|
||||||
|
|
||||||
#### 批量注册(推荐)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
UpdateSDK.registerPlugins([
|
|
||||||
{ moduleId: 'buz1' },
|
|
||||||
{ moduleId: 'buz2' },
|
|
||||||
{ moduleId: 'buz3' },
|
|
||||||
])
|
|
||||||
```
|
|
||||||
|
|
||||||
**版本号由 SDK 自动获取**,不需要 App 传入:
|
|
||||||
- SDK 从本地 manifest 文件读取当前已安装的插件版本
|
|
||||||
- 如果 manifest 中无记录(首次安装),视为版本 `0.0.0`
|
|
||||||
|
|
||||||
#### 单个注册(仍支持,向后兼容)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
UpdateSDK.registerPlugin({ moduleId: 'buz1' })
|
|
||||||
// 注意:不再接受 version 字段
|
|
||||||
```
|
|
||||||
|
|
||||||
**类型定义变更**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 旧
|
|
||||||
interface PluginMeta {
|
|
||||||
moduleId: string
|
|
||||||
version: string // ← 移除
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新
|
|
||||||
interface PluginRegistration {
|
|
||||||
moduleId: string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 App 整包更新
|
|
||||||
|
|
||||||
#### 检查更新
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const info = await UpdateSDK.checkAppUpdate(bypassIgnore?: boolean): Promise<AppUpdateInfo>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Android APK 直接下载安装(新增)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 下载 APK 并在完成后调起系统安装器
|
|
||||||
await UpdateSDK.downloadAndInstallApk(
|
|
||||||
downloadUrl: string,
|
|
||||||
options?: {
|
|
||||||
onProgress?: (progress: number) => void // 0~1
|
|
||||||
sha256?: string // 校验值,有则验证
|
|
||||||
}
|
|
||||||
): Promise<void>
|
|
||||||
```
|
|
||||||
|
|
||||||
**完整整包更新流程示例**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const info = await UpdateSDK.checkAppUpdate()
|
|
||||||
if (!info.needsUpdate) return
|
|
||||||
|
|
||||||
if (Platform.OS === 'android' && info.downloadUrl) {
|
|
||||||
// Android:直接下载安装
|
|
||||||
await UpdateSDK.downloadAndInstallApk(info.downloadUrl, {
|
|
||||||
onProgress: (p) => setProgress(p),
|
|
||||||
sha256: info.apkHash ?? undefined,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// iOS / Android 商店跳转
|
|
||||||
await UpdateSDK.openStore(info.appStoreUrl, info.marketUrl)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 插件(Bundle)热更新
|
|
||||||
|
|
||||||
**两个方法,SDK 自动完成所有步骤**:
|
|
||||||
|
|
||||||
#### 方法 1:检查更新信息
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const info = await UpdateSDK.checkPluginUpdate(moduleId: string): Promise<PluginUpdateInfo>
|
|
||||||
```
|
|
||||||
|
|
||||||
App 层拿到 `info` 后可自行决定:弹窗提示用户、静默后台更新或忽略。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface PluginUpdateInfo {
|
|
||||||
needsUpdate: boolean
|
|
||||||
latestVersion: string
|
|
||||||
currentVersion: string // 新增:SDK 自动填入
|
|
||||||
changeLog?: string
|
|
||||||
forceUpdate?: boolean // 新增:强制更新标识
|
|
||||||
minCommonVersion?: string // 要求的最低 common bundle 版本
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 方法 2:执行更新
|
|
||||||
|
|
||||||
```ts
|
|
||||||
await UpdateSDK.updatePlugin(
|
|
||||||
moduleId: string,
|
|
||||||
options?: {
|
|
||||||
onProgress?: (progress: number) => void
|
|
||||||
silent?: boolean // true = 静默更新(不重载,下次启动生效)
|
|
||||||
}
|
|
||||||
): Promise<void>
|
|
||||||
```
|
|
||||||
|
|
||||||
**SDK 内部自动完成**:
|
|
||||||
1. 调用 `checkPluginUpdate()` 确认有更新
|
|
||||||
2. 下载 bundle(带进度回调)
|
|
||||||
3. 写入文件系统(`rn-bundles/<moduleId>.<platform>.bundle`)
|
|
||||||
4. 若 `silent = false`(默认),触发宿主重载当前插件
|
|
||||||
|
|
||||||
**一步完成(静默后台更新)**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 启动时后台静默检查并缓存,下次进入插件生效
|
|
||||||
await UpdateSDK.updatePlugin('buz1', { silent: true })
|
|
||||||
```
|
|
||||||
|
|
||||||
**带确认弹窗的前台更新**:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const info = await UpdateSDK.checkPluginUpdate('buz1')
|
|
||||||
if (info.needsUpdate) {
|
|
||||||
const confirmed = info.forceUpdate || (await showConfirm(`发现新版本 ${info.latestVersion},是否更新?`))
|
|
||||||
if (confirmed) {
|
|
||||||
await UpdateSDK.updatePlugin('buz1', {
|
|
||||||
onProgress: (p) => setProgress(p),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.4 已移除 / 废弃
|
|
||||||
|
|
||||||
| 方法 | 替代 |
|
|
||||||
|------|------|
|
|
||||||
| `UpdateSDK.checkAndCachePlugin(moduleId)` | `UpdateSDK.updatePlugin(moduleId, { silent: true })` |
|
|
||||||
| `UpdateSDK.downloadPluginBundle(url)` | 内部实现,不对外暴露 |
|
|
||||||
| `UpdateSDK.cachePluginBundle(...)` | 内部实现,不对外暴露 |
|
|
||||||
| `UpdateSDK.getCachedPluginBundle(moduleId)` | 内部实现,不对外暴露 |
|
|
||||||
| `PluginMeta.version`(注册时传 version)| SDK 自动从 manifest 读取 |
|
|
||||||
|
|
||||||
### 5.5 用户定向更新
|
|
||||||
|
|
||||||
灰度/定向更新的用户白名单在**租户平台**配置,SDK 无需感知。UpdateSDK 在检查更新时会自动携带当前 `userId`(来自 `XuqmSDK.getUserId()`),由服务端决定是否返回 `needsUpdate: true`。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 六、LicenseSDK(License 服务 — @xuqm/rn-license)
|
|
||||||
|
|
||||||
### 6.1 定位
|
|
||||||
|
|
||||||
License 是**独立小服务**,大多数租户不会开通。它:
|
|
||||||
- 不承担 SDK 初始化职责
|
|
||||||
- 不向其他 SDK 提供基础能力
|
|
||||||
- 与 IM / Push / Update 等没有依赖关系
|
|
||||||
- 使用 `XuqmSDK` 的 `apiUrl`、`appKey`、`userId` 等公共上下文
|
|
||||||
|
|
||||||
### 6.2 初始化方式
|
|
||||||
|
|
||||||
**无需独立初始化**。LicenseSDK 在调用任何方法前会内部调用 `XuqmSDK.awaitInitialization()`,等待核心 SDK 就绪后直接使用其配置。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// App 只需调用 XuqmSDK.initialize(),LicenseSDK 无需额外操作
|
|
||||||
await XuqmSDK.initialize({ appKey, platformUrl })
|
|
||||||
// ...用户登录...
|
|
||||||
XuqmSDK.setUserInfo({ userId, ... })
|
|
||||||
|
|
||||||
// 然后即可直接调用 LicenseSDK 方法
|
|
||||||
const license = await LicenseSDK.validateLicense(licenseId)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 已移除
|
|
||||||
|
|
||||||
| 方法 | 移除原因 |
|
|
||||||
|------|---------|
|
|
||||||
| `LicenseSDK.initialize(...)` | 依赖 XuqmSDK,无需独立初始化 |
|
|
||||||
| `XuqmSDK.initializeFromLicense(file)` | License 文件不承担 SDK 初始化职责 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 七、SDK 整体架构图
|
|
||||||
|
|
||||||
```
|
|
||||||
App
|
|
||||||
├── XuqmSDK.initialize(appKey, platformUrl)
|
|
||||||
│ └─ 拉取平台配置 ──────────────────────────────┐
|
|
||||||
│ │ 返回各服务 URL 和开通状态
|
|
||||||
│ ← apiUrl / imWsUrl / fileServiceUrl ──────────┘
|
|
||||||
│
|
|
||||||
├── XuqmSDK.setUserInfo({ userId, userSig?, ... })
|
|
||||||
│ ├─ PushSDK ──── 自动检测厂商 → 获取厂商配置 → 注册设备 → 上报 token
|
|
||||||
│ ├─ ImSDK ─────── 自动登录(若 userSig 存在且 IM 已开通)
|
|
||||||
│ ├─ UpdateSDK ─── 更新 userId(用于定向更新)
|
|
||||||
│ └─ LicenseSDK ── 更新用户上下文
|
|
||||||
│
|
|
||||||
└── XuqmSDK.setUserInfo(null)
|
|
||||||
├─ PushSDK ──── 解绑 token
|
|
||||||
└─ ImSDK ─────── 断开连接
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 八、各子 SDK 依赖关系
|
|
||||||
|
|
||||||
```
|
|
||||||
@xuqm/rn-common ← XuqmSDK 核心、HTTP 客户端、设备信息、公共上下文
|
|
||||||
▲
|
|
||||||
│ 依赖(通过 awaitInitialization + getConfig + getUserId 等)
|
|
||||||
├── @xuqm/rn-push
|
|
||||||
├── @xuqm/rn-im
|
|
||||||
├── @xuqm/rn-update
|
|
||||||
├── @xuqm/rn-xwebview
|
|
||||||
└── @xuqm/rn-license
|
|
||||||
```
|
|
||||||
|
|
||||||
子 SDK 之间**不互相依赖**,均通过 `@xuqm/rn-common` 共享配置和用户上下文。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 九、初始化完整流程参考
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// 1. 初始化(通常在 App 入口,配置文件模式下可省略)
|
|
||||||
// 公有平台:不传 platformUrl
|
|
||||||
await XuqmSDK.initialize({ appKey: 'your-app-key', debug: __DEV__ })
|
|
||||||
// 私有化部署:传入自有平台地址
|
|
||||||
// await XuqmSDK.initialize({ appKey: 'your-app-key', platformUrl: 'https://your-server.com' })
|
|
||||||
|
|
||||||
// 2. 业务登录(App 自有登录逻辑)
|
|
||||||
const result = await api.login(phone, verifyCode)
|
|
||||||
|
|
||||||
// 3. 一次调用,全局生效
|
|
||||||
XuqmSDK.setUserInfo({
|
|
||||||
userId: result.userId,
|
|
||||||
userSig: result.userSig, // 服务端随登录返回
|
|
||||||
name: result.name,
|
|
||||||
phone: result.phone,
|
|
||||||
})
|
|
||||||
// → PushSDK 自动完成设备注册
|
|
||||||
// → ImSDK 自动完成 IM 登录(若开通)
|
|
||||||
|
|
||||||
// 4. 插件热更新(后台静默,启动时调用一次)
|
|
||||||
await UpdateSDK.registerPlugins([
|
|
||||||
{ moduleId: 'buz1' },
|
|
||||||
{ moduleId: 'buz2' },
|
|
||||||
])
|
|
||||||
await Promise.all([
|
|
||||||
UpdateSDK.updatePlugin('buz1', { silent: true }),
|
|
||||||
UpdateSDK.updatePlugin('buz2', { silent: true }),
|
|
||||||
])
|
|
||||||
|
|
||||||
// 5. 登出
|
|
||||||
XuqmSDK.setUserInfo(null)
|
|
||||||
// → PushSDK 解绑,ImSDK 断连,userId 清除
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 十、跨平台实现要求
|
|
||||||
|
|
||||||
本文档中所有设计均为**跨平台通用需求**,适用于:
|
|
||||||
|
|
||||||
| 平台 | SDK 包 |
|
|
||||||
|------|--------|
|
|
||||||
| Android(原生) | `xuqm-android-sdk` |
|
|
||||||
| iOS(原生) | `XuqmSDK.framework` |
|
|
||||||
| React Native | `@xuqm/rn-*` |
|
|
||||||
| Flutter | `xuqm_flutter_sdk` |
|
|
||||||
| HarmonyOS | `xuqm_harmony_sdk` |
|
|
||||||
| 微信小程序 | `xuqm-miniprogram-sdk` |
|
|
||||||
| Vue3(H5) | `@xuqm/vue-sdk` |
|
|
||||||
| Java 服务端 | `xuqm-java-sdk` |
|
|
||||||
| Python 服务端 | `xuqm-python-sdk` |
|
|
||||||
| Go 服务端 | `xuqm-go-sdk` |
|
|
||||||
|
|
||||||
各平台在实现时应在 API 签名和行为上保持一致;平台差异(如服务端 SDK 无 Push/IM 客户端能力)通过能力矩阵文档说明。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 十一、待讨论 / 待决策事项
|
|
||||||
|
|
||||||
| 事项 | 当前状态 | 说明 |
|
|
||||||
|------|---------|------|
|
|
||||||
| userSig 过期自动刷新 | 待设计 | 是否由 SDK 内部定时刷新,还是 App 层感知过期后手动调用 `refreshToken`? |
|
|
||||||
| IM 未开通时 userSig 传入是否报警 | 待决策 | 建议在 debug 模式下打印警告 |
|
|
||||||
| PushSDK 厂商配置获取失败降级策略 | 待决策 | 获取厂商配置失败时是否还尝试使用上次缓存配置? |
|
|
||||||
| 配置文件格式版本向上兼容 | 进行中 | 见 `docs/配置文件规范.md` |
|
|
||||||
| 服务端 SDK(Java/Go/Python)的 setUserInfo 等效方法 | 待设计 | 服务端无设备/Push 概念,需要单独定义 |
|
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户