# WPS365 授权错误排查指南

## 常见错误类型

### 1. invalid_request (40000001) - redirect_uri不匹配

```json
{
  "code": 40000001,
  "msg": "invalid_request",
  "debug": {
    "desc": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. The 'redirect_uri' parameter does not match any of the OAuth 2.0 Client's pre-registered redirect urls."
  }
}
```

**错误含义**：redirect_uri参数值与WPS365平台配置的回调地址不一致

### 2. invalid_scope (40000005) - scope权限无效 ⚠️

```json
{
  "code": 40000005,
  "msg": "invalid_scope",
  "debug": {
    "desc": "The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope 'file.read,ksheet.read,user.info'."
  }
}
```

**错误含义**：请求的scope权限格式不正确，或者应用未申请这些权限

## 错误含义总览

授权错误可能由以下原因导致：

1. **缺少必需参数** - 授权请求中缺少某个必需的参数
2. **参数值无效** - 某个参数的值格式不正确
3. **参数重复** - 某个参数在请求中出现了多次
4. **redirect_uri不匹配** - redirect_uri参数值与WPS365平台配置的回调地址不一致
5. **scope无效** - scope权限格式不正确或未申请

## 排查步骤

### 1. 查看后端日志

查看后端日志中的授权URL和参数清单，例如：

```
生成授权URL: https://openapi.wps.cn/oauth2/auth?client_id=xxx&redirect_uri=...
📋 授权请求参数清单:
   - client_id: AK20260114NNQJKV
   - redirect_uri: https://jarvis.van333.cn/wps365-callback
   - response_type: code
   - scope: file.read,ksheet.read,user.info
   - state: xxxxx
```

### 2. 检查参数名是否正确

**问题**：WPS365可能使用 `app_id` 而不是标准的 `client_id`

**解决方案**：
- 如果使用 `client_id` 报错，尝试改为 `app_id`
- 查看WPS365官方文档确认正确的参数名

**当前代码使用**：`client_id`（标准OAuth2参数名）

### 3. 检查必需参数是否齐全

授权请求必须包含以下参数：

| 参数名 | 是否必需 | 说明 | 当前值 |
|--------|---------|------|--------|
| `client_id` 或 `app_id` | ✅ 必需 | 应用ID | 从配置读取 |
| `redirect_uri` | ✅ 必需 | 回调地址 | 从配置读取 |
| `response_type` | ✅ 必需 | 固定值 `code` | `code` |
| `scope` | ✅ 必需 | 权限范围 | `file.read,ksheet.read,user.info` |
| `state` | ⚠️ 推荐 | 防CSRF攻击 | 自动生成 |

### 4. 检查redirect_uri是否匹配

这是最常见的错误原因。必须确保：

1. **协议一致**：必须是 `https://`（不能是 `http://`）
2. **域名一致**：必须是 `jarvis.van333.cn`（不能有 `www` 前缀）
3. **路径一致**：必须是 `/wps365-callback`（不能有末尾斜杠）
4. **端口一致**：使用默认443端口，不需要写端口号

**在WPS365平台配置的回调地址必须与日志中的redirect_uri完全一致**

### 5. 检查scope权限是否已申请（重要！）

**如果遇到 `invalid_scope` 错误，请按以下步骤排查：**

#### 5.1 检查WPS365平台后台的scope格式

1. 登录WPS365开放平台
2. 进入"开发配置" > "权限管理"
3. 查看已申请的权限列表，**注意权限的格式**：
   - 必须以 `kso.` 开头，如：`kso.file.read`、`kso.file.readwrite`
   - 不是 `file.read` 或 `ksheet.read`（这些格式不存在）
   - 根据官方文档：https://open.wps.cn/documents/app-integration-dev/wps365/server/

#### 5.2 检查scope分隔符

**根据WPS365官方文档，必须使用英文逗号分隔**（不是空格）：

| 分隔符 | 示例 | 说明 |
|--------|------|------|
| **逗号（正确）** | `kso.file.readwrite,kso.doclib.readwrite` | ✅ WPS365官方要求 |
| **空格（错误）** | `kso.file.readwrite kso.doclib.readwrite` | ❌ 会导致invalid_scope |
| **逗号+空格** | `kso.file.readwrite, kso.doclib.readwrite` | ⚠️ 可能支持，但不推荐 |

**重要**：WPS365官方文档明确要求使用英文逗号 `,` 分隔，不能使用空格。

#### 5.3 在配置文件中指定scope

在 `application.yml` 中添加 `scope` 配置，**必须使用英文逗号分隔**：

```yaml
wps365:
  # 根据WPS365平台后台"权限管理"中显示的实际权限名称配置
  # 使用英文逗号分隔（WPS365官方要求）
  # 权限名称必须以 kso. 开头
  scope: kso.file.readwrite
```

多个权限示例：

