XuqmGroup-Server/docs/API_ACCESS.md
XuqmGroup d7f5fd02c2 docs(server): 添加服务器信息记录和联调接口文档
- 创建信息记录文档,包含项目管理要求、产物范围、Git仓库、制品仓库信息
- 添加服务器部署信息,包括应用服务器、MySQL/Redis服务器、Jenkins服务配置
- 记录邮件服务、DNS/HTTPS证书配置及安全备注
- 创建API联调文档,包含线上入口、ID约定、初始化管理员账号信息
- 添加统一响应格式、常见错误码、鉴权规则说明
- 提供核心接口清单,涵盖tenant-service、im-service、push-service等服务
- 补充curl示例,包含运营平台登录、IM登录、会话管理等操作示例
- 实现会话控制器,支持置顶、免打扰、标记已读、草稿等功能
- 添加全局异常处理器,统一处理业务异常和参数校验错误
- 创建IM管理控制器,提供用户管理、好友请求、黑名单等管理功能
2026-04-29 12:33:25 +08:00

17 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
  • 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 服务列表
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 去重
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 版本
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

说明:这里的 appIdappKey 解析。当前 demo 默认使用 ak_demo_chattenant-service 会优先复用数据库里已有的应用;如果没有,会自动补一条默认 demo 应用和基础服务配置。POST /api/im/auth/login 还要求 demo-service 通过 AppSecret 生成签名头再转发给 IM 服务。

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'

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 人已读