XuqmGroup-Server/docs/API_ACCESS.md
XuqmGroup f5a1eb4470 docs(sdk): 添加 React Native SDK 文档和 Android/HarmonyOS 发版脚本
- 新增 XuqmGroup React Native SDK 使用文档,包含安装、初始化、HTTP客户端、IM模块、推送模块、版本管理等功能说明
- 添加 Android Gradle 发版任务脚本,支持构建发布 APK 并上传到更新服务
- 添加 HarmonyOS hvigorw 发版任务脚本,支持 HAP 包构建和上传功能
- 实现多平台版本检查、自动重连、灰度发布等发版流程自动化
- 集成商店提交、定时发布、Webhook 回调等发布后处理功能
2026-04-29 17:35:52 +08:00

20 KiB

XuqmGroup Server 联调接口文档

最后更新2026-04-28

线上入口

服务 地址 说明
租户服务 https://dev.xuqinmin.com/api/ 认证、应用、子账号、运营平台
IM HTTP https://dev.xuqinmin.com/api/im/ IM 登录、消息发送、撤回、历史消息
IM WebSocket wss://dev.xuqinmin.com/ws/im 实时消息
文件服务 https://file.dev.xuqinmin.com/api/file/ 文件上传、下载、缩略图
App 更新 https://dev.xuqinmin.com/api/v1/updates/ 原生版本管理
RN 热更新 https://dev.xuqinmin.com/api/v1/rn/ Bundle 热更新

ID 约定

这套工程里同时存在两种“应用标识”,不要混用:

名称 含义 常见位置
tenant appId 租户平台应用主键,tenant-service/api/apps/{id}/api/apps/{appId}/services 使用它 租户平台、服务配置页
IM appKey IM 业务域作用域标识,im-service 的管理接口和消息接口虽然参数名仍叫 appId,但实际传的是这个值 IM 管理页、IM HTTP 接口

结论:

  • tenant-platform 的“服务配置”只认租户 app.id
  • tenant-platform 的“IM 管理”必须带 appKey
  • tenant-platform 的“离线推送 / 版本管理”只需要一次开通,平台差异配置在各自的管理页里维护,不再按 Android / iOS / 鸿蒙分别申请开通
  • im-service 代码里沿用旧参数名 appId,但这是历史命名,调用方传的是 appKey

初始化管理员账号

字段
用户名 admin
初始密码 Admin@123456
登录接口 POST /api/auth/ops/login

统一响应

{
  "code": 200,
  "status": "0",
  "data": {},
  "message": "success"
}

常见错误码

code status 说明
200 "0" 成功
400 "1" 参数校验失败或请求不合法
401 "1" 未登录、Token 无效或已过期
403 "1" 无权限访问
500 "1" 服务端内部错误

鉴权规则

场景 鉴权方式
租户平台接口 Authorization: Bearer <tenant_jwt>
运营平台接口 Authorization: Bearer <ops_jwt>
IM HTTP 接口 Authorization: Bearer <im_jwt>
IM WebSocket ?token=<im_jwt>
App 更新检查 无需登录
RN 更新检查 无需登录
Bundle 下载 无需登录

核心接口清单

tenant-service

方法 路径 鉴权 说明
GET /api/auth/captcha 获取图形验证码
POST /api/auth/send-email-code 发送邮箱验证码
POST /api/auth/register 注册主账号
POST /api/auth/login 租户登录
POST /api/auth/forgot-password 发送找回密码邮件
POST /api/auth/reset-password 重置密码
GET /api/apps 应用列表
GET /api/apps/{id} 应用详情
POST /api/apps 创建应用
PUT /api/apps/{id} 更新应用
DELETE /api/apps/{id} 删除应用
GET /api/apps/{appId}/services 服务列表
GET /api/apps/{appId}/services/item 按平台和服务类型查询单条服务配置
PUT /api/apps/{appId}/services/config 更新服务配置,IM 和 UPDATE 走各自的配置模型
POST /api/apps/{appId}/services/toggle 开关服务
POST /api/apps/{appId}/services/{id}/regenerate-key 重新生成服务密钥
GET /api/sub-accounts 子账号列表
POST /api/sub-accounts/send-verify-code 子账号邮箱验证码
POST /api/sub-accounts/verify-email 校验子账号邮箱
POST /api/sub-accounts 创建子账号
DELETE /api/sub-accounts/{id} 禁用子账号
POST /api/auth/ops/login 运营管理员登录
GET /api/ops/tenants 运营租户列表
POST /api/ops/tenants/{id}/toggle-status 租户启停
GET /api/ops/statistics 统计面板