```yaml
wps365:
  # 多个权限用英文逗号分隔，不能有空格
  # 权限名称必须以 kso. 开头
  scope: kso.file.read,kso.file.readwrite
```

#### 5.4 确认权限已申请且名称正确

**关键步骤**：

1. **登录WPS365开放平台**
   - 访问：https://open.wps.cn/
   - 进入你的应用管理页面

2. **查看已申请的权限**
   - 进入"开发配置" > "权限管理"
   - 查看已申请权限的**准确名称**（注意大小写、分隔符、命名空间）

3. **对比权限名称**
   - 权限名称必须与后台显示的**完全一致**
   - 例如：如果后台显示的是 `kso.doclib.readwrite`，不能写成 `kso.doclib.readWrite` 或 `kso_doclib_readwrite`

4. **常见权限名称示例**（仅供参考，以平台后台实际显示为准）：
   - `kso.doclib.readwrite` - 文档库读写权限
   - `kso.doclib.read` - 文档库读取权限
   - `ksheet.read` - 在线表格读取权限（如果支持）

**重要提示**：
- ⚠️ `file.read`、`ksheet.read`、`user.info` 这些权限名称可能不存在
- ✅ 必须查看WPS365平台后台实际显示的权限名称
- ✅ 权限名称必须完全匹配（包括大小写、分隔符、命名空间）
- ✅ 必须使用英文逗号分隔多个权限

### 6. 尝试修改参数名

如果确认所有参数都正确，但仍然报错，可能是参数名问题：

**测试方案1**：将 `client_id` 改为 `app_id`

修改 `WPS365OAuthServiceImpl.java` 中的代码：
```java
// 原代码
authUrl.append("?client_id=").append(appId);

// 改为
authUrl.append("?app_id=").append(appId);
```

**测试方案2**：同时提供两个参数（如果WPS365支持）
```java
authUrl.append("?app_id=").append(appId);
authUrl.append("&client_id=").append(appId);
```

### 7. 检查URL编码

确保 `redirect_uri` 参数正确进行了URL编码：
- 空格应该编码为 `%20`
- 斜杠 `/` 应该编码为 `%2F`
- 冒号 `:` 应该编码为 `%3A`

查看日志中的"编码后"值，确认编码是否正确。

### 8. 验证WPS365平台配置

登录WPS365开放平台，检查：

1. **应用ID（AppId）** 是否与配置文件中的 `app-id` 一致
2. **回调地址配置** 是否与日志中的 `redirect_uri` 完全一致
3. **权限配置** 是否已申请所需的scope权限
4. **应用状态** 是否为"已上线"或"测试中"

## 常见问题

### Q1: 参数名应该用 `client_id` 还是 `app_id`？

**A**: 根据WPS365官方文档确认。标准OAuth2使用 `client_id`，但某些平台可能使用 `app_id`。如果 `client_id` 不工作，尝试 `app_id`。

### Q2: 为什么redirect_uri明明配置了还是报错？

**A**: 最常见的原因是：
- 平台配置的回调地址与代码中的不完全一致（多了/少了斜杠、协议不同等）
- 平台配置未保存或未生效
- 使用了错误的配置环境（开发/生产）

### Q3: scope权限在哪里申请？

**A**: 在WPS365开放平台的"开发配置" > "权限管理"中申请。

### Q4: 如何确认参数是否正确？

**A**: 查看后端日志，会打印完整的授权URL和参数清单。对比WPS365平台配置，确保完全一致。

### Q5: 遇到 `invalid_scope` 错误怎么办？ ⚠️

**A**: 这是scope格式或权限问题，按以下步骤排查：

1. **查看WPS365平台后台的权限格式**
   - 进入"开发配置" > "权限管理"
   - 查看已申请权限的**确切格式**（包括分隔符、大小写）

2. **尝试不同的scope格式**
   - 空格分隔：`file.read ksheet.read user.info`（当前默认）
   - 逗号分隔：`file.read,ksheet.read,user.info`
   - 在 `application.yml` 中配置 `scope` 参数进行测试

3. **确认权限已申请且已审核通过**
   - 权限必须处于"已通过"或"可用"状态
   - 如果权限未申请，需要先申请并等待审核

4. **查看后端日志中的scope值**
   - 日志会显示实际使用的scope格式
   - 对比WPS365平台显示的格式，确保完全一致

## 调试建议

1. **启用DEBUG日志**：在 `application.yml` 中设置日志级别为DEBUG
2. **查看完整授权URL**：复制日志中的授权URL，在浏览器中访问，查看具体错误
3. **对比官方文档**：查看WPS365官方OAuth文档，确认参数名和格式
4. **联系WPS365技术支持**：如果所有参数都正确但仍报错，可能是平台问题

## 下一步

如果按照以上步骤排查后仍然报错，请提供：
1. 后端日志中的完整授权URL和参数清单
2. WPS365平台配置的回调地址截图
3. WPS365平台的应用配置截图（隐藏敏感信息）

