12 KiB
12 KiB
腾讯文档API完整修复总结
修复日期
2025-11-05
修复概述
针对腾讯文档开放平台 V3 API 集成,完成了以下全面修复:
- 修正了 API 基础路径配置
- 修正了 API 端点路径结构
- 修正了鉴权方式(从 Authorization: Bearer 改为三个独立请求头)
- 更新了所有 Service 层调用以支持新的鉴权方式
修复详情
1. API 基础路径修复
修改文件
ruoyi-system/src/main/java/com/ruoyi/jarvis/config/TencentDocConfig.javaruoyi-admin/src/main/resources/application-dev.ymlruoyi-admin/src/main/resources/application-prod.yml
修改内容
// 修改前
private String apiBaseUrl = "https://docs.qq.com/open/v1";
// 修改后
private String apiBaseUrl = "https://docs.qq.com/openapi/spreadsheet/v3";
配置文件修改
# application-dev.yml 和 application-prod.yml
# 修改前
api-base-url: https://docs.qq.com/open/v1
# 修改后
api-base-url: https://docs.qq.com/openapi/spreadsheet/v3
2. API 端点路径结构修复
修改文件
ruoyi-system/src/main/java/com/ruoyi/jarvis/util/TencentDocApiUtil.java
修改的 API 端点
2.1 读取表格数据 (readSheetData)
// 修改前
String apiUrl = String.format("%s/spreadsheets/%s/%s/%s", apiBaseUrl, fileId, sheetId, range);
// 修改后
String apiUrl = String.format("%s/files/%s/%s/%s", apiBaseUrl, fileId, sheetId, range);
// 完整路径示例:
// https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}/{sheetId}/{range}
2.2 写入表格数据 (writeSheetData)
// 修改前
String apiUrl = String.format("%s/spreadsheets/%s/batchUpdate", apiBaseUrl, fileId);
// 修改后
String apiUrl = String.format("%s/files/%s/batchUpdate", apiBaseUrl, fileId);
// 完整路径示例:
// https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}/batchUpdate
2.3 追加表格数据 (appendSheetData)
// 修改前
String infoUrl = String.format("%s/spreadsheets/%s", apiBaseUrl, fileId);
// 修改后
String infoUrl = String.format("%s/files/%s", apiBaseUrl, fileId);
// 完整路径示例:
// https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}
2.4 获取文件信息 (getFileInfo)
// 修改前
String apiUrl = String.format("%s/spreadsheets/%s", apiBaseUrl, fileId);
// 修改后
String apiUrl = String.format("%s/files/%s", apiBaseUrl, fileId);
// 完整路径示例:
// https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}
2.5 获取工作表列表 (getSheetList)
// 修改前
String apiUrl = String.format("%s/spreadsheets/%s", apiBaseUrl, fileId);
// 修改后
String apiUrl = String.format("%s/files/%s", apiBaseUrl, fileId);
// 完整路径示例:
// https://docs.qq.com/openapi/spreadsheet/v3/files/{fileId}
3. 鉴权方式修复
3.1 callApi 方法签名修改
// 修改前
public static JSONObject callApi(String accessToken, String apiUrl, String method, String body)
// 修改后
public static JSONObject callApi(String accessToken, String clientId, String openId, String apiUrl, String method, String body)
3.2 请求头修改
// 修改前(错误的鉴权方式)
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
// 修改后(正确的鉴权方式)
conn.setRequestProperty("Access-Token", accessToken);
conn.setRequestProperty("Client-Id", clientId);
conn.setRequestProperty("Open-Id", openId);
3.3 新增辅助方法
getUserInfo 方法
用于获取用户信息(包含 Open-Id),使用传统的 Authorization: Bearer 鉴权方式。
/**
* 获取用户信息(包含Open-Id)
*
* @param accessToken 访问令牌
* @return 用户信息(包含 openId 字段)
*/
public static JSONObject getUserInfo(String accessToken) {
// 腾讯文档用户信息接口:https://docs.qq.com/open/document/app/oauth2/userinfo.html
// 注意:此接口使用不同的鉴权方式(Authorization: Bearer)
String apiUrl = "https://docs.qq.com/oauth/v2/userinfo";
return callApiLegacy(accessToken, apiUrl, "GET", null);
}
callApiLegacy 方法
用于支持旧版 OAuth2 用户信息接口的 Authorization: Bearer 鉴权方式。
/**
* 调用腾讯文档API(使用传统的 Authorization: Bearer 鉴权方式)
* 仅用于 OAuth2 用户信息接口
*/
private static JSONObject callApiLegacy(String accessToken, String apiUrl, String method, String body) {
try {
// ... 连接设置 ...
conn.setRequestMethod(method);
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Content-Type", "application/json");
// ... 处理请求和响应 ...
} catch (Exception e) {
// ... 错误处理 ...
}
}
4. Service 层更新
修改文件
ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocServiceImpl.java
修改的方法
所有与腾讯文档 API 交互的方法都进行了更新,在调用 API 前先获取 Open-Id:
4.1 uploadLogisticsToSheet 方法
@Override
public JSONObject uploadLogisticsToSheet(String accessToken, String fileId, String sheetId, List<JDOrder> orders) {
try {
// ... 参数验证 ...
// 获取用户信息(包含Open-Id)
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
String openId = userInfo.getString("openId");
if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id,请检查Access Token是否有效");
}
// ... 构建数据 ...
// 追加数据到表格
return TencentDocApiUtil.appendSheetData(
accessToken,
tencentDocConfig.getAppId(),
openId,
fileId,
sheetId,
values,
tencentDocConfig.getApiBaseUrl()
);
} catch (Exception e) {
// ... 错误处理 ...
}
}
4.2 appendLogisticsToSheet 方法
类似的修改模式:先获取 openId,然后传递给 API 调用。
4.3 readSheetData 方法
@Override
public JSONObject readSheetData(String accessToken, String fileId, String sheetId, String range) {
try {
// 获取用户信息(包含Open-Id)
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
String openId = userInfo.getString("openId");
if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id,请检查Access Token是否有效");
}
return TencentDocApiUtil.readSheetData(
accessToken,
tencentDocConfig.getAppId(),
openId,
fileId,
sheetId,
range,
tencentDocConfig.getApiBaseUrl()
);
} catch (Exception e) {
// ... 错误处理 ...
}
}
4.4 writeSheetData 方法
同样的模式。
4.5 getFileInfo 方法
同样的模式。
4.6 getSheetList 方法
同样的模式。
完整的修复清单
配置文件(3个)
- ✅
TencentDocConfig.java- 修正 API 基础路径 - ✅
application-dev.yml- 修正 API 基础路径 - ✅
application-prod.yml- 修正 API 基础路径
Util 工具类(1个)
- ✅
TencentDocApiUtil.java- 修正
callApi方法签名(添加 clientId, openId 参数) - 修正请求头设置(改用 Access-Token, Client-Id, Open-Id)
- 新增
getUserInfo方法(获取用户信息和 Open-Id) - 新增
callApiLegacy方法(支持旧版 OAuth2 接口) - 修正
readSheetData方法(更新 API 路径和参数) - 修正
writeSheetData方法(更新 API 路径和参数) - 修正
appendSheetData方法(更新 API 路径和参数) - 修正
getFileInfo方法(更新 API 路径和参数) - 修正
getSheetList方法(更新 API 路径和参数)
- 修正
Service 服务类(1个)
- ✅
TencentDocServiceImpl.java- 修正
uploadLogisticsToSheet方法(添加 Open-Id 获取逻辑) - 修正
appendLogisticsToSheet方法(添加 Open-Id 获取逻辑) - 修正
readSheetData方法(添加 Open-Id 获取逻辑) - 修正
writeSheetData方法(添加 Open-Id 获取逻辑) - 修正
getFileInfo方法(添加 Open-Id 获取逻辑) - 修正
getSheetList方法(添加 Open-Id 获取逻辑)
- 修正
官方文档参考
API 路径规范
基础URL:https://docs.qq.com/openapi/spreadsheet/v3
API 端点:
- 批量更新:POST /files/{fileId}/batchUpdate
- 获取文件信息:GET /files/{fileId}
- 读取表格数据:GET /files/{fileId}/{sheetId}/{range}
鉴权方式规范
根据官方文档(https://docs.qq.com/open/document/app/openapi/v3/sheet/batchUpdate.html), 所有 V3 API 请求必须包含以下三个请求头:
Access-Token: ACCESS_TOKEN
Client-Id: CLIENT_ID
Open-Id: OPEN_ID
Open-Id 获取
通过 OAuth2 用户信息接口获取:
GET https://docs.qq.com/oauth/v2/userinfo
Authorization: Bearer ACCESS_TOKEN
响应示例:
{
"openId": "用户的开放平台ID",
"unionId": "用户的联合ID",
"nickname": "用户昵称",
...
}
测试建议
1. 配置验证
# 检查配置文件中的 API 基础地址是否正确
grep "api-base-url" ruoyi-admin/src/main/resources/application-*.yml
2. 编译验证
cd ruoyi-java
mvn clean compile
3. 功能测试步骤
- 启动应用
- 进行 OAuth2 授权,获取 Access Token
- 调用
getUserInfoAPI,验证是否能正确获取 Open-Id - 调用
getFileInfoAPI,验证是否能正确访问文档 - 调用
readSheetDataAPI,验证是否能正确读取数据 - 调用
writeSheetDataAPI,验证是否能正确写入数据 - 调用
appendSheetDataAPI,验证是否能正确追加数据
4. 错误排查
如果仍然出现 404 错误:
- 检查 fileId 是否正确
- 检查 sheetId 是否正确
- 检查 Access Token 是否有效
- 检查 Open-Id 是否成功获取
- 检查网络连接和代理设置
如果出现 401 错误:
- 检查 Access Token 是否过期
- 检查 Client-Id (AppId) 是否正确
- 检查 Open-Id 是否正确
- 检查用户是否有权限访问该文档
注意事项
-
代理设置:代码中已添加
Proxy.NO_PROXY设置,确保直接连接腾讯文档 API,避免代理干扰。 -
Open-Id 获取:每次调用 V3 API 前都会先调用 getUserInfo 获取 Open-Id。如果频繁调用可能影响性能,建议后续优化为缓存机制。
-
错误处理:所有 API 调用都包含完善的错误处理和日志记录,便于问题排查。
-
API 版本:确保使用 V3 版本的 API,V1 和 V2 版本可能已经废弃或行为不同。
-
鉴权方式差异:
- V3 Spreadsheet API:使用
Access-Token,Client-Id,Open-Id三个请求头 - OAuth2 用户信息 API:使用
Authorization: Bearer {token}请求头
- V3 Spreadsheet API:使用
总结
本次修复完全基于腾讯文档开放平台官方 V3 API 文档,修正了以下核心问题:
- ✅ API 基础路径从
/open/v1修正为/openapi/spreadsheet/v3 - ✅ API 端点路径从
/spreadsheets/修正为/files/ - ✅ 鉴权方式从
Authorization: Bearer修正为Access-Token,Client-Id,Open-Id三个独立请求头 - ✅ Service 层所有调用都已更新以支持新的鉴权方式
- ✅ 新增
getUserInfo方法自动获取 Open-Id
所有修改已通过代码编译检查,无 lint 错误。接下来需要进行实际的集成测试以验证 API 调用是否正常。