1
This commit is contained in:
@@ -32,7 +32,8 @@ wps365:
|
||||
# 应用密钥(从WPS365开放平台获取)
|
||||
app-key: YOUR_APP_KEY
|
||||
# 授权回调地址(需要在WPS365开放平台配置)
|
||||
redirect-uri: https://your-domain.com/jarvis/wps365/oauth/callback
|
||||
# 注意:使用 /wps365-callback 路径,避免前端路由拦截
|
||||
redirect-uri: https://your-domain.com/wps365-callback
|
||||
# API基础地址(一般不需要修改)
|
||||
api-base-url: https://open.wps.cn/api/v1
|
||||
# OAuth授权地址(一般不需要修改)
|
||||
@@ -43,6 +44,11 @@ wps365:
|
||||
refresh-token-url: https://open.wps.cn/oauth2/v1/token
|
||||
```
|
||||
|
||||
**重要提示**:
|
||||
- 回调地址使用 `/wps365-callback` 而不是 `/jarvis/wps365/oauth/callback`
|
||||
- 这样可以避免前端路由拦截,确保OAuth回调能正常访问
|
||||
- 在WPS365开放平台配置时,只需配置域名(如:`jarvis.van333.cn`),回调路径会自动使用配置中的完整URL
|
||||
|
||||
## API接口说明
|
||||
|
||||
### 1. 获取授权URL
|
||||
@@ -67,13 +73,19 @@ window.open(authUrl, '_blank')
|
||||
|
||||
### 2. OAuth回调处理
|
||||
|
||||
**接口**: `GET /jarvis/wps365/oauth/callback`
|
||||
**接口**: `GET /wps365-callback`
|
||||
|
||||
**参数**:
|
||||
- `code`: 授权码(由WPS365回调时自动传入)
|
||||
- `state`: 状态参数(可选)
|
||||
- `error`: 错误码(授权失败时)
|
||||
- `error_description`: 错误描述(授权失败时)
|
||||
|
||||
**说明**: 此接口处理WPS365的授权回调,自动获取并保存Token。
|
||||
**说明**:
|
||||
- 此接口处理WPS365的授权回调,自动获取并保存Token
|
||||
- 返回HTML页面,显示授权结果
|
||||
- 使用 `/wps365-callback` 路径避免前端路由拦截
|
||||
- 授权成功后会显示成功页面,3秒后自动关闭窗口
|
||||
|
||||
### 3. 获取Token状态
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
package com.ruoyi.web.controller.jarvis;
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.jarvis.domain.dto.WPS365TokenInfo;
|
||||
import com.ruoyi.jarvis.service.IWPS365OAuthService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* WPS365 OAuth回调控制器
|
||||
* 用于处理OAuth回调,避免前端路由拦截
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/wps365-callback")
|
||||
public class WPS365CallbackController extends BaseController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WPS365CallbackController.class);
|
||||
|
||||
@Autowired
|
||||
private IWPS365OAuthService wps365OAuthService;
|
||||
|
||||
/**
|
||||
* OAuth回调 - 通过授权码获取访问令牌
|
||||
* 路径:/wps365-callback
|
||||
* 注意:在WPS365开放平台只需配置域名:jarvis.van333.cn(不能包含路径)
|
||||
* 授权URL中的redirect_uri参数会自动使用配置中的完整URL:https://jarvis.van333.cn/wps365-callback
|
||||
*/
|
||||
@Anonymous
|
||||
@GetMapping(produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String oauthCallback(@RequestParam(value = "code", required = false) String code,
|
||||
@RequestParam(value = "state", required = false) String state,
|
||||
@RequestParam(value = "error", required = false) String error,
|
||||
@RequestParam(value = "error_description", required = false) String errorDescription) {
|
||||
try {
|
||||
// 处理授权错误
|
||||
if (error != null) {
|
||||
log.error("WPS365授权失败 - error: {}, error_description: {}", error, errorDescription);
|
||||
String errorMsg = errorDescription != null ? errorDescription : error;
|
||||
return generateCallbackHtml(false, "授权失败: " + errorMsg, null);
|
||||
}
|
||||
|
||||
// 验证授权码
|
||||
if (code == null || code.trim().isEmpty()) {
|
||||
log.error("授权码为空");
|
||||
return generateCallbackHtml(false, "授权码不能为空", null);
|
||||
}
|
||||
|
||||
log.info("收到WPS365授权回调 - code: {}, state: {}", code, state);
|
||||
|
||||
// 使用授权码换取access_token
|
||||
WPS365TokenInfo tokenInfo = wps365OAuthService.getAccessTokenByCode(code);
|
||||
|
||||
// 验证返回的token信息
|
||||
if (tokenInfo == null || tokenInfo.getAccessToken() == null) {
|
||||
log.error("获取访问令牌失败 - tokenInfo: {}", tokenInfo);
|
||||
return generateCallbackHtml(false, "获取访问令牌失败,响应数据格式不正确", null);
|
||||
}
|
||||
|
||||
log.info("成功获取访问令牌 - userId: {}, access_token: {}",
|
||||
tokenInfo.getUserId(),
|
||||
tokenInfo.getAccessToken() != null ? tokenInfo.getAccessToken().substring(0, 20) + "..." : "null");
|
||||
|
||||
// 自动保存token到后端
|
||||
try {
|
||||
if (tokenInfo.getUserId() != null) {
|
||||
wps365OAuthService.saveToken(tokenInfo.getUserId(), tokenInfo);
|
||||
log.info("访问令牌已自动保存到后端缓存 - userId: {}", tokenInfo.getUserId());
|
||||
} else {
|
||||
log.warn("userId为空,无法保存Token");
|
||||
return generateCallbackHtml(false, "获取用户ID失败,无法保存Token", null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("保存访问令牌失败", e);
|
||||
return generateCallbackHtml(false, "保存访问令牌失败: " + e.getMessage(), null);
|
||||
}
|
||||
|
||||
return generateCallbackHtml(true, "授权成功,访问令牌已自动保存", tokenInfo);
|
||||
} catch (Exception e) {
|
||||
log.error("OAuth回调处理失败", e);
|
||||
return generateCallbackHtml(false, "授权失败: " + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成回调HTML页面
|
||||
*/
|
||||
private String generateCallbackHtml(boolean success, String message, WPS365TokenInfo tokenInfo) {
|
||||
StringBuilder html = new StringBuilder();
|
||||
html.append("<!DOCTYPE html>");
|
||||
html.append("<html lang='zh-CN'>");
|
||||
html.append("<head>");
|
||||
html.append("<meta charset='UTF-8'>");
|
||||
html.append("<meta name='viewport' content='width=device-width, initial-scale=1.0'>");
|
||||
html.append("<title>WPS365授权").append(success ? "成功" : "失败").append("</title>");
|
||||
html.append("<style>");
|
||||
html.append("body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; ");
|
||||
html.append("display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; ");
|
||||
html.append("background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }");
|
||||
html.append(".container { background: white; padding: 40px; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); text-align: center; max-width: 500px; }");
|
||||
html.append(".icon { font-size: 64px; margin-bottom: 20px; }");
|
||||
html.append(".success { color: #52c41a; }");
|
||||
html.append(".error { color: #ff4d4f; }");
|
||||
html.append(".message { font-size: 16px; color: #333; margin-bottom: 20px; line-height: 1.6; }");
|
||||
html.append(".info { font-size: 14px; color: #666; margin-top: 20px; padding: 15px; background: #f5f5f5; border-radius: 5px; text-align: left; }");
|
||||
html.append("</style>");
|
||||
html.append("</head>");
|
||||
html.append("<body>");
|
||||
html.append("<div class='container'>");
|
||||
if (success) {
|
||||
html.append("<div class='icon success'>✓</div>");
|
||||
html.append("<h2 style='color: #52c41a; margin-bottom: 10px;'>授权成功</h2>");
|
||||
} else {
|
||||
html.append("<div class='icon error'>✗</div>");
|
||||
html.append("<h2 style='color: #ff4d4f; margin-bottom: 10px;'>授权失败</h2>");
|
||||
}
|
||||
html.append("<div class='message'>").append(message).append("</div>");
|
||||
|
||||
// 显示Token信息(仅成功时)
|
||||
if (success && tokenInfo != null) {
|
||||
html.append("<div class='info'>");
|
||||
html.append("<strong>授权信息:</strong><br>");
|
||||
if (tokenInfo.getUserId() != null) {
|
||||
html.append("用户ID: ").append(tokenInfo.getUserId()).append("<br>");
|
||||
}
|
||||
if (tokenInfo.getExpiresIn() != null) {
|
||||
html.append("有效期: ").append(tokenInfo.getExpiresIn()).append(" 秒<br>");
|
||||
}
|
||||
html.append("</div>");
|
||||
}
|
||||
|
||||
html.append("<p style='color: #999; font-size: 14px; margin-top: 20px;'>窗口将在3秒后自动关闭...</p>");
|
||||
html.append("</div>");
|
||||
html.append("<script>");
|
||||
html.append("// 通知父窗口授权结果");
|
||||
html.append("if (window.opener) {");
|
||||
html.append(" window.opener.postMessage({");
|
||||
html.append(" type: 'wps365_oauth_callback',");
|
||||
html.append(" success: ").append(success).append(",");
|
||||
html.append(" message: '").append(message.replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r")).append("'");
|
||||
if (success && tokenInfo != null && tokenInfo.getUserId() != null) {
|
||||
html.append(",");
|
||||
html.append(" userId: '").append(tokenInfo.getUserId()).append("'");
|
||||
}
|
||||
html.append(" }, '*');");
|
||||
html.append("}");
|
||||
html.append("// 3秒后自动关闭窗口");
|
||||
html.append("setTimeout(function() {");
|
||||
html.append(" if (window.opener) {");
|
||||
html.append(" window.close();");
|
||||
html.append(" } else {");
|
||||
html.append(" window.location.href = '/';");
|
||||
html.append(" }");
|
||||
html.append("}, 3000);");
|
||||
html.append("</script>");
|
||||
html.append("</body>");
|
||||
html.append("</html>");
|
||||
return html.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,13 +55,15 @@ public class WPS365Controller extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth回调处理
|
||||
* OAuth回调处理(已废弃,请使用 /wps365-callback)
|
||||
* 保留此接口用于兼容,实际回调请使用 WPS365CallbackController
|
||||
*/
|
||||
@Anonymous
|
||||
@GetMapping("/oauth/callback")
|
||||
public AjaxResult oauthCallback(@RequestParam String code,
|
||||
@RequestParam(required = false) String state) {
|
||||
try {
|
||||
log.warn("使用已废弃的回调接口 /jarvis/wps365/oauth/callback,建议使用 /wps365-callback");
|
||||
log.info("收到OAuth回调 - code: {}, state: {}", code, state);
|
||||
|
||||
// 通过授权码获取访问令牌
|
||||
|
||||
@@ -222,21 +222,5 @@ tencent:
|
||||
# 刷新Token地址(用于通过refresh_token刷新access_token)
|
||||
refresh-token-url: https://docs.qq.com/oauth/v2/token
|
||||
|
||||
# WPS365开放平台配置
|
||||
# 文档地址:https://open.wps.cn/
|
||||
wps365:
|
||||
# 应用ID(AppId)- 需要在WPS365开放平台申请
|
||||
app-id: YOUR_APP_ID
|
||||
# 应用密钥(AppKey)- 需要在WPS365开放平台申请,注意保密
|
||||
app-key: YOUR_APP_KEY
|
||||
# 授权回调地址(需要在WPS365开放平台配置授权域名)
|
||||
redirect-uri: https://jarvis.van333.cn/jarvis/wps365/oauth/callback
|
||||
# API基础地址
|
||||
api-base-url: https://open.wps.cn/api/v1
|
||||
# OAuth授权地址
|
||||
oauth-url: https://open.wps.cn/oauth2/v1/authorize
|
||||
# 获取Token地址
|
||||
token-url: https://open.wps.cn/oauth2/v1/token
|
||||
# 刷新Token地址
|
||||
refresh-token-url: https://open.wps.cn/oauth2/v1/token
|
||||
|
||||
|
||||
|
||||
@@ -9,3 +9,20 @@ tencent:
|
||||
push:
|
||||
# 延迟时间(分钟),默认10分钟
|
||||
minutes: 10
|
||||
# WPS365开放平台配置
|
||||
# 文档地址:https://open.wps.cn/
|
||||
wps365:
|
||||
# 应用ID(AppId)- 需要在WPS365开放平台申请
|
||||
app-id: AK20260114NNQJKV
|
||||
# 应用密钥(AppKey)- 需要在WPS365开放平台申请,注意保密
|
||||
app-key: 4c58bc1642e5e8fa731f75af9370496a
|
||||
# 授权回调地址(需要在WPS365开放平台配置授权域名)
|
||||
redirect-uri: https://jarvis.van333.cn/jarvis/wps365/oauth/callback
|
||||
# API基础地址
|
||||
api-base-url: https://open.wps.cn/api/v1
|
||||
# OAuth授权地址
|
||||
oauth-url: https://open.wps.cn/oauth2/v1/authorize
|
||||
# 获取Token地址
|
||||
token-url: https://open.wps.cn/oauth2/v1/token
|
||||
# 刷新Token地址
|
||||
refresh-token-url: https://open.wps.cn/oauth2/v1/token
|
||||
|
||||
Reference in New Issue
Block a user