# XuqmGroup-Server 后端文档 > 当前推荐阅读入口:[`/docs/server/README.md`](../docs/server/README.md) > 仓库内联调文档:[`docs/API_ACCESS.md`](./docs/API_ACCESS.md) > 该文档保留为仓库内说明,线上地址、初始化账号与最新联调接口请以最新文档为准。 > Spring Boot 3.4.4 · Java 21 · Maven 多模块 ## 模块结构 ``` XuqmGroup-Server/ ├── pom.xml # 父 POM,统一依赖版本 ├── common/ # 公共库(ApiResponse、JWT、异常处理) ├── tenant-service/ # 租户服务 :8081 ├── im-service/ # IM 服务 :8082 ├── push-service/ # 推送服务 :8083 └── update-service/ # 版本管理服务 :8084 ``` ## 技术栈 | 组件 | 版本 | |------|------| | Spring Boot | 3.4.4 | | Java | 21 | | Spring Security 6 | JWT 无状态认证 | | Spring Data JPA | Hibernate 6,ddl-auto: update | | MySQL | 8.x | | Redis | 7.x(验证码、子账号会话) | | JJWT | 0.12.6,HMAC-SHA256 | | Spring Mail | 邮件验证码 | | Spring WebSocket + STOMP | IM 实时通信 | ## 快速启动 ```bash # 前置:MySQL 8 + Redis 7 本地运行 cd XuqmGroup-Server # 启动所有服务(各模块独立启动) cd tenant-service && mvn spring-boot:run & cd im-service && mvn spring-boot:run & cd push-service && mvn spring-boot:run & cd update-service && mvn spring-boot:run & ``` 首次启动会自动建表(ddl-auto: update)。 运营平台默认管理员:`admin` / `Admin@123456`(可通过 `ops.admin.*` 配置覆盖)。 --- ## tenant-service(租户服务)`:8081` ### 数据库表 | 表名 | 说明 | |------|------| | `t_tenant` | 租户主账号 & 子账号 | | `t_app` | 应用 | | `t_feature_service` | 功能服务(IM/推送/版本管理) | | `t_email_verification` | 邮箱验证码 | | `t_ops_admin` | 运营平台管理员 | ### 接口列表 #### 认证(无需 Token) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/auth/captcha` | 获取图形验证码 | | POST | `/api/auth/send-email-code?email=&purpose=` | 发送邮箱验证码(purpose: REGISTER / FORGOT_PASSWORD / SUB_ACCOUNT) | | POST | `/api/auth/register` | 注册主账号 | | POST | `/api/auth/login` | 登录,返回 JWT | | POST | `/api/auth/forgot-password?email=` | 发送重置密码邮件 | | POST | `/api/auth/reset-password?email=&code=&newPassword=` | 重置密码 | **注册请求体** ```json { "username": "demo", "password": "Demo@123456", "email": "demo@example.com", "nickname": "Demo", "emailCode": "AB3K" } ``` **登录请求体** ```json { "account": "demo", "password": "Demo@123456", "captchaKey": "uuid-from-captcha-api", "captchaCode": "XK2P" } ``` **登录响应** ```json { "code": 200, "status": "0", "data": { "token": "eyJ..." }, "message": "success" } ``` #### 应用管理(需 Token) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/apps` | 查询当前租户的应用列表 | | GET | `/api/apps/{id}` | 查询应用详情 | | POST | `/api/apps` | 创建应用 | | PUT | `/api/apps/{id}` | 更新应用信息 | | DELETE | `/api/apps/{id}` | 删除应用 | **创建应用请求体** ```json { "name": "我的App", "packageName": "com.example.myapp", "description": "描述", "iconUrl": "https://cdn.example.com/icon.png" } ``` **应用对象(响应)** ```json { "id": "uuid", "tenantId": "uuid", "name": "我的App", "packageName": "com.example.myapp", "appKey": "ak_xxxxxxxx", "appSecret": "as_xxxxxxxx", "createdAt": "2026-04-21T00:00:00" } ``` > 说明:SDK 和 demo 侧传入的 `appId` 实际按 `appKey` 解析。当前默认值是 `ak_demo_chat`,如果数据库里没有这条记录,tenant-service 会在启动时自动创建。 #### 功能服务(需 Token) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/apps/{appId}/services` | 获取应用下所有功能服务 | | POST | `/api/apps/{appId}/services/toggle?platform=&serviceType=&enable=` | 开启/关闭功能服务 | | POST | `/api/apps/{appId}/services/{id}/regenerate-key` | 重新生成 secretKey | **platform 枚举**:`ANDROID` / `IOS` / `HARMONY` **serviceType 枚举**:`IM` / `PUSH` / `UPDATE` #### 子账号(需 Token) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/sub-accounts` | 查询子账号列表 | | POST | `/api/sub-accounts/send-verify-code?email=` | 发送邮箱验证码(24h 内有效一次) | | POST | `/api/sub-accounts/verify-email?email=&code=` | 验证邮箱(通过后 24h 内可创建) | | POST | `/api/sub-accounts` | 创建子账号(需先验证邮箱) | | DELETE | `/api/sub-accounts/{id}` | 禁用子账号 | | GET | `/api/sub-accounts/generate-password` | 生成随机密码 | **创建子账号请求体** ```json { "username": "sub_user", "password": "Sub@123456", "email": "sub@example.com", "nickname": "子账号" } ``` #### 运营平台(需 OPS Token) | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/auth/ops/login` | 运营平台登录 | | GET | `/api/ops/tenants?keyword=&page=&size=` | 分页查询租户 | | POST | `/api/ops/tenants/{id}/toggle-status` | 启用/禁用租户 | | GET | `/api/ops/statistics` | 获取统计数据 | **运营登录请求体** ```json { "username": "admin", "password": "Admin@123456" } ``` **统计响应** ```json { "data": { "totalTenants": 128, "todayNew": 5, "activeApps": 42, "onlineUsers": 0 } } ``` --- ## im-service(IM 服务)`:8082` ### 数据库表 | 表名 | 说明 | |------|------| | `im_account` | IM 用户账号(仅存 userId,不含昵称/头像) | | `im_group` | 群组(memberIds、adminIds 为逗号分隔字符串) | | `im_message` | 消息记录 | | `im_keyword_filter` | 关键词过滤规则 | | `im_webhook_config` | Webhook 配置 | ### IM 账号登录 ``` POST /api/im/auth/login ?appId=ak_xxx &userId=user_001 &nickname=张三 (可选,仅首次注册时存入外部系统) &avatar=https://... (可选) ``` 该接口需要由 demo-service 带上 `X-App-Timestamp`、`X-App-Nonce`、`X-App-Signature` 头完成 AppSecret 验签。 响应:`{ "data": { "token": "eyJ..." } }` ### HTTP 消息接口 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/im/messages/send?appId=` | 发送消息 | | POST | `/api/im/messages/{id}/revoke?appId=` | 撤回消息 | | GET | `/api/im/messages/history/{toId}?appId=&page=&size=` | 查询历史消息 | **发送消息请求体** ```json { "toId": "user_002", "chatType": "SINGLE", "msgType": "TEXT", "content": "Hello!", "mentionedUserIds": "" } ``` **消息类型(MsgType)** | 值 | 说明 | |----|------| | TEXT | 文本(支持表情 Unicode / 自定义表情 ID) | | IMAGE | 图片(content 为 URL) | | VIDEO | 视频 | | AUDIO | 语音 | | FILE | 文件 | | CUSTOM | 自定义(content 为 JSON 字符串) | | LOCATION | 位置(content 为 `{"lat":x,"lng":y,"address":"..."}`) | | NOTIFY | 系统通知 | | RICH_TEXT | 图文混排 | | CALL_AUDIO | 音频通话信令 | | CALL_VIDEO | 视频通话信令 | | FORWARD | 转发(content 为原消息 JSON) | | REVOKED | 已撤回(系统占位,不可主动发送) | ### WebSocket 实时通信 **连接** ``` ws://localhost:8082/ws/im?token= ``` 支持 STOMP 协议(可直接使用原生 WebSocket 发 JSON frame)。 **发送消息(客户端 → 服务端)** ```json { "destination": "/app/chat.send", "payload": { "appId": "ak_xxx", "toId": "user_002", "chatType": "SINGLE", "msgType": "TEXT", "content": "Hello!" } } ``` **接收消息(服务端 → 客户端)** - 单聊推送至:`/user/{userId}/queue/messages` - 群聊推送至:`/topic/group/{groupId}` Frame 格式: ```json { "type": "MESSAGE", "payload": { "id": "uuid", "fromId": "user_001", "toId": "user_002", "chatType": "SINGLE", "msgType": "TEXT", "content": "Hello!", "revoked": false, "createdAt": "2026-04-21T10:00:00" } } ``` **撤回消息(客户端 → 服务端)** ```json { "destination": "/app/chat.revoke", "payload": { "appId": "ak_xxx", "messageId": "msg-uuid" } } ``` **撤回推送(服务端 → 客户端)** ```json { "type": "REVOKE", "payload": { "msgId": "msg-uuid", "operatorId": "user_001" } } ``` ### 关键词过滤 在 `im_keyword_filter` 表中配置,支持 `REPLACE`(替换为 `*`)和 `BLOCK`(拒绝发送)两种动作,pattern 为正则表达式。 ### Webhook 在 `im_webhook_config` 表中为 App 配置 URL,消息发送后异步 HTTP POST 通知,超时 3000ms,格式: ```json { "event": "message", "appId": "ak_xxx", "message": { ...消息对象... } } ``` --- ## push-service(推送服务)`:8083` ### 数据库表 | 表名 | 说明 | |------|------| | `push_device_token` | 设备推送 token(appId + userId + vendor 唯一) | ### 支持厂商 `HUAWEI` / `XIAOMI` / `OPPO` / `VIVO` / `HONOR` / `APNS`(iOS)/ `FCM` ### 接口 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/push/register` | 注册设备 token | | POST | `/api/push/send` | 向指定用户推送通知 | **注册 token** ``` POST /api/push/register ?appId=ak_xxx &userId=user_001 &vendor=HUAWEI &token=device_push_token ``` **发送推送** ``` POST /api/push/send ?appId=ak_xxx &userId=user_001 &title=新消息 &body=张三: Hello! &payload={"type":"IM","msgId":"uuid"} ``` ### 环境变量配置 ```yaml push: huawei: app-id: ${HUAWEI_APP_ID} app-secret: ${HUAWEI_APP_SECRET} xiaomi: app-secret: ${XIAOMI_APP_SECRET} apns: key-id: ${APNS_KEY_ID} team-id: ${APNS_TEAM_ID} key-path: ${APNS_KEY_PATH} # .p8 文件路径 bundle-id: ${APNS_BUNDLE_ID} production: false # true = 生产环境 ``` --- ## update-service(版本管理服务)`:8084` ### 数据库表 | 表名 | 说明 | |------|------| | `app_version` | 原生 App 版本(Android APK / iOS 跳转链接) | | `rn_bundle` | RN Bundle 版本 | ### App 版本管理 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/updates/app/check` | 检查更新 | | POST | `/api/v1/updates/app/upload` | 上传版本(APK 文件 multipart) | | POST | `/api/v1/updates/app/{id}/publish` | 发布版本 | | GET | `/api/v1/updates/app/list` | 版本列表 | **检查更新** ``` GET /api/v1/updates/app/check ?appId=ak_xxx &platform=ANDROID ¤tVersionCode=10 ``` 响应(有更新): ```json { "data": { "needsUpdate": true, "versionName": "1.1.0", "versionCode": 11, "downloadUrl": "http://update.xuqm.com/files/apk/xxx.apk", "changeLog": "修复若干问题", "forceUpdate": false, "appStoreUrl": "", "marketUrl": "" } } ``` **platform 枚举**:`ANDROID` / `IOS` / `HARMONY` **上传 APK(multipart/form-data)** ``` POST /api/v1/updates/app/upload appId=ak_xxx platform=ANDROID versionName=1.1.0 versionCode=11 changeLog=更新内容 forceUpdate=false apkFile= ``` ### RN Bundle 管理 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/rn/update/check` | 检查 RN Bundle 更新 | | POST | `/api/v1/rn/upload` | 上传 Bundle 文件 | | POST | `/api/v1/rn/{id}/publish` | 发布 Bundle | **检查 RN 更新** ``` GET /api/v1/rn/update/check ?appId=ak_xxx &moduleId=main &platform=android ¤tVersion=1.0.0 ``` 响应(有更新): ```json { "data": { "needsUpdate": true, "latestVersion": "1.1.0", "downloadUrl": "http://...", "md5": "abc123...", "minCommonVersion": "1.0.0", "note": "热更新说明" } } ``` **上传 Bundle(multipart/form-data)** ``` POST /api/v1/rn/upload appId=ak_xxx moduleId=main platform=ANDROID version=1.1.0 minCommonVersion=1.0.0 note=修复闪退 bundle= ``` 服务端自动计算 MD5,存储至 `{upload-dir}/rn/{appId}/{platform}/{moduleId}/`。 ### 环境变量配置 ```yaml update: upload-dir: ${UPDATE_UPLOAD_DIR:/tmp/xuqm-update} base-url: ${UPDATE_BASE_URL:http://localhost:8084} ```