package com.ruoyi.jarvis.util; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; /** * WPS365 API工具类 * * @author system */ public class WPS365ApiUtil { private static final Logger log = LoggerFactory.getLogger(WPS365ApiUtil.class); // 静态初始化块:禁用系统代理 static { System.setProperty("java.net.useSystemProxies", "false"); System.clearProperty("http.proxyHost"); System.clearProperty("http.proxyPort"); System.clearProperty("https.proxyHost"); System.clearProperty("https.proxyPort"); log.info("已禁用系统代理设置,WPS365 API将直接连接"); } /** * 获取访问令牌 * * @param appId 应用ID * @param appKey 应用密钥 * @param code 授权码 * @param redirectUri 回调地址 * @param tokenUrl Token地址 * @return 包含access_token和refresh_token的JSON对象 */ public static JSONObject getAccessToken(String appId, String appKey, String code, String redirectUri, String tokenUrl) { try { // 构建请求参数 StringBuilder params = new StringBuilder(); params.append("grant_type=authorization_code"); params.append("&client_id=").append(appId); params.append("&client_secret=").append(appKey); params.append("&code=").append(code); params.append("&redirect_uri=").append(java.net.URLEncoder.encode(redirectUri, "UTF-8")); // 使用HttpURLConnection,不使用代理 URL url = new URL(tokenUrl); java.net.Proxy proxy = java.net.Proxy.NO_PROXY; HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Accept", "application/json"); conn.setDoOutput(true); conn.setDoInput(true); conn.setConnectTimeout(10000); conn.setReadTimeout(30000); // 写入请求参数 try (OutputStream os = conn.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8)) { osw.write(params.toString()); osw.flush(); } // 读取响应 int statusCode = conn.getResponseCode(); BufferedReader reader; if (statusCode >= 200 && statusCode < 300) { reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); } else { reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8)); } StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); String responseStr = response.toString(); log.info("获取访问令牌响应: statusCode={}, response={}", statusCode, responseStr); if (statusCode < 200 || statusCode >= 300) { throw new RuntimeException("获取访问令牌失败: HTTP " + statusCode + ", response=" + responseStr); } return JSON.parseObject(responseStr); } catch (Exception e) { log.error("获取访问令牌失败", e); throw new RuntimeException("获取访问令牌失败: " + e.getMessage(), e); } } /** * 刷新访问令牌 * * @param appId 应用ID * @param appKey 应用密钥 * @param refreshToken 刷新令牌 * @param refreshTokenUrl 刷新令牌地址 * @return 包含新的access_token和refresh_token的JSON对象 */ public static JSONObject refreshAccessToken(String appId, String appKey, String refreshToken, String refreshTokenUrl) { try { // 构建请求参数 StringBuilder params = new StringBuilder(); params.append("grant_type=refresh_token"); params.append("&client_id=").append(appId); params.append("&client_secret=").append(appKey); params.append("&refresh_token=").append(refreshToken); // 使用HttpURLConnection,不使用代理 URL url = new URL(refreshTokenUrl); java.net.Proxy proxy = java.net.Proxy.NO_PROXY; HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Accept", "application/json"); conn.setDoOutput(true); conn.setDoInput(true); conn.setConnectTimeout(10000); conn.setReadTimeout(30000); // 写入请求参数 try (OutputStream os = conn.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8)) { osw.write(params.toString()); osw.flush(); } // 读取响应 int statusCode = conn.getResponseCode(); StringBuilder response = new StringBuilder(); try { BufferedReader reader; InputStream inputStream; if (statusCode >= 200 && statusCode < 300) { inputStream = conn.getInputStream(); } else { // 对于错误响应,尝试读取错误流 inputStream = conn.getErrorStream(); // 如果错误流为null,尝试读取正常流(某些服务器可能将错误信息放在正常流中) if (inputStream == null) { inputStream = conn.getInputStream(); } } // 如果输入流仍然为null,说明无法读取响应 if (inputStream == null) { log.warn("无法读取HTTP响应流,状态码: {}", statusCode); response.append("无法读取响应内容"); } else { reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); } } catch (Exception e) { log.error("读取HTTP响应失败", e); response.append("读取响应失败: ").append(e.getMessage()); } String responseStr = response.toString(); log.info("刷新访问令牌响应: statusCode={}, response={}", statusCode, responseStr); if (statusCode < 200 || statusCode >= 300) { throw new RuntimeException("刷新访问令牌失败: HTTP " + statusCode + ", response=" + responseStr); } return JSON.parseObject(responseStr); } catch (Exception e) { log.error("刷新访问令牌失败", e); throw new RuntimeException("刷新访问令牌失败: " + e.getMessage(), e); } } /** * 发送HTTP请求 * * @param method 请求方法(GET/POST/PUT/DELETE) * @param url 请求URL * @param accessToken 访问令牌 * @param body 请求体(JSON字符串,GET请求可为null) * @return 响应JSON对象 */ public static JSONObject httpRequest(String method, String url, String accessToken, String body) { try { log.debug("发送HTTP请求: method={}, url={}", method, url); URL requestUrl = new URL(url); java.net.Proxy proxy = java.net.Proxy.NO_PROXY; HttpURLConnection conn = (HttpURLConnection) requestUrl.openConnection(proxy); conn.setRequestMethod(method); conn.setRequestProperty("Accept", "application/json"); conn.setRequestProperty("Authorization", "Bearer " + accessToken); conn.setConnectTimeout(10000); conn.setReadTimeout(30000); if ("POST".equals(method) || "PUT".equals(method) || "PATCH".equals(method)) { conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); if (body != null && !body.isEmpty()) { try (OutputStream os = conn.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8)) { osw.write(body); osw.flush(); } } } // 读取响应 int statusCode = conn.getResponseCode(); StringBuilder response = new StringBuilder(); try { BufferedReader reader; InputStream inputStream; if (statusCode >= 200 && statusCode < 300) { inputStream = conn.getInputStream(); } else { // 对于错误响应,尝试读取错误流 inputStream = conn.getErrorStream(); // 如果错误流为null,尝试读取正常流(某些服务器可能将错误信息放在正常流中) if (inputStream == null) { inputStream = conn.getInputStream(); } } // 如果输入流仍然为null,说明无法读取响应 if (inputStream == null) { log.warn("无法读取HTTP响应流,状态码: {}", statusCode); response.append("无法读取响应内容"); } else { reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); } } catch (Exception e) { log.error("读取HTTP响应失败", e); response.append("读取响应失败: ").append(e.getMessage()); } String responseStr = response.toString(); log.info("HTTP响应: statusCode={}, url={}, response={}", statusCode, url, responseStr); if (statusCode < 200 || statusCode >= 300) { String errorMsg = String.format("HTTP请求失败: statusCode=%d, url=%s, response=%s", statusCode, url, responseStr); log.error(errorMsg); throw new RuntimeException(errorMsg); } if (responseStr == null || responseStr.trim().isEmpty()) { return new JSONObject(); } return JSON.parseObject(responseStr); } catch (Exception e) { log.error("HTTP请求失败: method={}, url={}", method, url, e); throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); } } }