# B 端认证 API 文档

本文档描述君鸿卡管系统 B 端认证接口（后台管理和 H5），包括登录、登出、Token 刷新、用户信息查询和密码修改功能。

---

## 概述

### 基础信息

- **后台 API 前缀**: `/api/admin`
- **H5 API 前缀**: `/api/h5`
- **认证方式**: Bearer Token (存储在 Redis)
- **Token 类型**:
  - Access Token：24 小时有效期，用于 API 访问
  - Refresh Token：7 天有效期，用于刷新 Access Token

### 用户类型限制

| 平台 | 允许的用户类型 |
|------|---------------|
| 后台 | SuperAdmin(1)、Platform(2)、Agent(3) |
| H5   | Agent(3)、Enterprise(4) |

---

## 公开接口（无需认证）

### 1. 用户登录

**后台**: `POST /api/admin/login`  
**H5**: `POST /api/h5/login`

使用用户名或手机号 + 密码登录，返回访问令牌。

#### 请求体

```json
{
  "username": "admin",
  "password": "Admin@123456",
  "device": "web"
}
```

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| username | string | 是 | 用户名或手机号 |
| password | string | 是 | 密码 |
| device | string | 否 | 设备标识（web/ios/android） |

#### 响应示例

**成功（200）**:
```json
{
  "code": 0,
  "message": "操作成功",
  "data": {
    "access_token": "550e8400-e29b-41d4-a716-446655440000",
    "refresh_token": "660f9500-f39c-52e5-b827-557766551111",
    "expires_in": 86400,
    "user": {
      "id": 1,
      "username": "admin",
      "phone": "13800000000",
      "user_type": 1,
      "user_type_name": "超级管理员",
      "shop_id": 0,
      "enterprise_id": 0
    },
    "permissions": [
      "user:create",
      "user:update",
      "user:delete",
      "role:manage"
    ]
  },
  "timestamp": "2026-01-15T16:05:00+08:00"
}
```

#### 错误码

| 错误码 | 消息 | 说明 |
|--------|------|------|
| 1001 | 参数验证失败 | 请求参数不完整或格式错误 |
| 1040 | 用户名或密码错误 | 凭证无效 |
| 1011 | 账号已禁用 | 账号被禁用，无法登录 |
| 1041 | 账号已锁定 | 账号被锁定 |

#### cURL 示例

```bash
# 后台登录
curl -X POST http://localhost:8080/api/admin/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "Admin@123456",
    "device": "web"
  }'

# H5 登录
curl -X POST http://localhost:8080/api/h5/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "agent001",
    "password": "password123",
    "device": "ios"
  }'
```

---

### 2. 刷新访问令牌

**后台**: `POST /api/admin/refresh-token`  
**H5**: `POST /api/h5/refresh-token`

使用 Refresh Token 获取新的 Access Token。

#### 请求体

```json
{
  "refresh_token": "660f9500-f39c-52e5-b827-557766551111"
}
```

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| refresh_token | string | 是 | 刷新令牌 |

#### 响应示例

**成功（200）**:
```json
{
  "code": 0,
  "message": "操作成功",
  "data": {
    "access_token": "770a0600-a40d-63f6-c938-668877662222",
    "expires_in": 86400
  },
  "timestamp": "2026-01-15T16:06:00+08:00"
}
```

#### 错误码

| 错误码 | 消息 | 说明 |
|--------|------|------|
| 1001 | 参数验证失败 | refresh_token 缺失 |
| 1003 | 无效或过期的令牌 | Refresh Token 无效或已过期 |

#### cURL 示例

```bash
curl -X POST http://localhost:8080/api/admin/refresh-token \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "660f9500-f39c-52e5-b827-557766551111"
  }'
```

---

## 受保护接口（需要认证）

所有受保护接口需在请求头中携带 Access Token：

```
Authorization: Bearer {access_token}
```

---

### 3. 用户登出

**后台**: `POST /api/admin/logout`  
**H5**: `POST /api/h5/logout`

撤销当前 Access Token 和 Refresh Token（如果提供）。

#### 请求头

```
Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000
```

