diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocCallbackController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocCallbackController.java new file mode 100644 index 0000000..6d517ed --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocCallbackController.java @@ -0,0 +1,152 @@ +package com.ruoyi.web.controller.jarvis; + +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.jarvis.service.ITencentDocService; +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; + +/** + * 腾讯文档OAuth回调控制器(备用路径) + * 用于处理更简单的回调路径,避免前端路由拦截 + * + * @author system + */ +@RestController +@RequestMapping("/tendoc-callback") +public class TencentDocCallbackController extends BaseController { + + private static final Logger log = LoggerFactory.getLogger(TencentDocCallbackController.class); + + @Autowired + private ITencentDocService tencentDocService; + + @Autowired + private com.ruoyi.jarvis.service.ITencentDocTokenService tencentDocTokenService; + + /** + * OAuth回调 - 通过授权码获取访问令牌 + * 路径:/tendoc-callback + * 注意:在腾讯文档开放平台只需配置域名:jarvis.van333.cn(不能包含路径) + * 授权URL中的redirect_uri参数会自动使用配置中的完整URL:https://jarvis.van333.cn/tendoc-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("腾讯文档授权失败 - 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("收到腾讯文档授权回调(备用路径)- code: {}, state: {}", code, state); + + // 使用授权码换取access_token + com.alibaba.fastjson2.JSONObject tokenInfo = tencentDocService.getAccessTokenByCode(code); + + // 验证返回的token信息 + if (tokenInfo == null || !tokenInfo.containsKey("access_token")) { + log.error("获取访问令牌失败 - 响应数据: {}", tokenInfo); + return generateCallbackHtml(false, "获取访问令牌失败,响应数据格式不正确", null); + } + + String accessToken = tokenInfo.getString("access_token"); + String refreshToken = tokenInfo.getString("refresh_token"); + Integer expiresIn = tokenInfo.getIntValue("expires_in"); + + log.info("成功获取访问令牌 - access_token: {}", accessToken); + + // 自动保存token到后端 + try { + if (tencentDocTokenService instanceof com.ruoyi.jarvis.service.impl.TencentDocTokenServiceImpl) { + ((com.ruoyi.jarvis.service.impl.TencentDocTokenServiceImpl) tencentDocTokenService) + .setToken(accessToken, refreshToken, expiresIn); + log.info("访问令牌已自动保存到后端缓存"); + } + } catch (Exception e) { + log.error("保存访问令牌失败", e); + return generateCallbackHtml(false, "保存访问令牌失败: " + e.getMessage(), null); + } + + return generateCallbackHtml(true, "授权成功,访问令牌已自动保存", null); + } catch (Exception e) { + log.error("OAuth回调处理失败", e); + return generateCallbackHtml(false, "授权失败: " + e.getMessage(), null); + } + } + + /** + * 生成回调HTML页面 + */ + private String generateCallbackHtml(boolean success, String message, Object data) { + StringBuilder html = new StringBuilder(); + html.append(""); + html.append(""); + html.append("
"); + html.append(""); + html.append(""); + html.append("窗口将在3秒后自动关闭...
"); + html.append("