im-service

方法 路径 鉴权 说明
POST /api/im/auth/login 获取 IM Token;需要 X-App-Timestamp / X-App-Nonce / X-App-Signature
GET /api/im/accounts/{userId} 查询用户资料
PUT /api/im/accounts/{userId} 更新自己的资料
GET /api/im/accounts/search 搜索账号
POST /api/im/accounts/import 导入单个账号
POST /api/im/accounts/import/batch 批量导入账号
DELETE /api/im/accounts/{userId} 删除账号
GET /api/im/accounts/{userId}/exists 检查账号是否存在
GET /api/im/groups/{groupId}/members 查询群成员列表
GET /api/im/groups/{groupId}/members/search 搜索群成员
POST /api/im/messages/send 发送消息TEXT / IMAGE / AUDIO / VIDEO / FILE / LOCATION / CUSTOM / NOTIFY / RICH_TEXT / CALL_AUDIO / CALL_VIDEO / FORWARD / QUOTE / MERGE
GET /api/im/messages/search 云端消息搜索
PUT /api/im/messages/{id} 编辑自己发送的文本消息
POST /api/im/messages/{id}/revoke 撤回消息
GET /api/im/messages/history/{toId} 查询历史消息
WS /ws/im IM Token 建立实时连接

push-service

方法 路径 鉴权 说明
POST /api/push/register 注册设备 token
POST /api/push/receive-push 开启或关闭接收推送
POST /api/push/send 发送推送通知

file-service

方法 路径 鉴权 说明
POST /api/file/upload 文件上传,按 SHA-256 去重,返回 url / hash / originalName
GET /api/file/{hash} 按 hash 获取文件
GET /api/file/{hash}/thumbnail 按 hash 获取缩略图

update-service

方法 路径 鉴权 说明
GET /api/v1/updates/app/check 检查 App 更新
POST /api/v1/updates/app/upload 上传 App 版本,支持即时发布 / 定时发布 / 市场提交配置;Android / iOS 支持 apkUrl(来自 file-service或旧版直传 apkFile,Harmony 版本仅保存市场链接,不提供本地安装包下载
POST /api/v1/updates/app/{id}/publish 发布 App 版本
GET /api/v1/updates/app/list App 版本列表
GET /api/v1/updates/files/apk/{filename} 下载 APK
GET /api/v1/rn/update/check 检查 RN 热更新
POST /api/v1/rn/upload 上传 Bundle
POST /api/v1/rn/{id}/publish 发布 Bundle
GET /api/v1/rn/files/{appId}/{platform}/{moduleId} 下载 Bundle

tenant-service 提供给 update-sdk 的公共配置接口

方法 路径 鉴权 说明
GET /api/sdk/config 发版脚本读取租户级默认配置;appId 可以传 appKeyplatform 用于读取当前平台的 UPDATE 配置

说明:

  • 这里的 appIdappKey 解析;当前 demo 默认使用 ak_demo_chattenant-service 会优先复用数据库里已有的应用,如果没有,会自动补一条默认 demo 应用和基础服务配置。
  • GET /api/sdk/config 主要给 update-sdk 脚本使用,脚本侧建议传 appKey。接口会根据 platform 返回当前平台的 UPDATE 默认配置和开关状态。
  • POST /api/im/auth/login 还要求 demo-service 通过 AppSecret 生成签名头再转发给 IM 服务。
  • 发版上传建议走两段式:先调 POST /api/file/upload 拿到 url,再把这个 url 作为 apkUrl 传给 POST /api/v1/updates/app/uploadPOST /api/v1/updates/app/inspect
  • 如果远程包地址暂时不可读,inspect 会返回 detected=false,发版页可以继续走手动填写 versionName/versionCode 的流程,不会因为解析失败直接中断。

update-sdk 自动发版

三个移动端 SDK 现在都支持通过脚本完成“检查版本 -> 打包 -> 上传 -> 选择发布时间/市场/回调”的流程。

脚本支持的公共参数:

  • xuqm.serverUrl
  • xuqm.tenantUrl
  • xuqm.appKey
  • xuqm.apiToken
  • xuqm.dryRun
  • xuqm.allowVersionMismatch
  • xuqm.publishMode
  • xuqm.publishImmediately
  • xuqm.scheduledPublishAt
  • xuqm.autoPublishAfterReview
  • xuqm.webhookUrl
  • xuqm.forceUpdate
  • xuqm.grayEnabled
  • xuqm.grayPercent
  • xuqm.storeTargets

推荐流程:

  1. 脚本先调用 GET /api/sdk/config?appId=<appKey>&platform=<platform>
  2. 如果服务未开通或配置缺失,则进入 dry-run 或提示补齐配置。
  3. 脚本读取服务器最新版本,和本地版本对比。
  4. 本地版本不高于服务端时,提示用户重新输入版本名 / 版本码。
  5. 让用户确认发布时间、市场提交目标、是否审核通过后自动发布、是否启用灰度、是否使用 webhook。
  6. 完成打包后上传到 update-service,再按配置提交市场或执行发布。

租户平台里的“发版默认配置”标签页保存的就是这组脚本默认值。它按平台分别保存,Android / iOS / Harmony 互不覆盖。

curl 示例

运营平台登录

curl -X POST 'https://dev.xuqinmin.com/api/auth/ops/login' \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"Admin@123456"}'

