diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
index edf31f24aa..228e844367 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
* 全局错误码枚举
* 0-999 系统异常编码保留
*
- * 一般情况下,使用 HTTP 响应状态码 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
+ * 一般情况下,使用 HTTP 响应状态码 ...
* 虽然说,HTTP 响应状态码作为业务使用表达能力偏弱,但是使用在系统层面还是非常不错的
* 比较特殊的是,因为之前一直使用 0 作为成功,就不使用 200 啦。
*
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/AgisoConfig.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/AgisoConfig.java
new file mode 100644
index 0000000000..d8627209b0
--- /dev/null
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/AgisoConfig.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.kfc.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Data
+@ConfigurationProperties(prefix = "agiso")
+@Configuration
+public class AgisoConfig {
+
+ private String appid;
+
+ private String appsecret;
+}
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/OkHttpConfig.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/OkHttpConfig.java
new file mode 100644
index 0000000000..81342dec1d
--- /dev/null
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/config/OkHttpConfig.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.kfc.config;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import java.util.concurrent.TimeUnit;
+/**
+OkHttp 配置类,用于创建并注册 OkHttpClient 实例到 Spring 容器
+*/
+@Configuration
+public class OkHttpConfig {
+ /**
+ 定义 OkHttpClient 的 bean,设置超时时间和连接池等参数
+ */
+ @Bean
+ public OkHttpClient okHttpClient () {
+ // 连接池配置:最大空闲连接数 5 个,连接空闲超时 5 分钟
+ ConnectionPool connectionPool = new ConnectionPool (5, 5, TimeUnit.MINUTES);
+ return new OkHttpClient.Builder ()
+ .connectTimeout (30, TimeUnit.SECONDS)
+ .readTimeout (30, TimeUnit.SECONDS)
+ .writeTimeout (30, TimeUnit.SECONDS)
+ .connectionPool (connectionPool)
+ .retryOnConnectionFailure (true)
+ .build ();
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/AgisoAuthCallbackController.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/AgisoAuthCallbackController.java
index 3546bbb7be..32a059ca1d 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/AgisoAuthCallbackController.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/AgisoAuthCallbackController.java
@@ -44,7 +44,6 @@ public class AgisoAuthCallbackController {
@GetMapping("/get/code-url")
@Operation(summary = "生成阿奇索code认证url")
- @PermitAll
public CommonResult getCodeUrl() {
return success(agisoAuthService.generateAuthUrl());
}
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenData.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoData.java
similarity index 96%
rename from yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenData.java
rename to yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoData.java
index 28089fb04f..541ff233af 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenData.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoData.java
@@ -7,7 +7,7 @@ import lombok.Data;
* 授权成功后返回的AccessToken相关数据实体类
*/
@Data
-public class AccessTokenData {
+public class AgisoData {
/**
* 平台标识
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenResponse.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoResponse.java
similarity index 89%
rename from yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenResponse.java
rename to yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoResponse.java
index af5c1db4b8..0d4d015818 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AccessTokenResponse.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/controller/admin/agisoproxy/vo/AgisoResponse.java
@@ -7,7 +7,7 @@ import lombok.Data;
* 换取AccessToken的完整响应实体类
*/
@Data
-public class AccessTokenResponse {
+public class AgisoResponse {
/**
* 操作是否成功
@@ -31,5 +31,5 @@ public class AccessTokenResponse {
* 详细数据(成功时返回)
*/
@JsonProperty("Data")
- private AccessTokenData data;
+ private AgisoData data;
}
\ No newline at end of file
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/enums/ErrorCodeConstants.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/enums/ErrorCodeConstants.java
index 30da95b8c3..4c0ef0af4e 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/enums/ErrorCodeConstants.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/enums/ErrorCodeConstants.java
@@ -53,4 +53,7 @@ public interface ErrorCodeConstants {
ErrorCode RESPONSE_IS_EMPTY = new ErrorCode(2_001_013_000,"响应体为空");
ErrorCode TOKEN_IS_EMPTY = new ErrorCode(2_001_013_001,"响应数据中未包含有效的Token");
+ ErrorCode STATE_NOT_VALID = new ErrorCode(2_001_013_002,"回调失败:state参数无效或已过期");
+ ErrorCode TOKEN_AUTH_FAILED = new ErrorCode(2_001_013_003,"认证失败:token令牌无效或已过期");
+ ErrorCode USER_AUTH_FAILED = new ErrorCode(2_001_013_004,"用户授权失败");
}
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthService.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthService.java
index 9372adacd2..e125d770f6 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthService.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthService.java
@@ -1,9 +1,26 @@
package cn.iocoder.yudao.module.kfc.service.agiso;
+import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AgisoResponse;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+import java.util.Map;
+
public interface AgisoAuthService {
String generateAuthUrl();
String authAndGetAccessToken(String code, String state, String error);
+ AgisoResponse execute(String url, String method, Map params, String sellerOpenUid) throws IOException, NoSuchAlgorithmException;
+
+ AgisoResponse doPost(String url, Map params, String sellerOpenUid) throws NoSuchAlgorithmException;
+
+ AgisoResponse doGet(String url, Map params, String sellerOpenUid) throws NoSuchAlgorithmException;
+
+ AgisoResponse autoShipment(List tids, String sellerOpenUid) throws NoSuchAlgorithmException;
+
+ String sign(Map params, String appSecret)
+ throws NoSuchAlgorithmException;
}
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthServiceImpl.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthServiceImpl.java
index 80a1efb971..383bbdb6d1 100644
--- a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthServiceImpl.java
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/service/agiso/AgisoAuthServiceImpl.java
@@ -1,40 +1,41 @@
package cn.iocoder.yudao.module.kfc.service.agiso;
import cn.hutool.core.util.RandomUtil;
-import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AccessTokenData;
-import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AccessTokenResponse;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import cn.iocoder.yudao.module.kfc.config.AgisoConfig;
+import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AgisoData;
+import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AgisoResponse;
+import cn.iocoder.yudao.module.kfc.utils.HttpUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
-import okhttp3.HttpUrl;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-import org.springframework.beans.factory.annotation.Value;
+import okhttp3.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
-import java.util.Objects;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.kfc.enums.ErrorCodeConstants.RESPONSE_IS_EMPTY;
-import static cn.iocoder.yudao.module.kfc.enums.ErrorCodeConstants.TOKEN_IS_EMPTY;
+import static cn.iocoder.yudao.module.kfc.enums.ErrorCodeConstants.*;
+import static software.amazon.awssdk.http.HttpStatusCode.BAD_REQUEST;
@Service
@Slf4j
public class AgisoAuthServiceImpl implements AgisoAuthService {
- @Value("${agiso.appid}")
- private String APPID;
- @Value("${agiso.appsecret}")
- private String APPSECRET;
+ @Resource
+ private AgisoConfig agisoConfig;
- // Redis中存储state的前缀,过期时间10分钟(授权流程通常较短)
+ // Redis中存储state的前缀,过期时间10分钟
private static final String STATE_REDIS_KEY_PREFIX = "agiso:auth:state:";
+ private static final String TOKEN_REDIS_KEY_PREFIX = "agiso:token:";
private static final long STATE_EXPIRE_MINUTES = 10;
+ private static final String AUTO_SHIPMENTS_URL = "http://gw.api.agiso.com/alds/Trade/AldsProcessTrades";
@Resource
private RedisTemplate redisTemplate;
@@ -46,7 +47,7 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
private ObjectMapper objectMapper;
/**
- * 生成授权链接(新增方法,用于发起授权)
+ * 生成授权链接
*/
@Override
public String generateAuthUrl() {
@@ -56,7 +57,7 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
redisTemplate.opsForValue()
.set(STATE_REDIS_KEY_PREFIX + state, "VALID", STATE_EXPIRE_MINUTES, TimeUnit.MINUTES);
// 3. 拼接授权URL
- return "https://alds.agiso.com/authorize.aspx?appId=" + APPID + "&state=" + state;
+ return "https://alds.agiso.com/authorize.aspx?appId=" + agisoConfig.getAppid() + "&state=" + state;
}
/**
@@ -68,7 +69,7 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
String redisKey = STATE_REDIS_KEY_PREFIX + state;
if (!redisTemplate.hasKey(redisKey)) {
log.warn("授权回调失败,state校验不通过,state={}", state);
- return "回调失败:state参数无效或已过期";
+ throw exception(STATE_NOT_VALID);
}
// 校验通过后删除state,防止重复使用
redisTemplate.delete(redisKey);
@@ -76,33 +77,34 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
// 2. 处理授权失败场景
if (error != null) {
log.warn("用户授权失败,error={}", error);
- return "授权失败:" + error;
+ throw exception(USER_AUTH_FAILED);
}
// 3. 处理授权成功场景
if (code != null) {
- try {
- String accessToken = getAccessToken(code, state);
- log.info("授权成功,AccessToken已存储到redis");
- return "success";
- } catch (Exception e) {
- log.error("换取AccessToken失败,code={}", code, e);
- return "换取AccessToken失败:" + e.getMessage();
- }
- }
- return "err:回调参数异常";
+ //异步执行,不阻塞回调线程
+ CompletableFuture.runAsync(() -> {
+ try {
+ String accessToken = generateAccessToken(code, state);
+ log.info("授权成功,AccessToken已存储到redis");
+ } catch (Exception e) {
+ log.error("换取AccessToken失败,code={}", code, e);
+ }
+ });
+ }
+ return "success";
}
/**
* 用授权码code换取AccessToken
*/
- private String getAccessToken(String code, String state) throws IOException {
+ private String generateAccessToken(String code, String state) throws IOException {
// 1. 构建请求URL
HttpUrl url = Objects.requireNonNull(HttpUrl.parse("https://alds.agiso.com/auth/token")).newBuilder()
.addQueryParameter("code", code)
- .addQueryParameter("appId", APPID)
- .addQueryParameter("secret", APPSECRET)
+ .addQueryParameter("appId", agisoConfig.getAppid())
+ .addQueryParameter("secret", agisoConfig.getAppsecret())
.addQueryParameter("state", state) // 使用回调的state,保持一致
.build();
log.debug("请求AccessToken的URL:{}", url);
@@ -128,7 +130,7 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
}
// 6. 解析响应
- AccessTokenResponse tokenResponse = objectMapper.readValue(responseBody, AccessTokenResponse.class);
+ AgisoResponse tokenResponse = objectMapper.readValue(responseBody, AgisoResponse.class);
if (!tokenResponse.isSuccess()) {
throw new RuntimeException(String.format(
"接口返回失败,错误码:%d,错误信息:%s",
@@ -138,13 +140,13 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
}
// 7. 提取Token和相关信息
- AccessTokenData data = tokenResponse.getData();
+ AgisoData data = tokenResponse.getData();
if (data == null || data.getToken() == null || data.getToken().isEmpty()) {
throw exception(TOKEN_IS_EMPTY);
}
// 8. 缓存Token
- String cacheKey = "agiso:token:" + data.getSellerOpenUid();
+ String cacheKey = TOKEN_REDIS_KEY_PREFIX + data.getSellerOpenUid();
redisTemplate.opsForValue()
.set(cacheKey, data.getToken(), data.getExpiresIn(), TimeUnit.SECONDS);
log.info("AccessToken缓存成功,商家ID:{},过期时间:{}秒", data.getSellerOpenUid(), data.getExpiresIn());
@@ -152,4 +154,105 @@ public class AgisoAuthServiceImpl implements AgisoAuthService {
return data.getToken();
}
}
+
+ @Override
+ public AgisoResponse execute(String url, String method, Map params, String sellerOpenUid) throws NoSuchAlgorithmException {
+
+ if (params == null) params = new HashMap<>();
+
+ //从redis获取accessToken
+ String accessToken = redisTemplate.opsForValue().get(TOKEN_REDIS_KEY_PREFIX + sellerOpenUid);
+ if (accessToken == null) throw exception(TOKEN_AUTH_FAILED);
+
+ //构建公共请求参数
+ long timestamp = System.currentTimeMillis() / 1000;
+ params.put("timestamp", Long.toString(timestamp));
+ params.put("sign",sign(params,agisoConfig.getAppsecret()));
+
+ //构建公共请求头
+ Map headers = new HashMap<>();
+ headers.put("Authorization", "Bearer " + accessToken);
+ headers.put("ApiVersion", "1");
+ //执行请求
+ return HttpUtils.execute(url,method, headers, params);
+ }
+
+ @Override
+ public AgisoResponse doPost(String url, Map params, String sellerOpenUid) throws NoSuchAlgorithmException {
+ return execute(url,"POST",params,sellerOpenUid);
+ }
+
+ @Override
+ public AgisoResponse doGet(String url, Map params, String sellerOpenUid) throws NoSuchAlgorithmException {
+ return execute(url,"GET",params,sellerOpenUid);
+ }
+
+ @Override
+ public AgisoResponse autoShipment(List tids, String sellerOpenUid) throws NoSuchAlgorithmException {
+ // 校验参数
+
+ if (tids == null || tids.isEmpty()) {
+ log.warn("自动发货失败,订单ID列表为空");
+ AgisoResponse emptyResponse = new AgisoResponse();
+ emptyResponse.setSuccess(false);
+ emptyResponse.setErrorCode(BAD_REQUEST);
+ emptyResponse.setErrorMsg("订单ID列表不能为空");
+ return emptyResponse;
+ }
+
+ // 拼接订单ID字符串(去除最后一个逗号)
+ String tidsStr = String.join(",", tids);
+ log.debug("自动发货处理,订单ID列表:{},商家标识:{}", tidsStr, sellerOpenUid);
+
+ // 构建请求参数
+ Map params = new HashMap<>();
+ params.put("tids", tidsStr);
+
+ // 调用POST请求方法
+ return doPost(AUTO_SHIPMENTS_URL, params, sellerOpenUid);
+ }
+
+ /**
+ * 阿奇索签名算法
+ * @param params 业务参数
+ * @param appSecret appsecret
+ * @return 签名字符串
+ * @throws NoSuchAlgorithmException 未找到算法异常
+ */
+ @Override
+ public String sign(Map params, String appSecret) throws NoSuchAlgorithmException {
+ String[] keys = params.keySet().toArray(new String[0]);
+ Arrays.sort(keys);
+
+ StringBuilder query = new StringBuilder();
+ query.append(appSecret);
+ for (String key : keys) {
+ String value = params.get(key);
+ query.append(key).append(value);
+ }
+ query.append(appSecret);
+
+ byte[] md5byte = encryptMD5(query.toString());
+
+ return byte2hex(md5byte);
+ }
+
+ // byte数组转成16进制字符串
+ private String byte2hex(byte[] bytes) {
+ StringBuilder sign = new StringBuilder();
+ for (byte aByte : bytes) {
+ String hex = Integer.toHexString(aByte & 0xFF);
+ if (hex.length() == 1) {
+ sign.append("0");
+ }
+ sign.append(hex.toLowerCase());
+ }
+ return sign.toString();
+ }
+
+ // Md5摘要
+ private byte[] encryptMD5(String data) throws NoSuchAlgorithmException {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ return md5.digest(data.getBytes(StandardCharsets.UTF_8));
+ }
}
\ No newline at end of file
diff --git a/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/utils/HttpUtils.java b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/utils/HttpUtils.java
new file mode 100644
index 0000000000..b692e31c86
--- /dev/null
+++ b/yudao-module-kfc/src/main/java/cn/iocoder/yudao/module/kfc/utils/HttpUtils.java
@@ -0,0 +1,131 @@
+package cn.iocoder.yudao.module.kfc.utils;
+
+import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AgisoData;
+import cn.iocoder.yudao.module.kfc.controller.admin.agisoproxy.vo.AgisoResponse;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+public class HttpUtils {
+ // 单例OkHttpClient实例
+ private static final OkHttpClient client = new OkHttpClient.Builder()
+ .connectTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .writeTimeout(30, TimeUnit.SECONDS)
+ .build();
+
+ // 用于JSON反序列化的ObjectMapper
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ /**
+ * 通用HTTP请求执行方法,返回结构化的AgisoResponse
+ * @param url 请求URL
+ * @param method 请求方法(GET, POST, PUT, DELETE等)
+ * @param headers 请求头
+ * @param params 请求参数
+ * @return 结构化的AgisoResponse响应
+ */
+ public static AgisoResponse execute(String url, String method, Map headers, Map params) {
+ // 参数处理
+ if (params == null) {
+ params = new HashMap<>();
+ }
+ if (headers == null) {
+ headers = new HashMap<>();
+ }
+
+ // 构建请求体
+ RequestBody requestBody = null;
+ if ("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) {
+ FormBody.Builder formBuilder = new FormBody.Builder();
+ for (Map.Entry entry : params.entrySet()) {
+ formBuilder.add(entry.getKey(), entry.getValue());
+ }
+ requestBody = formBuilder.build();
+ }
+ // GET请求参数拼接
+ else if ("GET".equalsIgnoreCase(method) && !params.isEmpty()) {
+ url = url + (url.contains("?") ? "&" : "?") + buildQueryString(params);
+ }
+
+ // 构建请求
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(url);
+
+ // 添加请求头
+ for (Map.Entry entry : headers.entrySet()) {
+ requestBuilder.addHeader(entry.getKey(), entry.getValue());
+ }
+
+ // 设置请求方法
+ Request request;
+ if ("GET".equalsIgnoreCase(method)) {
+ request = requestBuilder.get().build();
+ } else if ("DELETE".equalsIgnoreCase(method)) {
+ request = requestBuilder.delete().build();
+ } else {
+ request = requestBuilder.method(method, requestBody).build();
+ }
+
+ // 执行请求并处理响应
+ try (Response response = client.newCall(request).execute()) {
+ String responseBody = response.body() != null ? response.body().string() : "";
+ log.debug("HTTP请求响应内容: {}", responseBody);
+
+ // 尝试将响应体反序列化为AgisoResponse
+ if (!responseBody.isEmpty()) {
+ return objectMapper.readValue(responseBody, AgisoResponse.class);
+ }
+
+ // 响应体为空时构建默认失败响应
+ AgisoResponse emptyResponse = new AgisoResponse();
+ emptyResponse.setSuccess(false);
+ emptyResponse.setErrorCode(response.code());
+ emptyResponse.setErrorMsg("响应体为空");
+ return emptyResponse;
+
+ } catch (IOException e) {
+ log.error("请求执行异常:{}", e.getMessage(), e);
+ // 异常时构建失败响应
+ AgisoResponse errorResponse = new AgisoResponse();
+ errorResponse.setSuccess(false);
+ errorResponse.setErrorCode(500);
+ errorResponse.setErrorMsg("请求异常:" + e.getMessage());
+ return errorResponse;
+ }
+ }
+
+ /**
+ * 简化的POST请求方法,返回结构化响应
+ */
+ public static AgisoResponse post(String url, Map headers, Map params) {
+ return execute(url, "POST", headers, params);
+ }
+
+ /**
+ * 简化的GET请求方法,返回结构化响应
+ */
+ public static AgisoResponse get(String url, Map headers, Map params) {
+ return execute(url, "GET", headers, params);
+ }
+
+ /**
+ * 构建查询字符串
+ */
+ private static String buildQueryString(Map params) {
+ StringBuilder sb = new StringBuilder();
+ for (Map.Entry entry : params.entrySet()) {
+ if (sb.length() > 0) {
+ sb.append("&");
+ }
+ sb.append(entry.getKey()).append("=").append(entry.getValue());
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml
index 9a08e2a98a..f204e0404b 100644
--- a/yudao-server/src/main/resources/application-local.yaml
+++ b/yudao-server/src/main/resources/application-local.yaml
@@ -272,6 +272,7 @@ pf4j:
# pluginsDir: /tmp/
pluginsDir: ../plugins
+# 阿奇索的配置
agiso:
appid: appid
appsecret: appsecret
\ No newline at end of file