XuqmGroup-Server/README.md

499 行
11 KiB
Markdown

2026-04-21 22:25:31 +08:00
# XuqmGroup-Server 后端文档
> 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"
}
```
#### 功能服务(需 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-serviceIM 服务)`: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://... (可选)
```
响应:`{ "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=<im_jwt>
```
支持 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` | 设备推送 tokenappId + 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
&currentVersionCode=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`
**上传 APKmultipart/form-data**
```
POST /api/v1/updates/app/upload
appId=ak_xxx
platform=ANDROID
versionName=1.1.0
versionCode=11
changeLog=更新内容
forceUpdate=false
apkFile=<binary>
```
### 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
&currentVersion=1.0.0
```
响应(有更新):
```json
{
"data": {
"needsUpdate": true,
"latestVersion": "1.1.0",
"downloadUrl": "http://...",
"md5": "abc123...",
"minCommonVersion": "1.0.0",
"note": "热更新说明"
}
}
```
**上传 Bundlemultipart/form-data**
```
POST /api/v1/rn/upload
appId=ak_xxx
moduleId=main
platform=ANDROID
version=1.1.0
minCommonVersion=1.0.0
note=修复闪退
bundle=<binary .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}
```