Files
ruoyi-java/doc/腾讯文档API鉴权修复指南.md
2025-11-06 02:32:27 +08:00

6.0 KiB
Raw Blame History

腾讯文档 API 鉴权修复指南

关键发现

根据腾讯文档官方 API 文档,发现了之前鉴权方式的重大错误:

正确的鉴权方式

腾讯文档 V3 API 需要三个请求头进行鉴权:

Access-Token: {访问令牌}
Client-Id: {应用ID}
Open-Id: {开放平台用户ID}

而不是

Authorization: Bearer {访问令牌}  ❌ 错误!

推荐方案:使用应用级账号 Token

什么是应用级账号 Token

  • 不需要用户授权流程
  • 直接使用 client_idclient_secret 获取
  • 响应包含所有需要的信息

API 接口

请求:

GET https://docs.qq.com/oauth/v2/app-account-token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET

响应:

{
  "access_token": "ACCESSTOKENEXAMPLE",
  "token_type": "Bearer",
  "refresh_token": "REFRESHTOKENEXAMPLE",
  "expires_in": 259200,
  "scope": "scope.file.editable,scope.folder.creatable",
  "user_id": "bcb50c8a4b724d86bbcf6fc64c5e2b22"
}

字段映射

响应字段 对应请求头 说明
access_token Access-Token 访问令牌
请求参数 client_id Client-Id 应用ID
user_id Open-Id 开放平台用户ID关键

完整的 API 调用流程

步骤1获取应用级账号 Token

JSONObject tokenInfo = TencentDocApiUtil.getAppAccountToken(appId, appSecret);

String accessToken = tokenInfo.getString("access_token");
String openId = tokenInfo.getString("user_id");  // 这就是 Open-Id
String clientId = appId;  // Client-Id 就是 appId

步骤2调用业务 API

// 设置请求头
conn.setRequestProperty("Access-Token", accessToken);
conn.setRequestProperty("Client-Id", clientId);
conn.setRequestProperty("Open-Id", openId);
conn.setRequestProperty("Content-Type", "application/json");

步骤3发送请求

GET https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}/{sheetId}/A1:Z100
Access-Token: ACCESSTOKENEXAMPLE
Client-Id: YOUR_CLIENT_ID
Open-Id: bcb50c8a4b724d86bbcf6fc64c5e2b22
Content-Type: application/json

代码修改方案

方案 A简单封装推荐

在 Service 层创建一个包装类来管理鉴权信息:

public class TencentDocAuth {
    private String accessToken;
    private String clientId;
    private String openId;
    private long expiresAt;
    
    // 获取或刷新 Token
    public static TencentDocAuth getAuth(String appId, String appSecret) {
        JSONObject tokenInfo = TencentDocApiUtil.getAppAccountToken(appId, appSecret);
        
        TencentDocAuth auth = new TencentDocAuth();
        auth.accessToken = tokenInfo.getString("access_token");
        auth.openId = tokenInfo.getString("user_id");
        auth.clientId = appId;
        auth.expiresAt = System.currentTimeMillis() + tokenInfo.getIntValue("expires_in") * 1000;
        
        return auth;
    }
    
    // Getters...
}

方案 B修改现有方法签名

修改 callApi 方法,添加必要的参数:

public static JSONObject callApi(String accessToken, String clientId, String openId, 
                                  String apiUrl, String method, String body) {
    conn.setRequestProperty("Access-Token", accessToken);
    conn.setRequestProperty("Client-Id", clientId);
    conn.setRequestProperty("Open-Id", openId);
    // ...
}

然后更新所有调用此方法的地方。

实现步骤

1. 添加获取应用级账号 Token 的方法

已在 TencentDocApiUtil.java 中添加:

public static JSONObject getAppAccountToken(String appId, String appSecret)

2. 修改 callApi 方法

已更新为:

public static JSONObject callApi(String accessToken, String clientId, String openId, 
                                  String apiUrl, String method, String body)

3. 更新所有调用点(待完成)

需要更新以下方法:

  • readSheetData()
  • writeSheetData()
  • appendSheetData()
  • getFileInfo()
  • getSheetList()

以及所有调用这些方法的 Service 类。

测试验证

1. 获取应用级账号 Token

JSONObject tokenInfo = TencentDocApiUtil.getAppAccountToken(
    "YOUR_CLIENT_ID",
    "YOUR_CLIENT_SECRET"
);

System.out.println("Access Token: " + tokenInfo.getString("access_token"));
System.out.println("Open-Id: " + tokenInfo.getString("user_id"));

2. 调用表格 API

String accessToken = tokenInfo.getString("access_token");
String clientId = "YOUR_CLIENT_ID";
String openId = tokenInfo.getString("user_id");

JSONObject result = TencentDocApiUtil.readSheetData(
    accessToken, clientId, openId,
    "YOUR_FILE_ID", "SHEET_ID", "A1:Z10",
    "https://docs.qq.com/openapi/spreadsheet/v3"
);

注意事项

1. Token 有效期

应用级账号 Token 默认有效期为 3 天259200秒需要定期刷新。

2. 存储安全

  • client_secret 必须保密
  • Token 应该缓存并在过期前刷新
  • 不要在日志中打印完整的 Token

3. 权限范围

应用级账号的权限取决于申请时的 scope

  • scope.sheet - 读取表格
  • scope.sheet.editable - 编辑表格
  • scope.file.editable - 编辑文件
  • scope.folder.creatable - 创建文件夹

错误排查

401 Unauthorized

  • 检查 Access-Token 是否正确
  • 检查 Token 是否过期
  • 检查是否包含所有三个请求头

403 Forbidden

  • 检查应用是否有相应的权限 (scope)
  • 检查 Open-Id 是否正确

404 Not Found

  • 检查 URL 路径是否正确
  • 确认基础 URL 为 https://docs.qq.com/openapi/spreadsheet/v3
  • 确认路径格式为 /files/{fileId}/...

参考文档


更新时间2025-11-05
状态:部分完成,需要更新所有调用点