From e5a15f1b9fb4584159d6e0aad472720d51e6733d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 9 Sep 2025 00:53:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor(qrlogin):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=A0=81=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E7=A7=9F=E6=88=B7=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 QrLoginController 中添加 tenantId 参数 - 在 QrLoginService 接口中修改 generateQrLoginToken 方法签名,添加 tenantId 参数 - 重构 QrLoginServiceImpl 中的 generateQrLoginToken 方法,使用 WxService 获取 AccessToken - 新增 WxService 类,用于获取微信 AccessToken,并支持租户 ID --- .../auto/controller/QrLoginController.java | 2 +- .../auto/service/QrLoginService.java | 2 +- .../auto/service/impl/QrLoginServiceImpl.java | 75 ++---------- .../common/system/service/WxService.java | 110 ++++++++++++++++++ 4 files changed, 120 insertions(+), 69 deletions(-) create mode 100644 src/main/java/com/gxwebsoft/common/system/service/WxService.java diff --git a/src/main/java/com/gxwebsoft/auto/controller/QrLoginController.java b/src/main/java/com/gxwebsoft/auto/controller/QrLoginController.java index 5368fea..ad0de5b 100644 --- a/src/main/java/com/gxwebsoft/auto/controller/QrLoginController.java +++ b/src/main/java/com/gxwebsoft/auto/controller/QrLoginController.java @@ -35,7 +35,7 @@ public class QrLoginController extends BaseController { @PostMapping("/generate") public ApiResult generateQrLoginToken() { try { - QrLoginGenerateResponse response = qrLoginService.generateQrLoginToken(); + QrLoginGenerateResponse response = qrLoginService.generateQrLoginToken(getTenantId()); return success("生成成功", response); } catch (Exception e) { return fail(e.getMessage()); diff --git a/src/main/java/com/gxwebsoft/auto/service/QrLoginService.java b/src/main/java/com/gxwebsoft/auto/service/QrLoginService.java index 85ed28f..fbd854b 100644 --- a/src/main/java/com/gxwebsoft/auto/service/QrLoginService.java +++ b/src/main/java/com/gxwebsoft/auto/service/QrLoginService.java @@ -17,7 +17,7 @@ public interface QrLoginService { * * @return QrLoginGenerateResponse */ - QrLoginGenerateResponse generateQrLoginToken(); + QrLoginGenerateResponse generateQrLoginToken(Integer tenantId); /** * 检查扫码登录状态 diff --git a/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java b/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java index 13f4cfe..3bf7a1c 100644 --- a/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java +++ b/src/main/java/com/gxwebsoft/auto/service/impl/QrLoginServiceImpl.java @@ -14,8 +14,8 @@ import com.gxwebsoft.common.core.security.JwtSubject; import com.gxwebsoft.common.core.security.JwtUtil; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.system.entity.User; -import com.gxwebsoft.common.system.service.SettingService; import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.common.system.service.WxService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -47,15 +47,12 @@ public class QrLoginServiceImpl implements QrLoginService { private ConfigProperties configProperties; @Autowired - private SettingService settingService; + private WxService wxService; - @Autowired - private RedisTemplate redisTemplate; - - private static final String ACCESS_TOKEN_KEY = "WX_ACCESS_TOKEN"; + private static final String QR_LOGIN_TOKEN = "QR_LOGIN_TOKEN"; @Override - public QrLoginGenerateResponse generateQrLoginToken() { + public QrLoginGenerateResponse generateQrLoginToken(Integer tenantId) { // 生成唯一的扫码登录token String token = UUID.randomUUID().toString(true); @@ -85,7 +82,7 @@ public class QrLoginServiceImpl implements QrLoginService { // 生成微信小程序码 try { - String miniprogramQrCodeUrl = generateMiniprogramQrCode(token); + String miniprogramQrCodeUrl = generateMiniprogramQrCode(token,tenantId); response.setMiniprogramQrCodeUrl(miniprogramQrCodeUrl); } catch (Exception e) { log.warn("生成微信小程序码失败: {}", e.getMessage()); @@ -234,9 +231,10 @@ public class QrLoginServiceImpl implements QrLoginService { /** * 生成微信小程序码 */ - private String generateMiniprogramQrCode(String token) { + private String generateMiniprogramQrCode(String token, Integer tenantId) { try { - String accessToken = getWxAccessToken(); + // 使用公共的 WxService 获取 AccessToken + String accessToken = wxService.getAccessToken(tenantId); if (StrUtil.isBlank(accessToken)) { throw new RuntimeException("获取微信AccessToken失败"); } @@ -275,64 +273,7 @@ public class QrLoginServiceImpl implements QrLoginService { } } - /** - * 获取微信AccessToken - */ - private String getWxAccessToken() { - try { - String key = ACCESS_TOKEN_KEY + ":10048"; // 默认租户ID,可以根据需要调整 - // 从缓存获取 - String cachedToken = redisTemplate.opsForValue().get(key); - if (StrUtil.isNotBlank(cachedToken)) { - try { - JSONObject tokenData = JSON.parseObject(cachedToken); - String accessToken = tokenData.getString("access_token"); - if (StrUtil.isNotBlank(accessToken)) { - return accessToken; - } - } catch (Exception e) { - // 解析失败,可能是旧格式,直接使用 - if (!cachedToken.startsWith("{")) { - return cachedToken; - } - } - } - - // 缓存中没有,重新获取 - JSONObject setting = settingService.getBySettingKey("mp-weixin"); - if (setting == null) { - throw new RuntimeException("请先配置微信小程序"); - } - - String appId = setting.getString("appId"); - String appSecret = setting.getString("appSecret"); - if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) { - throw new RuntimeException("微信小程序配置不完整"); - } - - // 调用微信API获取AccessToken - String apiUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" - + appId + "&secret=" + appSecret; - String response = HttpRequest.get(apiUrl).execute().body(); - - JSONObject result = JSON.parseObject(response); - String accessToken = result.getString("access_token"); - if (StrUtil.isNotBlank(accessToken)) { - // 存入缓存 - JSONObject tokenData = new JSONObject(); - tokenData.put("access_token", accessToken); - tokenData.put("expires_in", result.get("expires_in")); - redisTemplate.opsForValue().set(key, tokenData.toJSONString(), 7000L, TimeUnit.SECONDS); - return accessToken; - } else { - throw new RuntimeException("获取AccessToken失败: " + response); - } - } catch (Exception e) { - log.error("获取微信AccessToken失败: {}", e.getMessage(), e); - return null; - } - } /** * 获取文件上传路径 diff --git a/src/main/java/com/gxwebsoft/common/system/service/WxService.java b/src/main/java/com/gxwebsoft/common/system/service/WxService.java new file mode 100644 index 0000000..e9b445c --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/WxService.java @@ -0,0 +1,110 @@ +package com.gxwebsoft.common.system.service; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +/** + * 微信公共服务类 + * + * @author 科技小王子 + * @since 2025-09-08 + */ +@Slf4j +@Service +public class WxService { + + @Autowired + private SettingService settingService; + + @Autowired + private RedisTemplate redisTemplate; + + private static final String ACCESS_TOKEN_KEY = "WX_ACCESS_TOKEN"; + + /** + * 获取微信AccessToken(使用默认租户) + */ + public String getAccessToken() { + return getAccessToken(null); + } + + /** + * 获取微信AccessToken(支持指定租户ID) + * + * @param tenantId 租户ID,为null时使用默认值 + * @return access_token + */ + public String getAccessToken(Integer tenantId) { + if (tenantId == null) { + tenantId = 10048; // 默认租户ID,可以根据需要调整 + } + + String key = ACCESS_TOKEN_KEY + ":" + tenantId; + + // 从缓存获取 + String cachedToken = redisTemplate.opsForValue().get(key); + if (StrUtil.isNotBlank(cachedToken)) { + try { + JSONObject tokenData = JSON.parseObject(cachedToken); + String accessToken = tokenData.getString("access_token"); + if (StrUtil.isNotBlank(accessToken)) { + log.debug("从缓存获取access_token: {}", accessToken); + return accessToken; + } + } catch (Exception e) { + // 解析失败,可能是旧格式,直接使用 + if (!cachedToken.startsWith("{")) { + log.debug("从缓存获取access_token(旧格式): {}", cachedToken); + return cachedToken; + } + log.warn("解析缓存的access_token失败: {}", e.getMessage()); + // 缓存数据异常,删除缓存,重新获取 + redisTemplate.delete(key); + } + } + + // 缓存中没有,重新获取 + try { + JSONObject setting = settingService.getBySettingKey("mp-weixin"); + if (setting == null) { + throw new RuntimeException("请先配置微信小程序"); + } + + String appId = setting.getString("appId"); + String appSecret = setting.getString("appSecret"); + if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) { + throw new RuntimeException("微信小程序配置不完整"); + } + + // 调用微信API获取AccessToken + String apiUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + + appId + "&secret=" + appSecret; + String response = HttpRequest.get(apiUrl).execute().body(); + + JSONObject result = JSON.parseObject(response); + String accessToken = result.getString("access_token"); + if (StrUtil.isNotBlank(accessToken)) { + // 存入缓存 + JSONObject tokenData = new JSONObject(); + tokenData.put("access_token", accessToken); + tokenData.put("expires_in", result.get("expires_in")); + redisTemplate.opsForValue().set(key, tokenData.toJSONString(), 7000L, TimeUnit.SECONDS); + log.info("获取新的access_token成功: {}", accessToken); + return accessToken; + } else { + throw new RuntimeException("获取AccessToken失败: " + response); + } + } catch (Exception e) { + log.error("获取微信AccessToken失败: {}", e.getMessage(), e); + throw new RuntimeException("获取微信AccessToken失败: " + e.getMessage()); + } + } +}