#### 请求体（可选）

```json
{
  "refresh_token": "660f9500-f39c-52e5-b827-557766551111"
}
```

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| refresh_token | string | 否 | 如果提供，同时撤销 Refresh Token |

#### 响应示例

**成功（200）**:
```json
{
  "code": 0,
  "message": "操作成功",
  "data": null,
  "timestamp": "2026-01-15T16:07:00+08:00"
}
```

#### 错误码

| 错误码 | 消息 | 说明 |
|--------|------|------|
| 1002 | 缺失认证令牌 | 请求头未携带 Authorization |
| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 |
| 1004 | 未授权访问 | Token 已被撤销 |

#### cURL 示例

```bash
curl -X POST http://localhost:8080/api/admin/logout \
  -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "660f9500-f39c-52e5-b827-557766551111"
  }'
```

---

### 4. 获取当前用户信息

**后台**: `GET /api/admin/me`  
**H5**: `GET /api/h5/me`

获取当前登录用户的详细信息和权限列表。

#### 请求头

```
Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000
```

#### 响应示例

**成功（200）**:
```json
{
  "code": 0,
  "message": "操作成功",
  "data": {
    "user": {
      "id": 1,
      "username": "admin",
      "phone": "13800000000",
      "user_type": 1,
      "user_type_name": "超级管理员",
      "shop_id": 0,
      "enterprise_id": 0,
      "status": 1,
      "created_at": "2026-01-01T00:00:00+08:00"
    },
    "permissions": [
      "user:create",
      "user:update",
      "user:delete",
      "role:manage",
      "permission:manage"
    ]
  },
  "timestamp": "2026-01-15T16:08:00+08:00"
}
```

#### 错误码

| 错误码 | 消息 | 说明 |
|--------|------|------|
| 1002 | 缺失认证令牌 | 请求头未携带 Authorization |
| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 |
| 1004 | 未授权访问 | 用户信息查询失败 |

#### cURL 示例

```bash
curl -X GET http://localhost:8080/api/admin/me \
  -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000"
```

---

### 5. 修改密码

**后台**: `POST /api/admin/password`  
**H5**: `POST /api/h5/password`

修改当前用户密码，修改成功后所有旧 Token 将失效。

#### 请求头

```
Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000
```

#### 请求体

```json
{
  "old_password": "Admin@123456",
  "new_password": "NewPassword@2026"
}
```

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| old_password | string | 是 | 当前密码 |
| new_password | string | 是 | 新密码（6-20 位，包含字母和数字） |

#### 响应示例

**成功（200）**:
```json
{
  "code": 0,
  "message": "操作成功",
  "data": null,
  "timestamp": "2026-01-15T16:09:00+08:00"
}
```

#### 错误码

| 错误码 | 消息 | 说明 |
|--------|------|------|
| 1001 | 参数验证失败 | 密码格式不符合要求 |
| 1002 | 缺失认证令牌 | 请求头未携带 Authorization |
| 1003 | 无效或过期的令牌 | Access Token 无效或已过期 |
| 1043 | 旧密码错误 | 提供的旧密码不正确 |

#### cURL 示例

```bash
curl -X POST http://localhost:8080/api/admin/password \
  -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "old_password": "Admin@123456",
    "new_password": "NewPassword@2026"
  }'
```

---

## 错误码对照表

### 认证相关错误（1000-1099）

| 错误码 | 消息 | HTTP 状态码 | 说明 |
|--------|------|-------------|------|
| 1001 | 参数验证失败 | 400 | 请求参数不完整或格式错误 |
| 1002 | 缺失认证令牌 | 401 | Authorization 请求头缺失 |
| 1003 | 无效或过期的令牌 | 401 | Token 无效或已过期 |
| 1004 | 未授权访问 | 401 | 无权访问该资源 |
| 1005 | 禁止访问 | 403 | 用户类型不允许访问 |
| 1040 | 用户名或密码错误 | 401 | 登录凭证错误 |
| 1011 | 账号已禁用 | 403 | 账号被管理员禁用 |
| 1041 | 账号已锁定 | 403 | 账号因安全原因被锁定 |
| 1042 | 密码已过期 | 403 | 需要更新密码 |
| 1043 | 旧密码错误 | 400 | 修改密码时提供的旧密码不正确 |

