Files
ruoyi-java/doc/腾讯文档API快速参考.md
2025-11-06 10:26:40 +08:00

399 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 腾讯文档 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