# 腾讯文档 API V3 快速参考指南 ## API 配置 ### 基础 URL ``` https://docs.qq.com/openapi/spreadsheet/v3 ``` ### 配置文件位置 - 开发环境:`ruoyi-admin/src/main/resources/application-dev.yml` - 生产环境:`ruoyi-admin/src/main/resources/application-prod.yml` - Java 配置:`ruoyi-system/src/main/java/com/ruoyi/jarvis/config/TencentDocConfig.java` ## 鉴权方式 ### V3 API 请求头(Spreadsheet 操作) ```http Access-Token: {access_token} Client-Id: {app_id} Open-Id: {open_id} Content-Type: application/json ``` ### OAuth2 用户信息请求头 ```http Authorization: Bearer {access_token} ``` ## 主要 API 端点 ### 1. 读取表格数据 ``` GET /files/{fileId}/{sheetId}/{range} ``` **示例**: ```java JSONObject result = TencentDocApiUtil.readSheetData( accessToken, appId, openId, fileId, sheetId, "A1:Z100", apiBaseUrl ); ``` ### 2. 写入表格数据 ``` PUT /files/{fileId}/batchUpdate ``` **示例**: ```java Object[][] values = { {"姓名", "年龄", "城市"}, {"张三", "25", "北京"} }; JSONObject result = TencentDocApiUtil.writeSheetData( accessToken, appId, openId, fileId, sheetId, "A1", values, apiBaseUrl ); ``` ### 3. 追加表格数据 ``` 自动计算位置 + PUT /files/{fileId}/batchUpdate ``` **示例**: ```java Object[][] values = { {"李四", "30", "上海"} }; JSONObject result = TencentDocApiUtil.appendSheetData( accessToken, appId, openId, fileId, sheetId, values, apiBaseUrl ); ``` ### 4. 获取文件信息 ``` GET /files/{fileId} ``` **示例**: ```java JSONObject result = TencentDocApiUtil.getFileInfo( accessToken, appId, openId, fileId, apiBaseUrl ); ``` ### 5. 获取工作表列表 ``` GET /files/{fileId} ``` **示例**: ```java JSONObject result = TencentDocApiUtil.getSheetList( accessToken, appId, openId, fileId, apiBaseUrl ); ``` ### 6. 获取用户信息(含 Open-Id) ``` GET https://docs.qq.com/oauth/v2/userinfo ``` **示例**: ```java JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken); String openId = userInfo.getString("openId"); ``` ## Service 层使用示例 ### 读取表格数据 ```java @Autowired private ITencentDocService tencentDocService; public void readData() { String accessToken = "..."; // 从授权流程获取 String fileId = "..."; // 表格文件ID String sheetId = "..."; // 工作表ID String range = "A1:Z100"; // 读取范围 JSONObject result = tencentDocService.readSheetData( accessToken, fileId, sheetId, range ); JSONArray values = result.getJSONArray("values"); // 处理数据... } ``` ### 写入表格数据 ```java public void writeData() { String accessToken = "..."; String fileId = "..."; String sheetId = "..."; String range = "A1"; Object[][] values = { {"列1", "列2", "列3"}, {"数据1", "数据2", "数据3"} }; JSONObject result = tencentDocService.writeSheetData( accessToken, fileId, sheetId, range, values ); } ``` ### 追加订单数据 ```java public void appendOrder(JDOrder order) { String accessToken = "..."; String fileId = "..."; String sheetId = "..."; JSONObject result = tencentDocService.appendLogisticsToSheet( accessToken, fileId, sheetId, order ); } ``` ## 常见参数说明 ### fileId(文件ID) - 从腾讯文档 URL 中获取 - 示例 URL:`https://docs.qq.com/sheet/DQXxxxxxxxxxxxxxx?tab=BB08J2` - fileId:`DQXxxxxxxxxxxxxxx` ### sheetId(工作表ID) - 从腾讯文档 URL 的 tab 参数中获取 - 示例 URL:`https://docs.qq.com/sheet/DQXxxxxxxxxxxxxxx?tab=BB08J2` - sheetId:`BB08J2` ### range(单元格范围) - 格式:`起始列字母 + 起始行号 : 结束列字母 + 结束行号` - 示例: - `A1:Z100` - 从 A1 到 Z100 的矩形区域 - `A1` - 单个单元格 - `A:A` - 整个 A 列 - `1:1` - 整个第 1 行 ### values(数据值) - 二维数组格式 - 示例: ```java // Java 数组 Object[][] values = { {"行1列1", "行1列2", "行1列3"}, {"行2列1", "行2列2", "行2列3"} }; // JSONArray JSONArray values = new JSONArray(); JSONArray row1 = new JSONArray(); row1.add("行1列1"); row1.add("行1列2"); values.add(row1); ``` ## OAuth2 授权流程 ### 1. 获取授权 URL ```java String authUrl = tencentDocService.getAuthUrl(); // 重定向用户到 authUrl 进行授权 ``` ### 2. 处理回调获取 Access Token ```java @GetMapping("/callback") public String callback(@RequestParam String code) { JSONObject tokenResponse = tencentDocService.getAccessTokenByCode(code); String accessToken = tokenResponse.getString("access_token"); String refreshToken = tokenResponse.getString("refresh_token"); Integer expiresIn = tokenResponse.getInteger("expires_in"); // 保存 tokens... return "授权成功"; } ``` ### 3. 刷新 Access Token ```java public void refreshToken(String refreshToken) { JSONObject tokenResponse = tencentDocService.refreshAccessToken(refreshToken); String newAccessToken = tokenResponse.getString("access_token"); String newRefreshToken = tokenResponse.getString("refresh_token"); // 更新保存的 tokens... } ``` ## 错误处理 ### 常见错误码 #### 401 Unauthorized - **原因**:Access Token 无效或过期 - **解决**:使用 Refresh Token 刷新 Access Token #### 403 Forbidden - **原因**:用户没有访问该文档的权限 - **解决**:检查文档权限设置,确保授权用户有访问权限 #### 404 Not Found - **原因**:文件ID或工作表ID不存在,或 API 路径错误 - **解决**: 1. 检查 fileId 和 sheetId 是否正确 2. 检查 API 基础路径配置是否为 `https://docs.qq.com/openapi/spreadsheet/v3` #### 429 Too Many Requests - **原因**:API 调用频率超过限制 - **解决**:实现请求限流和重试机制 ### 异常捕获示例 ```java try { JSONObject result = tencentDocService.readSheetData( accessToken, fileId, sheetId, range ); } catch (RuntimeException e) { if (e.getMessage().contains("401")) { // Token 过期,刷新 token refreshToken(savedRefreshToken); } else if (e.getMessage().contains("404")) { // 文件不存在 log.error("文件不存在: fileId={}", fileId); } else if (e.getMessage().contains("无法获取Open-Id")) { // Access Token 无效 log.error("Access Token 无效,需要重新授权"); } else { // 其他错误 log.error("API调用失败", e); } } ``` ## 性能优化建议 ### 1. Open-Id 缓存 当前实现在每次调用 API 前都会获取 Open-Id,建议添加缓存: ```java // 使用 Spring Cache @Cacheable(value = "openIdCache", key = "#accessToken") public String getOpenId(String accessToken) { JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken); return userInfo.getString("openId"); } ``` ### 2. Access Token 缓存和自动刷新 ```java // 在数据库或 Redis 中存储 token 及过期时间 public String getValidAccessToken(String userId) { TokenInfo tokenInfo = tokenRepository.findByUserId(userId); if (tokenInfo.isExpired()) { // 自动刷新 JSONObject newTokens = tencentDocService.refreshAccessToken( tokenInfo.getRefreshToken() ); tokenInfo.update(newTokens); tokenRepository.save(tokenInfo); } return tokenInfo.getAccessToken(); } ``` ### 3. 批量操作 对于多次写入,优先使用 `batchUpdate` API 一次性提交多个操作。 ## 调试技巧 ### 1. 启用详细日志 在 `application-dev.yml` 中设置: ```yaml logging: level: com.ruoyi.jarvis.util.TencentDocApiUtil: DEBUG com.ruoyi.jarvis.service.impl.TencentDocServiceImpl: DEBUG ``` ### 2. 查看完整请求和响应 `TencentDocApiUtil` 已包含详细的日志记录: - 请求 URL - 请求方法 - 请求体 - 响应状态码 - 响应内容 ### 3. 测试 API 连接 ```java @Test public void testConnection() { String accessToken = "your_test_token"; // 1. 测试获取用户信息 JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken); System.out.println("User Info: " + userInfo); // 2. 测试获取文件信息 String fileId = "your_test_file_id"; JSONObject fileInfo = tencentDocService.getFileInfo(accessToken, fileId); System.out.println("File Info: " + fileInfo); } ``` ## 官方文档链接 - [OAuth2 授权](https://docs.qq.com/open/document/app/oauth2/authorize.html) - [获取用户信息](https://docs.qq.com/open/document/app/oauth2/userinfo.html) - [表格 API 概览](https://docs.qq.com/open/document/app/openapi/v3/sheet/model/spreadsheet.html) - [批量更新表格](https://docs.qq.com/open/document/app/openapi/v3/sheet/batchUpdate.html) ## 技术支持 如遇到问题,请查看: 1. 项目文档目录下的 `腾讯文档API完整修复总结.md` 2. 项目日志文件(位于 `logs/` 目录) 3. 腾讯文档开放平台官方文档 --- **最后更新时间**:2025-11-05