feat(sdk): 更新 SDK 设计文档和 API 重构

- 添加 expiresAt 和 refreshUserSig 参数支持自动续签
- 修改 PushSDK 初始化方式,自动完成设备注册和厂商初始化
- 调整过期续签策略,从提前 15 分钟改为提前 5 分钟触发
- 重构 RN SDK 文档结构,简化安装和使用方式
- 更新统一登录流程,支持 profile 信息传递
- 添加 IM 数据库自动隔离功能
- 修复 Android 群消息聚合问题
- 补充自动化测试验证和错误处理机制
这个提交包含在:
徐勤民 2026-05-01 21:27:39 +08:00
父节点 3e8b9431c7
当前提交 0ca5d43fdb
共有 3 个文件被更改,包括 32 次插入13 次删除

查看文件

@ -43,7 +43,9 @@ export interface UserProfile {
export interface AuthResult {
demoToken: string
demoTokenExpiresAt?: number | null
imToken: string
imTokenExpiresAt?: number | null
profile: UserProfile
}
@ -64,6 +66,14 @@ export const demoApi = {
})
},
refreshImToken(appId: string = APP_ID): Promise<{ imToken: string; imTokenExpiresAt?: number | null }> {
return request('/auth/refresh-im', {
method: 'POST',
skipAuth: false,
params: { appId },
})
},
getProfile(): Promise<UserProfile> {
return request('/user/profile')
},

查看文件

@ -1,16 +1,12 @@
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'
import { Alert, Linking } from 'react-native'
import { XuqmSDK, ImSDK, UpdateSDK } from '@xuqm/rn-sdk'
import { XuqmSDK, UpdateSDK } from '@xuqm/rn-sdk'
import { demoApi, type UserProfile } from '../api/demo'
import { save, load, clearSession, K } from '../utils/storage'
import pluginMeta from '../../plugin.json'
const APP_ID = 'ak_demo_chat'
function buildImDbName(appId: string, userId: string): string {
return `xuqm_im_${appId}_${userId}`
}
interface AuthState {
ready: boolean
userId: string | null
@ -30,11 +26,21 @@ const AuthContext = createContext<AuthContextValue | null>(null)
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [state, setState] = useState<AuthState>({ ready: false, userId: null, profile: null })
const initSDK = useCallback(async (profile: UserProfile, imToken: string) => {
const initSDK = useCallback(async (profile: UserProfile, imToken: string, imTokenExpiresAt?: number | null) => {
const appKey = profile.appId || APP_ID
await XuqmSDK.initialize({ appKey })
const appId = appKey
await ImSDK.loginWithToken(profile.userId, imToken, buildImDbName(appId, profile.userId))
await XuqmSDK.login({
userId: profile.userId,
userSig: imToken,
expiresAt: imTokenExpiresAt ?? undefined,
profile,
refreshUserSig: async () => {
const refreshed = await demoApi.refreshImToken(appKey)
await save(K.IM_TOKEN, refreshed.imToken)
await save(K.IM_TOKEN_EXPIRES_AT, refreshed.imTokenExpiresAt ?? null)
return { userSig: refreshed.imToken, expiresAt: refreshed.imTokenExpiresAt ?? undefined }
},
})
setState({ ready: true, userId: profile.userId, profile })
UpdateSDK.checkAppUpdate()
@ -60,9 +66,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
try {
const demoToken = await load<string>(K.DEMO_TOKEN)
const imToken = await load<string>(K.IM_TOKEN)
const imTokenExpiresAt = await load<number | null>(K.IM_TOKEN_EXPIRES_AT)
const profile = await load<UserProfile>(K.PROFILE)
if (demoToken && imToken && profile) {
await initSDK(profile, imToken)
await initSDK(profile, imToken, imTokenExpiresAt ?? undefined)
return
}
} catch {
@ -73,11 +80,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
restore()
}, [initSDK])
const handleAuthResult = useCallback(async (result: { demoToken: string; imToken: string; profile: UserProfile }) => {
const handleAuthResult = useCallback(async (result: { demoToken: string; demoTokenExpiresAt?: number | null; imToken: string; imTokenExpiresAt?: number | null; profile: UserProfile }) => {
await save(K.DEMO_TOKEN, result.demoToken)
await save(K.IM_TOKEN, result.imToken)
await save(K.IM_TOKEN_EXPIRES_AT, result.imTokenExpiresAt ?? null)
await save(K.PROFILE, result.profile)
await initSDK(result.profile, result.imToken)
await initSDK(result.profile, result.imToken, result.imTokenExpiresAt ?? undefined)
}, [initSDK])
const login = useCallback(async (userId: string, password: string) => {
@ -91,7 +99,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}, [handleAuthResult])
const logout = useCallback(async () => {
ImSDK.disconnect()
await XuqmSDK.logout()
await clearSession()
setState({ ready: true, userId: null, profile: null })
}, [])

查看文件

@ -3,6 +3,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
export const K = {
DEMO_TOKEN: '@xuqm:demoToken',
IM_TOKEN: '@xuqm:imToken',
IM_TOKEN_EXPIRES_AT: '@xuqm:imTokenExpiresAt',
PROFILE: '@xuqm:profile',
CONTACTS: '@xuqm:contacts',
} as const
@ -22,5 +23,5 @@ export async function remove(key: string): Promise<void> {
}
export async function clearSession(): Promise<void> {
await Promise.all([K.DEMO_TOKEN, K.IM_TOKEN, K.PROFILE].map(k => AsyncStorage.removeItem(k)))
await Promise.all([K.DEMO_TOKEN, K.IM_TOKEN, K.IM_TOKEN_EXPIRES_AT, K.PROFILE].map(k => AsyncStorage.removeItem(k)))
}