2026-04-24 10:42:11 +08:00
|
|
|
|
# XuqmGroup Server 联调接口文档
|
|
|
|
|
|
|
2026-04-28 09:45:20 +08:00
|
|
|
|
> 最后更新:2026-04-28
|
2026-04-24 10:42:11 +08:00
|
|
|
|
|
|
|
|
|
|
## 线上入口
|
|
|
|
|
|
|
|
|
|
|
|
| 服务 | 地址 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
2026-04-27 17:18:55 +08:00
|
|
|
|
| 租户服务 | `https://dev.xuqinmin.com/api/` | 认证、应用、子账号、运营平台 |
|
|
|
|
|
|
| IM HTTP | `https://dev.xuqinmin.com/api/im/` | IM 登录、消息发送、撤回、历史消息 |
|
|
|
|
|
|
| IM WebSocket | `wss://dev.xuqinmin.com/ws/im` | 实时消息 |
|
2026-04-28 09:45:20 +08:00
|
|
|
|
| 文件服务 | `https://file.dev.xuqinmin.com/api/file/` | 文件上传、下载、缩略图 |
|
2026-04-27 17:18:55 +08:00
|
|
|
|
| App 更新 | `https://dev.xuqinmin.com/api/v1/updates/` | 原生版本管理 |
|
|
|
|
|
|
| RN 热更新 | `https://dev.xuqinmin.com/api/v1/rn/` | Bundle 热更新 |
|
2026-04-24 10:42:11 +08:00
|
|
|
|
|
2026-04-29 12:33:25 +08:00
|
|
|
|
## 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`
|
2026-04-29 16:07:22 +08:00
|
|
|
|
- `tenant-platform` 的“离线推送 / 版本管理”只需要一次开通,平台差异配置在各自的管理页里维护,不再按 Android / iOS / 鸿蒙分别申请开通
|
2026-04-29 12:33:25 +08:00
|
|
|
|
- `im-service` 代码里沿用旧参数名 `appId`,但这是历史命名,调用方传的是 `appKey`
|
|
|
|
|
|
|
2026-04-24 10:42:11 +08:00
|
|
|
|
## 初始化管理员账号
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 值 |
|
|
|
|
|
|
|------|----|
|
|
|
|
|
|
| 用户名 | `admin` |
|
|
|
|
|
|
| 初始密码 | `Admin@123456` |
|
|
|
|
|
|
| 登录接口 | `POST /api/auth/ops/login` |
|
|
|
|
|
|
|
|
|
|
|
|
## 统一响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"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` | 是 | 服务列表 |
|
2026-04-29 17:35:52 +08:00
|
|
|
|
| GET | `/api/apps/{appId}/services/item` | 是 | 按平台和服务类型查询单条服务配置 |
|
|
|
|
|
|
| PUT | `/api/apps/{appId}/services/config` | 是 | 更新服务配置,IM 和 UPDATE 走各自的配置模型 |
|
2026-04-24 10:42:11 +08:00
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 鉴权 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
2026-04-27 23:41:58 +08:00
|
|
|
|
| POST | `/api/im/auth/login` | 否 | 获取 IM Token;需要 `X-App-Timestamp` / `X-App-Nonce` / `X-App-Signature` |
|
2026-04-29 00:34:17 +08:00
|
|
|
|
| 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` | 是 | 搜索群成员 |
|
2026-04-28 09:45:20 +08:00
|
|
|
|
| POST | `/api/im/messages/send` | 是 | 发送消息(TEXT / IMAGE / AUDIO / VIDEO / FILE / LOCATION / CUSTOM / NOTIFY / RICH_TEXT / CALL_AUDIO / CALL_VIDEO / FORWARD / QUOTE / MERGE) |
|
2026-04-29 00:34:17 +08:00
|
|
|
|
| GET | `/api/im/messages/search` | 是 | 云端消息搜索 |
|
|
|
|
|
|
| PUT | `/api/im/messages/{id}` | 是 | 编辑自己发送的文本消息 |
|
2026-04-24 10:42:11 +08:00
|
|
|
|
| POST | `/api/im/messages/{id}/revoke` | 是 | 撤回消息 |
|
|
|
|
|
|
| GET | `/api/im/messages/history/{toId}` | 是 | 查询历史消息 |
|
|
|
|
|
|
| WS | `/ws/im` | IM Token | 建立实时连接 |
|
|
|
|
|
|
|
|
|
|
|
|
### push-service
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 鉴权 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| POST | `/api/push/register` | 是 | 注册设备 token |
|
2026-04-29 12:33:25 +08:00
|
|
|
|
| POST | `/api/push/receive-push` | 是 | 开启或关闭接收推送 |
|
2026-04-24 10:42:11 +08:00
|
|
|
|
| POST | `/api/push/send` | 是 | 发送推送通知 |
|
|
|
|
|
|
|
2026-04-28 09:45:20 +08:00
|
|
|
|
### file-service
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 鉴权 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
2026-04-29 17:35:52 +08:00
|
|
|
|
| POST | `/api/file/upload` | 是 | 文件上传,按 SHA-256 去重,返回 `url` / `hash` / `originalName` |
|
2026-04-28 09:45:20 +08:00
|
|
|
|
| GET | `/api/file/{hash}` | 否 | 按 hash 获取文件 |
|
|
|
|
|
|
| GET | `/api/file/{hash}/thumbnail` | 否 | 按 hash 获取缩略图 |
|
|
|
|
|
|
|
2026-04-24 10:42:11 +08:00
|
|
|
|
### update-service
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 鉴权 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| GET | `/api/v1/updates/app/check` | 否 | 检查 App 更新 |
|
2026-04-29 17:35:52 +08:00
|
|
|
|
| POST | `/api/v1/updates/app/upload` | 是 | 上传 App 版本,支持即时发布 / 定时发布 / 市场提交配置;Android / iOS 支持 `apkUrl`(来自 file-service)或旧版直传 `apkFile`,Harmony 版本仅保存市场链接,不提供本地安装包下载 |
|
2026-04-24 10:42:11 +08:00
|
|
|
|
| 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 |
|
|
|
|
|
|
|
2026-04-29 17:35:52 +08:00
|
|
|
|
### tenant-service 提供给 update-sdk 的公共配置接口
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 鉴权 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| GET | `/api/sdk/config` | 否 | 发版脚本读取租户级默认配置;`appId` 可以传 `appKey`,`platform` 用于读取当前平台的 UPDATE 配置 |
|
|
|
|
|
|
|
|
|
|
|
|
说明:
|
|
|
|
|
|
|
|
|
|
|
|
- 这里的 `appId` 按 `appKey` 解析;当前 demo 默认使用 `ak_demo_chat`,`tenant-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/upload` 和 `POST /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 互不覆盖。
|
2026-04-27 23:41:58 +08:00
|
|
|
|
|
2026-04-24 10:42:11 +08:00
|
|
|
|
## curl 示例
|
|
|
|
|
|
|
|
|
|
|
|
### 运营平台登录
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-04-27 17:18:55 +08:00
|
|
|
|
curl -X POST 'https://dev.xuqinmin.com/api/auth/ops/login' \
|
2026-04-24 10:42:11 +08:00
|
|
|
|
-H 'Content-Type: application/json' \
|
|
|
|
|
|
-d '{"username":"admin","password":"Admin@123456"}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### App 更新检查
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-04-27 17:18:55 +08:00
|
|
|
|
curl 'https://dev.xuqinmin.com/api/v1/updates/app/check?appId=ak_demo_chat&platform=ANDROID¤tVersionCode=1'
|
2026-04-29 15:46:40 +08:00
|
|
|
|
curl 'https://dev.xuqinmin.com/api/v1/updates/app/check?appId=ak_demo_chat&platform=HARMONY¤tVersionCode=1'
|
2026-04-24 10:42:11 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-29 15:46:40 +08:00
|
|
|
|
Harmony 平台只跳转应用市场,不提供本地安装包下载。
|
|
|
|
|
|
|
2026-04-24 10:42:11 +08:00
|
|
|
|
### RN 热更新检查
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-04-27 17:18:55 +08:00
|
|
|
|
curl 'https://dev.xuqinmin.com/api/v1/rn/update/check?appId=ak_demo_chat&platform=ANDROID&moduleId=chat-home¤tVersion=1.0.0'
|
2026-04-24 10:42:11 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### IM 登录
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-04-27 17:18:55 +08:00
|
|
|
|
curl -X POST 'https://dev.xuqinmin.com/api/im/auth/login?appId=ak_demo_chat&userId=demo_alice'
|
2026-04-24 10:42:11 +08:00
|
|
|
|
```
|
2026-04-27 23:41:58 +08:00
|
|
|
|
|
2026-04-28 09:45:20 +08:00
|
|
|
|
返回示例中的 `data` 会同时包含 `token` 和 `expiresAt`,用于客户端提前做静默续签。
|
|
|
|
|
|
|
|
|
|
|
|
### Demo IM 刷新
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
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`。
|
|
|
|
|
|
|
2026-04-27 23:41:58 +08:00
|
|
|
|
### IM 会话与关系链
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-04-29 00:34:17 +08:00
|
|
|
|
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'
|
2026-04-27 23:41:58 +08:00
|
|
|
|
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'
|
2026-04-28 09:45:20 +08:00
|
|
|
|
curl 'https://dev.xuqinmin.com/api/im/groups/public?appId=ak_demo_chat&keyword=demo'
|
2026-04-29 00:34:17 +08:00
|
|
|
|
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'
|
2026-04-28 09:45:20 +08:00
|
|
|
|
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'
|
2026-04-27 23:41:58 +08:00
|
|
|
|
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'
|
|
|
|
|
|
```
|
2026-04-28 09:45:20 +08:00
|
|
|
|
|
|
|
|
|
|
### IM 管理后台接口
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
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'
|
2026-04-29 00:34:17 +08:00
|
|
|
|
curl 'https://dev.xuqinmin.com/api/im/admin/operation-logs?appId=ak_demo_chat&page=0&size=20'
|
2026-04-28 09:45:20 +08:00
|
|
|
|
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'
|
2026-04-29 12:33:25 +08:00
|
|
|
|
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`: 签名结果
|
|
|
|
|
|
|
|
|
|
|
|
签名规则:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
HMAC-SHA256(appSecret, appId + "\n" + timestamp + "\n" + nonce + "\n" + sha256(body))
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
统一请求体结构:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"callbackId": "uuid",
|
|
|
|
|
|
"callbackType": "message",
|
|
|
|
|
|
"callbackEvent": "message.sent",
|
|
|
|
|
|
"requestTime": 1714360000000,
|
|
|
|
|
|
"payload": {},
|
|
|
|
|
|
"signature": null,
|
|
|
|
|
|
"appId": "ak_demo_chat"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
字段说明:
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `callbackId` | 回调唯一 ID,用于去重和排障 |
|
|
|
|
|
|
| `callbackType` | 回调大类,例如 `message`、`friend`、`group`、`blacklist` |
|
|
|
|
|
|
| `callbackEvent` | 具体事件,例如 `message.sent`、`friend.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`
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"appId": "ak_demo_chat",
|
|
|
|
|
|
"readerId": "user_001",
|
|
|
|
|
|
"peerId": "user_002",
|
|
|
|
|
|
"groupId": null,
|
|
|
|
|
|
"chatType": "SINGLE",
|
|
|
|
|
|
"readAt": 1714360000000,
|
|
|
|
|
|
"messageIds": ["msg_001", "msg_002"]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### `FriendRequestCallbackPayload`
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"appId": "ak_demo_chat",
|
|
|
|
|
|
"requestId": "req_001",
|
|
|
|
|
|
"fromUserId": "user_001",
|
|
|
|
|
|
"toUserId": "user_002",
|
|
|
|
|
|
"remark": "hi",
|
|
|
|
|
|
"status": "PENDING",
|
|
|
|
|
|
"reviewedAt": null
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### `GroupJoinRequestCallbackPayload`
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"appId": "ak_demo_chat",
|
|
|
|
|
|
"requestId": "req_001",
|
|
|
|
|
|
"groupId": "group_001",
|
|
|
|
|
|
"groupName": "技术群",
|
|
|
|
|
|
"requesterId": "user_003",
|
|
|
|
|
|
"remark": "申请加入",
|
|
|
|
|
|
"status": "PENDING",
|
|
|
|
|
|
"reviewedAt": null
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### `BlacklistCallbackPayload`
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"appId": "ak_demo_chat",
|
|
|
|
|
|
"id": "blk_001",
|
|
|
|
|
|
"userId": "user_001",
|
|
|
|
|
|
"blockedUserId": "user_002",
|
|
|
|
|
|
"action": "ADD",
|
|
|
|
|
|
"createdAt": 1714360000000
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
说明:
|
|
|
|
|
|
|
|
|
|
|
|
- 回调发送失败不会影响主流程,只记录日志。
|
|
|
|
|
|
- 当前版本的回调配置是按应用维度管理的,多个地址会同时接收同一事件。
|
|
|
|
|
|
- 新增的好友、入群、黑名单回调都复用同一 envelope 和签名规则,payload 字段按上表中的类型序列化。
|
|
|
|
|
|
- 接收方建议用 `callbackId` 做幂等去重,避免重复投递造成重复处理。
|
|
|
|
|
|
- 服务端当前不做重试队列,失败只会在调用端记录日志。
|
|
|
|
|
|
|
|
|
|
|
|
示例验签:
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-04-28 09:45:20 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 好友申请 / 黑名单
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
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'
|
2026-04-29 00:34:17 +08:00
|
|
|
|
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'
|
2026-04-28 09:45:20 +08:00
|
|
|
|
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 历史过滤查询
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
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'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
支持的筛选参数:`keyword`、`msgType`、`startTime`、`endTime`。
|
|
|
|
|
|
|
|
|
|
|
|
### IM 媒体消息
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
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` 的消息发送接口已经支持 `AUDIO`、`LOCATION`、`CUSTOM`、`RICH_TEXT`、`FORWARD`、`QUOTE`、`MERGE`、`CALL_AUDIO`、`CALL_VIDEO` 这些通用类型,客户端只需按协议传入对应 JSON 内容即可。
|
|
|
|
|
|
|
|
|
|
|
|
群聊消息在历史查询和实时推送里会携带 `groupReadCount`,用于展示 `N 人已读`。
|