Files
carrotskin/API文档.md

944 lines
20 KiB
Markdown
Raw Permalink Normal View History

# CarrotSkin 后端 API 文档
## 概述
本文档总结了 CarrotSkin 后端 API主要关注前端需要的接口不包括 Yggdrasil 相关接口(除了更换 Yggdrasil 密码)。
## 基础信息
- **基础URL**: `/api/v1`
- **认证方式**: JWT Bearer Token
- **数据格式**: JSON
- **字符编码**: UTF-8
## 通用响应格式
所有API响应都遵循以下格式
```json
{
"code": 200,
"message": "操作成功",
"data": {
// 具体数据内容
}
}
```
分页响应格式:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [],
"total": 100,
"page": 1,
"page_size": 20,
"total_pages": 5
}
}
```
## 认证相关 API
### 1. 用户注册
- **URL**: `POST /api/v1/auth/register`
- **认证**: 无需认证
- **请求参数**:
```json
{
"username": "newuser", // 用户名3-50字符
"email": "user@example.com", // 邮箱地址
"password": "password123", // 密码6-128字符
"verification_code": "123456", // 邮箱验证码6位数字
"avatar": "https://example.com/avatar.png" // 可选头像URL
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "注册成功",
"data": {
"token": "jwt_token_here",
"user_info": {
"id": 1,
"username": "newuser",
"email": "user@example.com",
"avatar": "https://example.com/avatar.png",
"points": 0,
"role": "user",
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
}
```
### 2. 用户登录
- **URL**: `POST /api/v1/auth/login`
- **认证**: 无需认证
- **请求参数**:
```json
{
"username": "testuser", // 用户名或邮箱
"password": "password123" // 密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "登录成功",
"data": {
"token": "jwt_token_here",
"user_info": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
}
```
### 3. 发送验证码
- **URL**: `POST /api/v1/auth/send-code`
- **认证**: 无需认证
- **请求参数**:
```json
{
"email": "user@example.com", // 邮箱地址
"type": "register" // 类型: register/reset_password/change_email
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "验证码已发送,请查收邮件",
"data": {
"message": "验证码已发送,请查收邮件"
}
}
```
### 4. 重置密码
- **URL**: `POST /api/v1/auth/reset-password`
- **认证**: 无需认证
- **请求参数**:
```json
{
"email": "user@example.com", // 邮箱地址
"verification_code": "123456", // 邮箱验证码
"new_password": "newpassword123" // 新密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "密码重置成功",
"data": {
"message": "密码重置成功"
}
}
```
## 用户相关 API
### 1. 获取用户信息
- **URL**: `GET /api/v1/user/profile`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 2. 更新用户信息
- **URL**: `PUT /api/v1/user/profile`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"avatar": "https://example.com/new-avatar.png", // 可选新头像URL
"old_password": "oldpassword123", // 可选,修改密码时需要
"new_password": "newpassword123" // 可选,新密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/new-avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 3. 生成头像上传URL
- **URL**: `POST /api/v1/user/avatar/upload-url`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"file_name": "avatar.png" // 文件名
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"post_url": "https://rustfs.example.com/avatars",
"form_data": {
"key": "user_1/xxx.png",
"policy": "base64_policy",
"x-amz-signature": "signature"
},
"avatar_url": "https://rustfs.example.com/avatars/user_1/xxx.png",
"expires_in": 900
}
}
```
### 4. 更新头像URL
- **URL**: `PUT /api/v1/user/avatar`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数: `avatar_url` - 头像URL
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/new-avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 5. 更换邮箱
- **URL**: `POST /api/v1/user/change-email`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"new_email": "newemail@example.com", // 新邮箱地址
"verification_code": "123456" // 邮箱验证码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "newemail@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 6. 重置Yggdrasil密码
- **URL**: `POST /api/v1/user/yggdrasil-password/reset`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"password": "new_yggdrasil_password"
}
}
```
## 材质相关 API
### 1. 搜索材质
- **URL**: `GET /api/v1/texture`
- **认证**: 无需认证
- **请求参数**:
- Query参数:
- `keyword`: 搜索关键词
- `type`: 材质类型 (SKIN/CAPE)
- `public_only`: 是否只搜索公开材质 (true/false)
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 100,
"page": 1,
"page_size": 20,
"total_pages": 5
}
}
```
### 2. 获取材质详情
- **URL**: `GET /api/v1/texture/{id}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 3. 直接上传材质文件(推荐)
- **URL**: `POST /api/v1/texture/upload`
- **认证**: 需要JWT认证
- **Content-Type**: `multipart/form-data`
- **请求参数**:
- `file`: 材质文件PNG格式1KB-10MB
- `name`: 材质名称必填1-100字符
- `description`: 材质描述可选最多500字符
- `type`: 材质类型可选默认SKIN可选值SKIN/CAPE
- `is_public`: 是否公开可选默认falsetrue/false
- `is_slim`: 是否为细臂模型可选默认falsetrue/false
- **说明**:
- 后端会自动计算文件的SHA256哈希值
- 如果已存在相同哈希的材质会复用已存在的文件URL不重复上传
- 允许多次上传相同哈希的材质(包括同一用户),每次都会创建新的数据库记录
- 文件存储路径格式:`{type}/{hash[:2]}/{hash[2:4]}/{hash}.png`
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/skin/e3/b0/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 0,
"favorite_count": 0,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 4. 生成材质上传URL兼容接口
- **URL**: `POST /api/v1/texture/upload-url`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"file_name": "skin.png", // 文件名
"texture_type": "SKIN" // 材质类型: SKIN/CAPE
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"post_url": "https://rustfs.example.com/textures",
"form_data": {
"key": "user_1/skin/xxx.png",
"policy": "base64_policy",
"x-amz-signature": "signature"
},
"texture_url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"expires_in": 900
}
}
```
### 5. 创建材质记录配合预签名URL使用
- **URL**: `POST /api/v1/texture`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"name": "My Cool Skin", // 材质名称1-100字符
"description": "A very cool skin", // 描述最多500字符
"type": "SKIN", // 材质类型: SKIN/CAPE
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png", // 材质URL
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", // SHA256哈希
"size": 2048, // 文件大小(字节)
"is_public": true, // 是否公开
"is_slim": false // 是否为细臂模型(Alex)
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 0,
"favorite_count": 0,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 6. 更新材质
- **URL**: `PUT /api/v1/texture/{id}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- 请求体:
```json
{
"name": "Updated Skin Name", // 可选,新名称
"description": "Updated description", // 可选,新描述
"is_public": false // 可选,是否公开
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "Updated Skin Name",
"description": "Updated description",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": false,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 7. 删除材质
- **URL**: `DELETE /api/v1/texture/{id}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": null
}
```
### 8. 切换收藏状态
- **URL**: `POST /api/v1/texture/{id}/favorite`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"is_favorited": true
}
}
```
### 9. 获取用户上传的材质列表
- **URL**: `GET /api/v1/texture/my`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数:
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 50,
"page": 1,
"page_size": 20,
"total_pages": 3
}
}
```
### 10. 获取用户收藏的材质列表
- **URL**: `GET /api/v1/texture/favorites`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数:
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 2,
"name": "Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 30,
"page": 1,
"page_size": 20,
"total_pages": 2
}
}
```
## 档案相关 API
### 1. 创建档案
- **URL**: `POST /api/v1/profile`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"name": "PlayerName" // 角色名1-16字符
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": null,
"cape_id": null,
"is_active": false,
"last_used_at": null,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 2. 获取档案列表
- **URL**: `GET /api/v1/profile`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
]
}
```
### 3. 获取档案详情
- **URL**: `GET /api/v1/profile/{uuid}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 4. 更新档案
- **URL**: `PUT /api/v1/profile/{uuid}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- 请求体:
```json
{
"name": "NewPlayerName", // 可选,新角色名
"skin_id": 1, // 可选皮肤ID
"cape_id": 2 // 可选披风ID
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "NewPlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 5. 删除档案
- **URL**: `DELETE /api/v1/profile/{uuid}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"message": "删除成功"
}
}
```
### 6. 设置活跃档案
- **URL**: `POST /api/v1/profile/{uuid}/activate`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"message": "设置成功"
}
}
```
## 验证码相关 API
### 1. 生成验证码
- **URL**: `GET /api/v1/captcha/generate`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"data": {
"masterImage": "base64_encoded_master_image",
"tileImage": "base64_encoded_tile_image",
"captchaId": "captcha_id_here",
"y": 100
}
}
```
### 2. 验证验证码
- **URL**: `POST /api/v1/captcha/verify`
- **认证**: 无需认证
- **请求参数**:
```json
{
"captchaId": "captcha_id_here",
"dx": 150 // 滑动距离
}
```
- **响应数据**:
```json
{
"code": 200,
"msg": "验证成功"
}
```
## 系统相关 API
### 1. 获取系统配置
- **URL**: `GET /api/v1/system/config`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"site_name": "CarrotSkin",
"site_description": "A Minecraft Skin Station",
"registration_enabled": true,
"max_textures_per_user": 100,
"max_profiles_per_user": 5
}
}
```
## CustomSkin API
### 1. 获取玩家信息
- **URL**: `GET /api/v1/csl/{username}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `username` - 玩家用户名
- **响应数据**:
```json
{
"username": "PlayerName",
"textures": {
"default": "skin_hash_here",
"slim": "skin_hash_here",
"cape": "cape_hash_here",
"elytra": "cape_hash_here"
}
}
```
或简化格式:
```json
{
"username": "PlayerName",
"skin": "skin_hash_here"
}
```
### 2. 获取资源文件
- **URL**: `GET /api/v1/csl/textures/{hash}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `hash` - 资源哈希值
- **响应数据**: 二进制文件内容
## 健康检查
### 1. 健康检查
- **URL**: `GET /health`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"status": "ok"
}
```
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 操作成功 |
| 400 | 请求参数错误 |
| 401 | 未认证或认证失败 |
| 403 | 无权限操作 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
## 认证说明
需要JWT认证的API需要在请求头中添加
```
Authorization: Bearer {jwt_token}
```
JWT Token在用户登录或注册成功后返回有效期内可用于访问需要认证的API。