App 更新检查

curl 'https://dev.xuqinmin.com/api/v1/updates/app/check?appId=ak_demo_chat&platform=ANDROID&currentVersionCode=1'
curl 'https://dev.xuqinmin.com/api/v1/updates/app/check?appId=ak_demo_chat&platform=HARMONY&currentVersionCode=1'

Harmony 平台只跳转应用市场,不提供本地安装包下载。

RN 热更新检查

curl 'https://dev.xuqinmin.com/api/v1/rn/update/check?appId=ak_demo_chat&platform=ANDROID&moduleId=chat-home&currentVersion=1.0.0'

IM 登录

curl -X POST 'https://dev.xuqinmin.com/api/im/auth/login?appId=ak_demo_chat&userId=demo_alice'

返回示例中的 data 会同时包含 tokenexpiresAt,用于客户端提前做静默续签。

Demo IM 刷新

curl -X POST 'https://dev.xuqinmin.com/api/demo/auth/refresh-im?appId=ak_demo_chat' \
  -H 'Authorization: Bearer <demo_jwt>'

该接口会基于 demo 登录态重新签发 IM token,并返回新的 expiresAt

IM 会话与关系链

curl 'https://dev.xuqinmin.com/api/im/accounts/user_001?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/accounts/import?appId=ak_demo_chat' \
  -H 'Content-Type: application/json' \
  -d '{"userId":"user_001","nickname":"Alice"}'
curl -X POST 'https://dev.xuqinmin.com/api/im/accounts/import/batch?appId=ak_demo_chat' \
  -H 'Content-Type: application/json' \
  -d '[{"userId":"user_001"},{"userId":"user_002"}]'
curl -X DELETE 'https://dev.xuqinmin.com/api/im/accounts/user_001?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/accounts/user_001/exists?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/conversations?appId=ak_demo_chat'
curl -X PUT 'https://dev.xuqinmin.com/api/im/conversations/user_002/pinned?appId=ak_demo_chat&chatType=SINGLE&pinned=true'
curl -X PUT 'https://dev.xuqinmin.com/api/im/conversations/user_002/draft?appId=ak_demo_chat&chatType=SINGLE&draft=hello'
curl -X DELETE 'https://dev.xuqinmin.com/api/im/conversations/user_002?appId=ak_demo_chat&chatType=SINGLE'
curl 'https://dev.xuqinmin.com/api/im/groups?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/groups/public?appId=ak_demo_chat&keyword=demo'
curl 'https://dev.xuqinmin.com/api/im/groups/search?appId=ak_demo_chat&keyword=demo&size=20'
curl 'https://dev.xuqinmin.com/api/im/groups/group_001/members?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/groups/group_001/members/search?appId=ak_demo_chat&keyword=demo&size=20'
curl 'https://dev.xuqinmin.com/api/im/messages/search?appId=ak_demo_chat&keyword=hello&page=0&size=20'
curl 'https://dev.xuqinmin.com/api/im/admin/webhooks?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests?appId=ak_demo_chat&remark=申请加入'
curl 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests/req_001/accept?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests/req_001/reject?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/blacklist?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/friend-requests?appId=ak_demo_chat&direction=incoming'

