refactor(qrLogin): 简化二维码生成逻辑,移除文件生成和请求

- 二维码内容改为自定义协议,前端生成base64二维码
- 不再生成微信小程序码图片文件,删除相关生成方法
- 不再生成公众号带参数二维码URL,前端使用扫码跳转URL
- 扫码跳转URL改为配置值,提供默认域名降级处理
- 删除了生成文件和请求微信API的多余代码和相关依赖
- 保持miniprogramQrCodeUrl和wechatQrCodeUrl为空,由前端自动处理
This commit is contained in:
2026-04-07 21:04:41 +08:00
parent 345afab954
commit d1ad38c69f
2 changed files with 80 additions and 5 deletions

View File

@@ -26,9 +26,12 @@ public class QrLoginGenerateResponse {
@Schema(description = "微信小程序页面路径")
private String miniprogramPath;
@Schema(description = "微信小程序码图片URL")
@Schema(description = "微信小程序码图片URL已废弃改用base64")
private String miniprogramQrCodeUrl;
@Schema(description = "微信小程序码图片Base64扫码后直接打开小程序优先使用")
private String miniprogramQrCode;
@Schema(description = "过期时间(秒)")
private Long expiresIn;

View File

@@ -4,6 +4,9 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.auto.dto.*;
@@ -22,8 +25,8 @@ import com.gxwebsoft.common.system.service.WxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import static com.gxwebsoft.common.core.constants.PlatformConstants.MP_OFFICIAL;
@@ -99,13 +102,82 @@ public class QrLoginServiceImpl implements QrLoginService {
response.setWechatScanUrl("https://websopy.websoft.top/wx-scan?token=" + token);
}
// 不再生成小程序码图片文件改为前端通过qrCodeContent生成base64二维码
// 不再生成公众号带参数二维码URL前端使用wechatScanUrl生成二维码
// miniprogramQrCodeUrl 和 wechatQrCodeUrl 保持null前端自动使用本地生成
// 生成小程序码通过微信API生成小程序码返回Base64图片扫码后直接打开小程序确认页面
try {
String miniprogramQrCodeBase64 = generateMiniprogramQrCode(token, tenantId);
if (StrUtil.isNotBlank(miniprogramQrCodeBase64)) {
response.setMiniprogramQrCode(miniprogramQrCodeBase64);
log.info("生成小程序码成功Base64长度: {}", miniprogramQrCodeBase64.length());
}
} catch (Exception e) {
log.error("生成小程序码失败: {}", e.getMessage(), e);
// 生成失败不影响主流程继续使用H5方式
}
return response;
}
/**
* 生成小程序码用于PC端扫码登录
* 调用微信API生成无限制小程序码返回Base64图片扫码后直接打开小程序确认页面
*
* @param token 扫码登录token
* @param tenantId 租户ID
* @return 小程序码图片Base64字符串
*/
private String generateMiniprogramQrCode(String token, Integer tenantId) {
try {
// 获取小程序access_token
String accessToken = wxService.getAccessToken(tenantId);
if (StrUtil.isBlank(accessToken)) {
log.warn("获取小程序access_token失败跳过生成小程序码");
return null;
}
// 调用微信API生成小程序码
String apiUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
HashMap<String, Object> params = new HashMap<>();
params.put("scene", "token=" + token); // 场景值,扫码后会透传
params.put("page", "pages/public/qr-confirm/index"); // 小程序确认页面路径
params.put("env_version", "release"); // 正式版小程序
params.put("width", 280); // 二维码宽度
params.put("auto_color", false); // 不自动配置颜色
HashMap<String, Object> lineColor = new HashMap<>();
lineColor.put("r", 0);
lineColor.put("g", 122);
lineColor.put("b", 255);
params.put("line_color", lineColor); // 二维码颜色
// 发送请求并获取二进制响应
byte[] imageBytes = HttpRequest.post(apiUrl)
.body(JSON.toJSONString(params))
.timeout(15000)
.execute().bytes();
// 判断是否返回图片二进制或错误JSON
if (imageBytes == null || imageBytes.length == 0) {
log.error("生成小程序码API返回空数据");
return null;
}
// 检查是否返回JSON错误微信API错误时会返回JSON
if (imageBytes.length < 100 && new String(imageBytes).startsWith("{")) {
JSONObject errorResult = JSON.parseObject(new String(imageBytes));
log.error("生成小程序码API返回错误: {}", errorResult);
return null;
}
// 将图片字节数组转换为Base64字符串
String base64Image = cn.hutool.core.codec.Base64.encode(imageBytes);
// 添加Data URI前缀使前端可以直接使用
return "data:image/png;base64," + base64Image;
} catch (Exception e) {
log.error("生成小程序码异常: {}", e.getMessage(), e);
return null;
}
}
@Override
public QrLoginStatusResponse checkQrLoginStatus(String token) {
if (StrUtil.isBlank(token)) {