rwadurian/backend/services/admin-service/docs/API.md

911 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Admin Service API 文档
## 目录
- [1. API 概述](#1-api-概述)
- [2. 认证](#2-认证)
- [3. 通用响应格式](#3-通用响应格式)
- [4. 错误处理](#4-错误处理)
- [5. API 端点](#5-api-端点)
- [6. 数据模型](#6-数据模型)
- [7. 使用示例](#7-使用示例)
---
## 1. API 概述
### 1.1 基本信息
| 项目 | 值 |
|-----|---|
| **Base URL** | `http://localhost:3005/api/v1` |
| **协议** | HTTP/HTTPS |
| **数据格式** | JSON |
| **字符编码** | UTF-8 |
| **API 版本** | v1 |
### 1.2 API 分类
| 分类 | 端点数 | 说明 |
|-----|-------|------|
| 版本管理 | 5 | 创建、启用、禁用、查询版本 |
| 版本检查 | 1 | 移动端检查更新 |
---
## 2. 认证
### 2.1 认证方式 (待实现)
当前版本 API **未实现认证机制**,生产环境需要添加 JWT 认证。
**计划认证方案**:
```http
Authorization: Bearer <JWT_TOKEN>
```
**获取 Token** (待实现):
```http
POST /api/v1/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password123"
}
```
**响应**:
```json
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 7200
}
```
### 2.2 权限级别 (待实现)
| 角色 | 权限 |
|-----|------|
| **admin** | 完全权限:创建、启用、禁用、删除版本 |
| **developer** | 创建、查询版本 |
| **public** | 仅检查更新 (无需认证) |
---
## 3. 通用响应格式
### 3.1 成功响应
**200 OK** - 查询成功:
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "1",
"downloadUrl": "https://cdn.example.com/app-v1.0.0.apk",
"fileSize": 52428800,
"fileSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"changelog": "Initial release",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin",
"createdAt": "2025-01-02T10:00:00.000Z",
"updatedBy": "admin",
"updatedAt": "2025-01-02T10:00:00.000Z"
}
```
**201 Created** - 创建成功:
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"platform": "android",
"versionCode": 101,
...
}
```
**204 No Content** - 操作成功无返回内容
### 3.2 分页响应 (待实现)
```json
{
"data": [...],
"meta": {
"total": 50,
"page": 1,
"pageSize": 10,
"totalPages": 5
}
}
```
---
## 4. 错误处理
### 4.1 错误响应格式
```json
{
"statusCode": 400,
"message": "Invalid version code",
"error": "Bad Request",
"timestamp": "2025-01-02T10:00:00.000Z",
"path": "/api/v1/version"
}
```
### 4.2 HTTP 状态码
| 状态码 | 说明 | 常见场景 |
|-------|------|---------|
| **200** | 成功 | 查询成功 |
| **201** | 已创建 | 创建版本成功 |
| **204** | 无内容 | 启用/禁用成功 |
| **400** | 请求错误 | 参数验证失败 |
| **401** | 未认证 | Token 缺失或无效 |
| **403** | 禁止访问 | 权限不足 |
| **404** | 未找到 | 版本不存在 |
| **409** | 冲突 | 版本号重复 |
| **500** | 服务器错误 | 内部异常 |
### 4.3 业务错误码 (待实现)
| 错误码 | 说明 |
|-------|------|
| `VERSION_ALREADY_EXISTS` | 版本已存在 |
| `INVALID_VERSION_CODE` | 版本号格式错误 |
| `INVALID_VERSION_NAME` | 版本名称格式错误 |
| `INVALID_SHA256` | SHA256 格式错误 |
| `VERSION_NOT_FOUND` | 版本不存在 |
| `FILE_SIZE_INVALID` | 文件大小无效 |
---
## 5. API 端点
### 5.1 创建版本
**端点**: `POST /api/v1/version`
**权限**: 需要认证 (待实现)
**请求体**:
```json
{
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "1",
"downloadUrl": "https://cdn.example.com/app-v1.0.0.apk",
"fileSize": 52428800,
"fileSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"changelog": "Initial release",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin"
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 | 验证规则 |
|-----|------|-----|------|---------|
| `platform` | string | ✅ | 平台 | `android``ios` |
| `versionCode` | number | ✅ | 版本号 | 正整数 |
| `versionName` | string | ✅ | 版本名称 | 语义化版本 (x.y.z) |
| `buildNumber` | string | ✅ | 构建号 | 非空字符串 |
| `downloadUrl` | string | ✅ | 下载链接 | 有效 URL |
| `fileSize` | number | ✅ | 文件大小 (字节) | > 0 |
| `fileSha256` | string | ✅ | SHA256 哈希 | 64 位十六进制 |
| `changelog` | string | ✅ | 更新日志 | 非空字符串 |
| `isEnabled` | boolean | ❌ | 是否启用 | 默认 `true` |
| `isForceUpdate` | boolean | ❌ | 是否强制更新 | 默认 `false` |
| `createdBy` | string | ✅ | 创建者 | 非空字符串 |
**响应**: `201 Created`
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "1",
"downloadUrl": "https://cdn.example.com/app-v1.0.0.apk",
"fileSize": 52428800,
"fileSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"changelog": "Initial release",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin",
"createdAt": "2025-01-02T10:00:00.000Z",
"updatedBy": "admin",
"updatedAt": "2025-01-02T10:00:00.000Z"
}
```
**错误响应**:
```json
// 400 Bad Request - 版本号无效
{
"statusCode": 400,
"message": "Version code must be a positive integer",
"error": "Bad Request"
}
// 409 Conflict - 版本已存在
{
"statusCode": 409,
"message": "Version already exists for this platform",
"error": "Conflict"
}
```
**cURL 示例**:
```bash
curl -X POST http://localhost:3005/api/v1/version \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "1",
"downloadUrl": "https://cdn.example.com/app-v1.0.0.apk",
"fileSize": 52428800,
"fileSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"changelog": "Initial release",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin"
}'
```
---
### 5.2 查询所有版本
**端点**: `GET /api/v1/version`
**权限**: 需要认证 (待实现)
**查询参数**:
| 参数 | 类型 | 必填 | 说明 | 示例 |
|-----|------|-----|------|------|
| `platform` | string | ❌ | 过滤平台 | `android` |
| `isEnabled` | boolean | ❌ | 过滤启用状态 | `true` |
| `page` | number | ❌ | 页码 (待实现) | `1` |
| `pageSize` | number | ❌ | 每页数量 (待实现) | `10` |
**请求示例**:
```http
GET /api/v1/version?platform=android&isEnabled=true
```
**响应**: `200 OK`
```json
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"platform": "android",
"versionCode": 101,
"versionName": "1.0.1",
...
},
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
...
}
]
```
**cURL 示例**:
```bash
curl -X GET "http://localhost:3005/api/v1/version?platform=android&isEnabled=true"
```
---
### 5.3 查询单个版本
**端点**: `GET /api/v1/version/:id`
**权限**: 需要认证 (待实现)
**路径参数**:
| 参数 | 类型 | 说明 |
|-----|------|------|
| `id` | string (UUID) | 版本 ID |
**请求示例**:
```http
GET /api/v1/version/550e8400-e29b-41d4-a716-446655440000
```
**响应**: `200 OK`
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"platform": "android",
"versionCode": 100,
"versionName": "1.0.0",
...
}
```
**错误响应**:
```json
// 404 Not Found
{
"statusCode": 404,
"message": "Version not found",
"error": "Not Found"
}
```
**cURL 示例**:
```bash
curl -X GET http://localhost:3005/api/v1/version/550e8400-e29b-41d4-a716-446655440000
```
---
### 5.4 启用版本
**端点**: `PATCH /api/v1/version/:id/enable`
**权限**: 需要认证 (待实现)
**路径参数**:
| 参数 | 类型 | 说明 |
|-----|------|------|
| `id` | string (UUID) | 版本 ID |
**请求体**:
```json
{
"updatedBy": "admin"
}
```
**请求示例**:
```http
PATCH /api/v1/version/550e8400-e29b-41d4-a716-446655440000/enable
Content-Type: application/json
{
"updatedBy": "admin"
}
```
**响应**: `204 No Content`
**错误响应**:
```json
// 404 Not Found
{
"statusCode": 404,
"message": "Version not found",
"error": "Not Found"
}
```
**cURL 示例**:
```bash
curl -X PATCH http://localhost:3005/api/v1/version/550e8400-e29b-41d4-a716-446655440000/enable \
-H "Content-Type: application/json" \
-d '{"updatedBy": "admin"}'
```
---
### 5.5 禁用版本
**端点**: `PATCH /api/v1/version/:id/disable`
**权限**: 需要认证 (待实现)
**路径参数**:
| 参数 | 类型 | 说明 |
|-----|------|------|
| `id` | string (UUID) | 版本 ID |
**请求体**:
```json
{
"updatedBy": "admin"
}
```
**请求示例**:
```http
PATCH /api/v1/version/550e8400-e29b-41d4-a716-446655440000/disable
Content-Type: application/json
{
"updatedBy": "admin"
}
```
**响应**: `204 No Content`
**业务逻辑**:
- 禁用版本时,会自动将 `isForceUpdate` 设置为 `false`
- 禁用后的版本不会出现在 "检查更新" 结果中
**cURL 示例**:
```bash
curl -X PATCH http://localhost:3005/api/v1/version/550e8400-e29b-41d4-a716-446655440000/disable \
-H "Content-Type: application/json" \
-d '{"updatedBy": "admin"}'
```
---
### 5.6 检查更新 (移动端)
**端点**: `GET /api/v1/version/check`
**权限**: 公开 (无需认证)
**查询参数**:
| 参数 | 类型 | 必填 | 说明 | 示例 |
|-----|------|-----|------|------|
| `platform` | string | ✅ | 平台 | `android` |
| `versionCode` | number | ✅ | 当前版本号 | `100` |
**请求示例**:
```http
GET /api/v1/version/check?platform=android&versionCode=100
```
**响应 1**: `200 OK` - 有更新
```json
{
"hasUpdate": true,
"latestVersion": "1.0.1",
"downloadUrl": "https://cdn.example.com/app-v1.0.1.apk",
"isForceUpdate": false,
"changelog": "Bug fixes and performance improvements"
}
```
**响应 2**: `200 OK` - 无更新
```json
{
"hasUpdate": false
}
```
**响应 3**: `200 OK` - 强制更新
```json
{
"hasUpdate": true,
"latestVersion": "2.0.0",
"downloadUrl": "https://cdn.example.com/app-v2.0.0.apk",
"isForceUpdate": true,
"changelog": "Major security update. Please update immediately!"
}
```
**错误响应**:
```json
// 400 Bad Request - 参数缺失
{
"statusCode": 400,
"message": ["platform should not be empty", "versionCode must be a number"],
"error": "Bad Request"
}
```
**业务逻辑**:
1. 查询指定平台的所有启用版本 (`isEnabled = true`)
2.`versionCode` 降序排序,取第一个作为最新版本
3. 如果最新版本的 `versionCode` > 当前版本号,返回更新信息
4. 否则返回 `hasUpdate: false`
**移动端处理逻辑**:
```typescript
// Flutter 示例
async function checkForUpdate() {
const response = await fetch(
`${API_BASE}/version/check?platform=android&versionCode=100`
);
const data = await response.json();
if (data.hasUpdate) {
if (data.isForceUpdate) {
// 显示强制更新对话框(无法关闭)
showForceUpdateDialog({
version: data.latestVersion,
downloadUrl: data.downloadUrl,
changelog: data.changelog,
});
} else {
// 显示普通更新对话框(可以关闭)
showUpdateDialog({
version: data.latestVersion,
downloadUrl: data.downloadUrl,
changelog: data.changelog,
});
}
}
}
```
**cURL 示例**:
```bash
curl -X GET "http://localhost:3005/api/v1/version/check?platform=android&versionCode=100"
```
---
## 6. 数据模型
### 6.1 AppVersion (应用版本)
```typescript
interface AppVersion {
id: string; // UUID
platform: 'android' | 'ios';// 平台
versionCode: number; // 版本号(整数)
versionName: string; // 版本名称x.y.z
buildNumber: string; // 构建号
downloadUrl: string; // 下载链接
fileSize: number; // 文件大小(字节)
fileSha256: string; // SHA256 哈希
changelog: string; // 更新日志
isEnabled: boolean; // 是否启用
isForceUpdate: boolean; // 是否强制更新
createdBy: string; // 创建者
createdAt: string; // 创建时间ISO 8601
updatedBy: string; // 更新者
updatedAt: string; // 更新时间ISO 8601
}
```
### 6.2 Platform (平台枚举)
```typescript
enum Platform {
ANDROID = 'android',
IOS = 'ios',
}
```
### 6.3 VersionCheckResult (版本检查结果)
```typescript
interface VersionCheckResult {
hasUpdate: boolean; // 是否有更新
latestVersion?: string; // 最新版本名称
downloadUrl?: string; // 下载链接
isForceUpdate?: boolean; // 是否强制更新
changelog?: string; // 更新日志
}
```
---
## 7. 使用示例
### 7.1 完整发版流程
#### 步骤 1: 创建 Android 新版本
```bash
curl -X POST http://localhost:3005/api/v1/version \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"versionCode": 101,
"versionName": "1.0.1",
"buildNumber": "20250102001",
"downloadUrl": "https://cdn.rwadurian.com/android/app-v1.0.1.apk",
"fileSize": 54525952,
"fileSha256": "a3c5d7e9f1b2c4d6e8f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2",
"changelog": "1. Fixed mining reward calculation bug\n2. Improved UI performance\n3. Added dark mode support",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin"
}'
```
#### 步骤 2: 验证版本已创建
```bash
curl -X GET "http://localhost:3005/api/v1/version?platform=android&isEnabled=true"
```
#### 步骤 3: 移动端检查更新
```bash
# 用户当前版本号 100
curl -X GET "http://localhost:3005/api/v1/version/check?platform=android&versionCode=100"
# 响应:
{
"hasUpdate": true,
"latestVersion": "1.0.1",
"downloadUrl": "https://cdn.rwadurian.com/android/app-v1.0.1.apk",
"isForceUpdate": false,
"changelog": "1. Fixed mining reward calculation bug\n2. Improved UI performance\n3. Added dark mode support"
}
```
#### 步骤 4: 发现问题,紧急禁用版本
```bash
curl -X PATCH http://localhost:3005/api/v1/version/550e8400-e29b-41d4-a716-446655440001/disable \
-H "Content-Type: application/json" \
-d '{"updatedBy": "admin"}'
```
#### 步骤 5: 创建修复版本
```bash
curl -X POST http://localhost:3005/api/v1/version \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"versionCode": 102,
"versionName": "1.0.2",
"buildNumber": "20250102002",
"downloadUrl": "https://cdn.rwadurian.com/android/app-v1.0.2.apk",
"fileSize": 54530048,
"fileSha256": "b4d6e8f0a2c3d5e7f9a1b3c4d6e8f0a2b3c5d7e9f1a2b4c6d8e0f1a3b5c7d9e1",
"changelog": "Hotfix: Fixed critical security vulnerability",
"isEnabled": true,
"isForceUpdate": true,
"createdBy": "admin"
}'
```
### 7.2 iOS 版本发布
```bash
curl -X POST http://localhost:3005/api/v1/version \
-H "Content-Type: application/json" \
-d '{
"platform": "ios",
"versionCode": 1,
"versionName": "1.0.0",
"buildNumber": "1",
"downloadUrl": "https://apps.apple.com/app/rwa-durian/id123456789",
"fileSize": 67108864,
"fileSha256": "c5e7f9a1b3c4d6e8f0a2b3c5d7e9f1a2b4c6d8e0f1a3b5c7d9e1f2a4b6c8d0e2",
"changelog": "Initial iOS release",
"isEnabled": true,
"isForceUpdate": false,
"createdBy": "admin"
}'
```
### 7.3 Postman Collection (部分示例)
```json
{
"info": {
"name": "Admin Service API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Create Android Version",
"request": {
"method": "POST",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {
"mode": "raw",
"raw": "{\n \"platform\": \"android\",\n \"versionCode\": 100,\n \"versionName\": \"1.0.0\",\n \"buildNumber\": \"1\",\n \"downloadUrl\": \"https://cdn.example.com/app-v1.0.0.apk\",\n \"fileSize\": 52428800,\n \"fileSha256\": \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n \"changelog\": \"Initial release\",\n \"isEnabled\": true,\n \"isForceUpdate\": false,\n \"createdBy\": \"admin\"\n}"
},
"url": {
"raw": "http://localhost:3005/api/v1/version",
"protocol": "http",
"host": ["localhost"],
"port": "3005",
"path": ["api", "v1", "version"]
}
}
},
{
"name": "Check For Update",
"request": {
"method": "GET",
"url": {
"raw": "http://localhost:3005/api/v1/version/check?platform=android&versionCode=100",
"protocol": "http",
"host": ["localhost"],
"port": "3005",
"path": ["api", "v1", "version", "check"],
"query": [
{"key": "platform", "value": "android"},
{"key": "versionCode", "value": "100"}
]
}
}
}
]
}
```
---
## 8. 版本控制策略
### 8.1 版本号规则
**VersionCode** (数字版本号):
- 每次发布递增 1
- Android: 从 1 开始
- iOS: 从 1 开始
- 用于版本比较 (机器识别)
**VersionName** (语义化版本):
- 格式: `MAJOR.MINOR.PATCH` (例如: `1.2.3`)
- 用于用户展示 (人类可读)
**BuildNumber** (构建号):
- 格式: 自定义 (建议: `YYYYMMDDXXX`)
- 例如: `20250102001` = 2025年1月2日第1次构建
### 8.2 更新策略
| 场景 | isForceUpdate | 说明 |
|-----|---------------|------|
| 功能更新 | `false` | 用户可选择更新时机 |
| Bug 修复 | `false` | 建议更新,但不强制 |
| 安全漏洞 | `true` | 必须更新才能继续使用 |
| API 破坏性变更 | `true` | 旧版本无法正常工作 |
---
## 9. 最佳实践
### 9.1 文件托管建议
1. **使用 CDN**: 加速全球用户下载
2. **HTTPS**: 确保传输安全
3. **文件命名**: `app-{platform}-v{versionName}.{ext}`
- Android: `app-android-v1.0.0.apk`
- iOS: `app-ios-v1.0.0.ipa`
### 9.2 SHA256 校验流程
**服务端计算** (发版时):
```bash
# Linux/macOS
sha256sum app-android-v1.0.0.apk
# Windows
certutil -hashfile app-android-v1.0.0.apk SHA256
```
**移动端校验** (下载后):
```dart
// Flutter 示例
import 'package:crypto/crypto.dart';
import 'dart:io';
Future<bool> verifyApkIntegrity(String filePath, String expectedSha256) async {
final file = File(filePath);
final bytes = await file.readAsBytes();
final digest = sha256.convert(bytes);
return digest.toString() == expectedSha256.toLowerCase();
}
// 使用
final isValid = await verifyApkIntegrity(
'/storage/emulated/0/Download/app.apk',
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
);
if (!isValid) {
throw Exception('File integrity check failed! Possible tampering detected.');
}
```
### 9.3 更新日志编写规范
**推荐格式**:
```
1. 新功能:添加暗黑模式支持
2. 优化:挖矿页面性能提升 30%
3. 修复:交易历史加载失败问题
4. 安全:修复账户导入漏洞
```
**避免**:
- ❌ "Bug fixes and improvements" (太笼统)
- ❌ 技术术语 (普通用户不理解)
- ✅ 简洁明了,面向用户
---
## 10. 常见问题
### Q1: 如何回滚版本?
**方案 1**: 禁用问题版本,启用旧版本
```bash
# 禁用 v1.0.1
curl -X PATCH http://localhost:3005/api/v1/version/{v1.0.1-id}/disable \
-H "Content-Type: application/json" \
-d '{"updatedBy": "admin"}'
# 启用 v1.0.0
curl -X PATCH http://localhost:3005/api/v1/version/{v1.0.0-id}/enable \
-H "Content-Type: application/json" \
-d '{"updatedBy": "admin"}'
```
**方案 2**: 创建新版本,使用更高的 versionCode
```bash
# 创建 v1.0.0-hotfix (versionCode = 103)
curl -X POST http://localhost:3005/api/v1/version \
-H "Content-Type: application/json" \
-d '{
"platform": "android",
"versionCode": 103,
"versionName": "1.0.0",
"buildNumber": "20250102003",
...
}'
```
### Q2: 如何处理多渠道包 (Google Play, 自建服务器)?
当前版本不支持,建议通过 `buildNumber` 区分:
```bash
# Google Play 渠道
{
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "100-gplay",
"downloadUrl": "https://play.google.com/store/apps/details?id=com.rwa.durian",
...
}
# 自建渠道
{
"versionCode": 100,
"versionName": "1.0.0",
"buildNumber": "100-self",
"downloadUrl": "https://cdn.rwadurian.com/android/app-v1.0.0.apk",
...
}
```
### Q3: 如何实现灰度发布?
当前版本不支持,未来可扩展:
```typescript
// 计划实现
interface AppVersion {
...
releaseType: 'full' | 'gray'; // 发布类型
grayRatio?: number; // 灰度比例 (0-100)
grayUserIds?: string[]; // 灰度用户列表
}
```
---
**最后更新**: 2025-12-03
**版本**: 1.0.0
**维护者**: RWA Durian Team