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

22 KiB
Raw Permalink Blame History

Admin Service API 文档

目录


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 认证。

计划认证方案:

Authorization: Bearer <JWT_TOKEN>

获取 Token (待实现):

POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "password123"
}

响应:

{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 7200
}

2.2 权限级别 (待实现)

角色 权限
admin 完全权限:创建、启用、禁用、删除版本
developer 创建、查询版本
public 仅检查更新 (无需认证)

3. 通用响应格式

3.1 成功响应

200 OK - 查询成功:

{
  "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 - 创建成功:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "platform": "android",
  "versionCode": 101,
  ...
}

204 No Content - 操作成功无返回内容

3.2 分页响应 (待实现)

{
  "data": [...],
  "meta": {
    "total": 50,
    "page": 1,
    "pageSize": 10,
    "totalPages": 5
  }
}

4. 错误处理

4.1 错误响应格式

{
  "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

权限: 需要认证 (待实现)

请求体:

{
  "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 平台 androidios
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

{
  "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"
}

错误响应:

// 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 示例:

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

请求示例:

GET /api/v1/version?platform=android&isEnabled=true

响应: 200 OK

[
  {
    "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 示例:

curl -X GET "http://localhost:3005/api/v1/version?platform=android&isEnabled=true"

5.3 查询单个版本

端点: GET /api/v1/version/:id

权限: 需要认证 (待实现)

路径参数:

参数 类型 说明
id string (UUID) 版本 ID

请求示例:

GET /api/v1/version/550e8400-e29b-41d4-a716-446655440000

响应: 200 OK

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "platform": "android",
  "versionCode": 100,
  "versionName": "1.0.0",
  ...
}

错误响应:

// 404 Not Found
{
  "statusCode": 404,
  "message": "Version not found",
  "error": "Not Found"
}

cURL 示例:

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

请求体:

{
  "updatedBy": "admin"
}

请求示例:

PATCH /api/v1/version/550e8400-e29b-41d4-a716-446655440000/enable
Content-Type: application/json

{
  "updatedBy": "admin"
}

响应: 204 No Content

错误响应:

// 404 Not Found
{
  "statusCode": 404,
  "message": "Version not found",
  "error": "Not Found"
}

cURL 示例:

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

请求体:

{
  "updatedBy": "admin"
}

请求示例:

PATCH /api/v1/version/550e8400-e29b-41d4-a716-446655440000/disable
Content-Type: application/json

{
  "updatedBy": "admin"
}

响应: 204 No Content

业务逻辑:

  • 禁用版本时,会自动将 isForceUpdate 设置为 false
  • 禁用后的版本不会出现在 "检查更新" 结果中

cURL 示例:

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

请求示例:

GET /api/v1/version/check?platform=android&versionCode=100

响应 1: 200 OK - 有更新

{
  "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 - 无更新

{
  "hasUpdate": false
}

响应 3: 200 OK - 强制更新

{
  "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!"
}

错误响应:

// 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

移动端处理逻辑:

// 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 示例:

curl -X GET "http://localhost:3005/api/v1/version/check?platform=android&versionCode=100"

6. 数据模型

6.1 AppVersion (应用版本)

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 (平台枚举)

enum Platform {
  ANDROID = 'android',
  IOS = 'ios',
}

6.3 VersionCheckResult (版本检查结果)

interface VersionCheckResult {
  hasUpdate: boolean;         // 是否有更新
  latestVersion?: string;     // 最新版本名称
  downloadUrl?: string;       // 下载链接
  isForceUpdate?: boolean;    // 是否强制更新
  changelog?: string;         // 更新日志
}

7. 使用示例

7.1 完整发版流程

步骤 1: 创建 Android 新版本

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: 验证版本已创建

curl -X GET "http://localhost:3005/api/v1/version?platform=android&isEnabled=true"

步骤 3: 移动端检查更新

# 用户当前版本号 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: 发现问题,紧急禁用版本

curl -X PATCH http://localhost:3005/api/v1/version/550e8400-e29b-41d4-a716-446655440001/disable \
  -H "Content-Type: application/json" \
  -d '{"updatedBy": "admin"}'

步骤 5: 创建修复版本

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 版本发布

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 (部分示例)

{
  "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 校验流程

服务端计算 (发版时):

# Linux/macOS
sha256sum app-android-v1.0.0.apk

# Windows
certutil -hashfile app-android-v1.0.0.apk SHA256

移动端校验 (下载后):

// 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: 禁用问题版本,启用旧版本

# 禁用 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

# 创建 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 区分:

# 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: 如何实现灰度发布?

当前版本不支持,未来可扩展:

// 计划实现
interface AppVersion {
  ...
  releaseType: 'full' | 'gray'; // 发布类型
  grayRatio?: number;           // 灰度比例 (0-100)
  grayUserIds?: string[];       // 灰度用户列表
}

最后更新: 2025-12-03 版本: 1.0.0 维护者: RWA Durian Team