IM 管理后台接口

curl 'https://dev.xuqinmin.com/api/im/admin/users?appId=ak_demo_chat&page=0&size=20'
curl 'https://dev.xuqinmin.com/api/im/admin/groups?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/admin/messages?appId=ak_demo_chat&userA=user_001&userB=user_002&page=0&size=20'
curl 'https://dev.xuqinmin.com/api/im/admin/operation-logs?appId=ak_demo_chat&page=0&size=20'
curl -X POST 'https://dev.xuqinmin.com/api/im/admin/messages/msg_001/revoke?appId=ak_demo_chat'
curl -X DELETE 'https://dev.xuqinmin.com/api/im/admin/groups/group_001'
curl 'https://dev.xuqinmin.com/api/im/admin/friend-requests?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/admin/friend-requests/req_001/accept?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/admin/blacklist?appId=ak_demo_chat' \
  -H 'Content-Type: application/json' \
  -d '{"userId":"user_001","blockedUserId":"user_002"}'
curl 'https://dev.xuqinmin.com/api/im/admin/groups/group_001/members?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/admin/groups/group_001/join-requests?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/admin/groups/group_001/join-requests/req_001/accept?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/admin/keyword-filters?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/admin/global-mute?appId=ak_demo_chat'

IM Webhook 回调

IM 服务会在消息、好友和已读等事件发生后,以 POST 方式向你配置的回调地址推送事件。

请求头:

  • Content-Type: application/json
  • X-App-Id: 应用 appId
  • X-App-Timestamp: 请求时间戳
  • X-App-Nonce: 随机串
  • X-App-Signature: 签名结果

签名规则:

HMAC-SHA256(appSecret, appId + "\n" + timestamp + "\n" + nonce + "\n" + sha256(body))

统一请求体结构:

{
  "callbackId": "uuid",
  "callbackType": "message",
  "callbackEvent": "message.sent",
  "requestTime": 1714360000000,
  "payload": {},
  "signature": null,
  "appId": "ak_demo_chat"
}

字段说明:

字段 说明
callbackId 回调唯一 ID,用于去重和排障
callbackType 回调大类,例如 messagefriendgroupblacklist
callbackEvent 具体事件,例如 message.sentfriend.request.sent
requestTime 毫秒时间戳
payload 事件数据,结构随事件变化
signature 预留字段,当前由请求头承载
appId 回调所属应用 ID

payload 会根据事件类型变化:

事件 payload 类型 说明
message.sent ImMessageEntity 发送消息成功后触发
message.revoked ImMessageEntity 撤回消息后触发
message.edited ImMessageEntity 编辑文本消息后触发
message.read MessageReadCallbackPayload 已读回执同步后触发
friend.request.sent FriendRequestCallbackPayload 好友申请创建后触发
friend.request.accepted FriendRequestCallbackPayload 好友申请通过后触发
friend.request.rejected FriendRequestCallbackPayload 好友申请拒绝后触发
group.join.request.sent GroupJoinRequestCallbackPayload 入群申请创建后触发
group.join.request.accepted GroupJoinRequestCallbackPayload 入群申请通过后触发
group.join.request.rejected GroupJoinRequestCallbackPayload 入群申请拒绝后触发
blacklist.added BlacklistCallbackPayload 黑名单记录新增后触发
blacklist.removed BlacklistCallbackPayload 黑名单记录移除后触发

各 payload 字段如下:

MessageReadCallbackPayload

{
  "appId": "ak_demo_chat",
  "readerId": "user_001",
  "peerId": "user_002",
  "groupId": null,
  "chatType": "SINGLE",
  "readAt": 1714360000000,
  "messageIds": ["msg_001", "msg_002"]
}