### 服务端错误（2000-2999）

| 错误码 | 消息 | HTTP 状态码 | 说明 |
|--------|------|-------------|------|
| 2001 | 内部服务器错误 | 500 | 服务器内部错误 |
| 2002 | 数据库错误 | 500 | 数据库操作失败 |
| 2003 | Redis 错误 | 500 | Redis 操作失败 |
| 2004 | 服务不可用 | 503 | 服务暂时不可用 |

---

## 使用场景示例

### 场景 1：完整登录流程

```bash
# 1. 用户登录
curl -X POST http://localhost:8080/api/admin/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"Admin@123456"}' \
  | jq

# 响应获取 access_token 和 refresh_token
# {
#   "code": 0,
#   "data": {
#     "access_token": "550e8400-...",
#     "refresh_token": "660f9500-..."
#   }
# }

# 2. 使用 access_token 访问受保护接口
curl -X GET http://localhost:8080/api/admin/me \
  -H "Authorization: Bearer 550e8400-..." \
  | jq

# 3. Access Token 过期后，使用 Refresh Token 刷新
curl -X POST http://localhost:8080/api/admin/refresh-token \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":"660f9500-..."}' \
  | jq

# 4. 登出
curl -X POST http://localhost:8080/api/admin/logout \
  -H "Authorization: Bearer 550e8400-..." \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":"660f9500-..."}' \
  | jq
```

### 场景 2：修改密码

```bash
# 1. 登录获取 token
TOKEN=$(curl -s -X POST http://localhost:8080/api/admin/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"Admin@123456"}' \
  | jq -r '.data.access_token')

# 2. 修改密码
curl -X POST http://localhost:8080/api/admin/password \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "old_password": "Admin@123456",
    "new_password": "NewPassword@2026"
  }' \
  | jq

# 3. 旧 token 失效，需要重新登录
curl -X POST http://localhost:8080/api/admin/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"NewPassword@2026"}' \
  | jq
```

---

## 安全注意事项

1. **Token 存储**：
   - 前端应将 Token 存储在安全位置（如 HttpOnly Cookie 或 secure storage）
   - 不要将 Token 暴露在 URL 中

2. **Token 传输**：
   - 始终使用 HTTPS 传输 Token
   - Token 仅在 Authorization 请求头中传递

3. **密码要求**：
   - 长度：6-20 位
   - 必须包含字母和数字
   - 建议包含特殊字符

4. **Token 生命周期**：
   - Access Token：24 小时自动过期
   - Refresh Token：7 天自动过期
   - 修改密码后所有旧 Token 立即失效

5. **并发登录**：
   - 系统支持同一用户多设备同时登录
   - 每个设备拥有独立的 Token 对
   - 登出只撤销当前设备的 Token

---

## 常见问题

**Q: 如何判断 Access Token 是否过期？**  
A: 接口返回 `1003` 错误码时表示 Token 过期，应使用 Refresh Token 刷新。

**Q: Refresh Token 过期后怎么办？**  
A: Refresh Token 过期后需要重新登录。

**Q: 修改密码后需要重新登录吗？**  
A: 是的，修改密码后所有设备的 Token 都会失效，需要重新登录。

**Q: 后台用户可以使用 H5 接口吗？**  
A: 不可以。后台和 H5 有不同的用户类型限制，使用错误的端点会返回 `1005` 错误。

**Q: 如何撤销所有设备的登录状态？**  
A: 调用 `/api/admin/password` 修改密码，所有设备的 Token 会自动失效。

---

## 相关文档

- [使用指南](../auth-usage-guide.md) - 如何在代码中集成认证
- [架构说明](../auth-architecture.md) - 认证系统架构设计
- [错误处理指南](../003-error-handling/使用指南.md) - 统一错误处理

---

**文档版本**: v1.0  
**最后更新**: 2026-01-15  
**维护者**: 君鸿卡管系统开发团队
