refactor(qrlogin): 重构二维码登录功能并添加租户支持
- 在 QrLoginController 中添加 tenantId 参数 - 在 QrLoginService 接口中修改 generateQrLoginToken 方法签名,添加 tenantId 参数 - 重构 QrLoginServiceImpl 中的 generateQrLoginToken 方法,使用 WxService 获取 AccessToken - 新增 WxService 类,用于获取微信 AccessToken,并支持租户 ID
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface QrLoginService {
|
||||
*
|
||||
* @return QrLoginGenerateResponse
|
||||
*/
|
||||
QrLoginGenerateResponse generateQrLoginToken();
|
||||
QrLoginGenerateResponse generateQrLoginToken(Integer tenantId);
|
||||
|
||||
/**
|
||||
* 检查扫码登录状态
|
||||
|
||||
@@ -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<String, String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件上传路径
|
||||
|
||||
110
src/main/java/com/gxwebsoft/common/system/service/WxService.java
Normal file
110
src/main/java/com/gxwebsoft/common/system/service/WxService.java
Normal file
@@ -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<String, String> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user