FriendRequestCallbackPayload

{
  "appId": "ak_demo_chat",
  "requestId": "req_001",
  "fromUserId": "user_001",
  "toUserId": "user_002",
  "remark": "hi",
  "status": "PENDING",
  "reviewedAt": null
}

GroupJoinRequestCallbackPayload

{
  "appId": "ak_demo_chat",
  "requestId": "req_001",
  "groupId": "group_001",
  "groupName": "技术群",
  "requesterId": "user_003",
  "remark": "申请加入",
  "status": "PENDING",
  "reviewedAt": null
}

BlacklistCallbackPayload

{
  "appId": "ak_demo_chat",
  "id": "blk_001",
  "userId": "user_001",
  "blockedUserId": "user_002",
  "action": "ADD",
  "createdAt": 1714360000000
}

说明:

  • 回调发送失败不会影响主流程,只记录日志。
  • 当前版本的回调配置是按应用维度管理的,多个地址会同时接收同一事件。
  • 新增的好友、入群、黑名单回调都复用同一 envelope 和签名规则,payload 字段按上表中的类型序列化。
  • 接收方建议用 callbackId 做幂等去重,避免重复投递造成重复处理。
  • 服务端当前不做重试队列,失败只会在调用端记录日志。

示例验签:

import crypto from 'crypto'

export function verifyWebhook({
  appId,
  timestamp,
  nonce,
  body,
  signature,
  appSecret,
}: {
  appId: string
  timestamp: string
  nonce: string
  body: string
  signature: string
  appSecret: string
}) {
  const bodyHash = crypto.createHash('sha256').update(body, 'utf8').digest('hex')
  const payload = `${appId}\n${timestamp}\n${nonce}\n${bodyHash}`
  const expected = crypto.createHmac('sha256', appSecret).update(payload, 'utf8').digest('hex')
  return expected === signature
}

好友申请 / 黑名单

curl -X POST 'https://dev.xuqinmin.com/api/im/friend-requests?appId=ak_demo_chat&toUserId=user_002&remark=hi'
curl -X POST 'https://dev.xuqinmin.com/api/im/friend-requests/req_001/accept?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/friend-requests/req_001/reject?appId=ak_demo_chat'
curl 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests?appId=ak_demo_chat&remark=申请加入'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests/req_001/accept?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/groups/group_001/join-requests/req_001/reject?appId=ak_demo_chat'
curl -X POST 'https://dev.xuqinmin.com/api/im/blacklist?appId=ak_demo_chat&blockedUserId=user_002'
curl -X DELETE 'https://dev.xuqinmin.com/api/im/blacklist?appId=ak_demo_chat&blockedUserId=user_002'

IM 历史过滤查询

curl 'https://dev.xuqinmin.com/api/im/messages/history/user_002?appId=ak_demo_chat&page=0&size=20&keyword=hello&msgType=TEXT'
curl 'https://dev.xuqinmin.com/api/im/messages/group-history/group_001?appId=ak_demo_chat&page=0&size=20&keyword=user_002&startTime=2026-04-27T00:00:00&endTime=2026-04-27T23:59:59'

支持的筛选参数:keywordmsgTypestartTimeendTime

IM 媒体消息

curl -X POST 'https://file.dev.xuqinmin.com/api/file/upload' \
  -H 'Authorization: Bearer <im_jwt>' \
  -F 'file=@image.jpg'

curl -X POST 'https://im.dev.xuqinmin.com/api/im/messages/send?appId=ak_demo_chat' \
  -H 'Authorization: Bearer <im_jwt>' \
  -H 'Content-Type: application/json' \
  -d '{"toId":"user_002","chatType":"SINGLE","msgType":"IMAGE","content":"{\"url\":\"https://file.dev.xuqinmin.com/api/file/abc\"}"}'

当前 im-service 的消息发送接口已经支持 AUDIOLOCATIONCUSTOMRICH_TEXTFORWARDQUOTEMERGECALL_AUDIOCALL_VIDEO 这些通用类型,客户端只需按协议传入对应 JSON 内容即可。

群聊消息在历史查询和实时推送里会携带 groupReadCount,用于展示 N 人已读