fix(wx): 修复微信公众号扫码关注及登录流程中的数据处理问题

- 调整默认角色分配,从guest改为user以提升用户权限合理性
- 完善扫码关注事件的用户信息处理流程,确保unionid和subscribe状态正确管理
- 修复用户角色绑定逻辑,处理无角色或无效角色时重新分配默认角色
- 优化扫码登录状态更新日志打印,提升信息可读性
- 修正用户注册流程中角色获取失败时的默认角色设置
- 增加生成微信扫码登录二维码接口的稳定性和错误处理
- 统一日志输出格式,增加关键节点日志便于问题追踪
- 清理微信消息
This commit is contained in:
2026-04-07 01:53:21 +08:00
parent e73e0fb6b5
commit 181801abdb
2 changed files with 51 additions and 51 deletions

View File

@@ -13,5 +13,5 @@
} }
] ]
}, },
"lastUpdated": 1775497010453 "lastUpdated": 1775497544505
} }

View File

@@ -76,11 +76,11 @@ public class WxOfficialController extends BaseController {
private static final String QRCODE_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="; private static final String QRCODE_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=";
// 查看二维码接口 // 查看二维码接口
private static final String QRCODE_SHOW_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="; private static final String QRCODE_SHOW_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
// 微信服务器配置(从配置文件读取或使用默认值) // 微信服务器配置(从配置文件读取或使用默认值)
private static final String TOKEN = "gxwebsoft"; private static final String TOKEN = "gxwebsoft";
private static final String ENCODING_AES_KEY = "ARve4au5GF2fE2cT13xpaHhuqS2yjE34gpVe8IZwd4C"; private static final String ENCODING_AES_KEY = "ARve4au5GF2fE2cT13xpaHhuqS2yjE34gpVe8IZwd4C";
@Resource @Resource
private UserService userService; private UserService userService;
@Resource @Resource
@@ -135,11 +135,11 @@ public class WxOfficialController extends BaseController {
System.out.println("========== 接收微信消息 =========="); System.out.println("========== 接收微信消息 ==========");
System.out.println("tenantId = " + tenantId); System.out.println("tenantId = " + tenantId);
System.out.println("msg_signature = " + msg_signature); System.out.println("msg_signature = " + msg_signature);
// 从请求中获取XML数据 // 从请求中获取XML数据
String xmlData = IOUtils.toString(request.getInputStream(), "UTF-8"); String xmlData = IOUtils.toString(request.getInputStream(), "UTF-8");
System.out.println("原始xmlData = " + xmlData); System.out.println("原始xmlData = " + xmlData);
// 如果有加密参数,进行解密 // 如果有加密参数,进行解密
if (StrUtil.isNotBlank(msg_signature) && StrUtil.isNotBlank(xmlData) && xmlData.contains("Encrypt")) { if (StrUtil.isNotBlank(msg_signature) && StrUtil.isNotBlank(xmlData) && xmlData.contains("Encrypt")) {
try { try {
@@ -160,40 +160,40 @@ public class WxOfficialController extends BaseController {
return "error"; return "error";
} }
} }
// 解析XML数据 // 解析XML数据
Document document = XmlUtil.parseXml(xmlData); Document document = XmlUtil.parseXml(xmlData);
Element rootElement = XmlUtil.getRootElement(document); Element rootElement = XmlUtil.getRootElement(document);
// 获取消息类型 // 获取消息类型
Element msgTypeElement = XmlUtil.getElement(rootElement, "MsgType"); Element msgTypeElement = XmlUtil.getElement(rootElement, "MsgType");
String msgType = msgTypeElement != null ? msgTypeElement.getTextContent() : ""; String msgType = msgTypeElement != null ? msgTypeElement.getTextContent() : "";
System.out.println("msgType = " + msgType); System.out.println("msgType = " + msgType);
// 获取事件类型(如果是事件消息) // 获取事件类型(如果是事件消息)
Element eventElement = XmlUtil.getElement(rootElement, "Event"); Element eventElement = XmlUtil.getElement(rootElement, "Event");
String event = eventElement != null ? eventElement.getTextContent() : ""; String event = eventElement != null ? eventElement.getTextContent() : "";
System.out.println("event = " + event); System.out.println("event = " + event);
// 获取事件KEY用于判断是否是扫码事件 // 获取事件KEY用于判断是否是扫码事件
Element eventKeyElement = XmlUtil.getElement(rootElement, "EventKey"); Element eventKeyElement = XmlUtil.getElement(rootElement, "EventKey");
String eventKey = eventKeyElement != null ? eventKeyElement.getTextContent() : ""; String eventKey = eventKeyElement != null ? eventKeyElement.getTextContent() : "";
System.out.println("eventKey = " + eventKey); System.out.println("eventKey = " + eventKey);
// 获取用户openid // 获取用户openid
Element FromUserName = XmlUtil.getElement(rootElement, "FromUserName"); Element FromUserName = XmlUtil.getElement(rootElement, "FromUserName");
String openId = FromUserName != null ? FromUserName.getTextContent() : ""; String openId = FromUserName != null ? FromUserName.getTextContent() : "";
System.out.println("openId = " + openId); System.out.println("openId = " + openId);
// 获取 ticket扫码事件专用 // 获取 ticket扫码事件专用
Element ticketElement = XmlUtil.getElement(rootElement, "Ticket"); Element ticketElement = XmlUtil.getElement(rootElement, "Ticket");
String ticket = ticketElement != null ? ticketElement.getTextContent() : ""; String ticket = ticketElement != null ? ticketElement.getTextContent() : "";
System.out.println("ticket = " + ticket); System.out.println("ticket = " + ticket);
// 处理扫码关注事件 // 处理扫码关注事件
if ("event".equals(msgType) && ("subscribe".equals(event) || "SCAN".equals(event))) { if ("event".equals(msgType) && ("subscribe".equals(event) || "SCAN".equals(event))) {
System.out.println("========== 处理扫码关注事件 =========="); System.out.println("========== 处理扫码关注事件 ==========");
// 获取扫码的 token从 EventKey 中提取格式qrscene_xxx 或直接是 xxx // 获取扫码的 token从 EventKey 中提取格式qrscene_xxx 或直接是 xxx
String token = ""; String token = "";
if (StrUtil.isNotBlank(eventKey)) { if (StrUtil.isNotBlank(eventKey)) {
@@ -204,7 +204,7 @@ public class WxOfficialController extends BaseController {
} }
} }
System.out.println("扫码登录token = " + token); System.out.println("扫码登录token = " + token);
// 获取用户信息 // 获取用户信息
if (StrUtil.isNotBlank(openId)) { if (StrUtil.isNotBlank(openId)) {
// 获取用户基本信息(UnionID机制) // 获取用户基本信息(UnionID机制)
@@ -214,26 +214,26 @@ public class WxOfficialController extends BaseController {
final String subscribe = jsonObject.getString("subscribe"); final String subscribe = jsonObject.getString("subscribe");
System.out.println("unionid = " + unionid); System.out.println("unionid = " + unionid);
System.out.println("subscribe = " + subscribe); System.out.println("subscribe = " + subscribe);
Integer userId = processWxUser(tenantId, openId, unionid, subscribe); Integer userId = processWxUser(tenantId, openId, unionid, subscribe);
// 如果有关联的扫码登录token完成登录 // 如果有关联的扫码登录token完成登录
if (StrUtil.isNotBlank(token) && userId != null && userId > 0) { if (StrUtil.isNotBlank(token) && userId != null && userId > 0) {
completeQrLogin(token, userId, tenantId); completeQrLogin(token, userId, tenantId);
} }
} }
} }
// 返回 success 表示处理成功 // 返回 success 表示处理成功
return "success"; return "success";
} }
/** /**
* 处理微信用户(关注/注册/登录) * 处理微信用户(关注/注册/登录)
*/ */
private Integer processWxUser(Integer tenantId, String openId, String unionid, String subscribe) { private Integer processWxUser(Integer tenantId, String openId, String unionid, String subscribe) {
Integer userId = 0; Integer userId = 0;
// 关注操作 // 关注操作
if (subscribe != null && subscribe.equals("1")) { if (subscribe != null && subscribe.equals("1")) {
final int count = userOauthService.count(new LambdaQueryWrapper<UserOauth>() final int count = userOauthService.count(new LambdaQueryWrapper<UserOauth>()
@@ -241,7 +241,7 @@ public class WxOfficialController extends BaseController {
.eq(UserOauth::getUnionid, unionid) .eq(UserOauth::getUnionid, unionid)
.eq(UserOauth::getTenantId, tenantId)); .eq(UserOauth::getTenantId, tenantId));
System.out.println("已绑定用户数量 = " + count); System.out.println("已绑定用户数量 = " + count);
if (count == 0) { if (count == 0) {
// 检查其他平台是否有注册过 // 检查其他平台是否有注册过
final List<UserOauth> list = userOauthService.list( final List<UserOauth> list = userOauthService.list(
@@ -249,7 +249,7 @@ public class WxOfficialController extends BaseController {
.eq(UserOauth::getUnionid, unionid) .eq(UserOauth::getUnionid, unionid)
.eq(UserOauth::getDeleted, 0)); .eq(UserOauth::getDeleted, 0));
final int size = list.size(); final int size = list.size();
// 新用户注册 // 新用户注册
if (size == 0) { if (size == 0) {
User user = new User(); User user = new User();
@@ -263,7 +263,7 @@ public class WxOfficialController extends BaseController {
user.setRecommend(0); user.setRecommend(0);
final RoleParam roleParam = new RoleParam(); final RoleParam roleParam = new RoleParam();
roleParam.setTenantId(tenantId); roleParam.setTenantId(tenantId);
roleParam.setRoleCode("guest"); roleParam.setRoleCode("user");
Role role = roleService.getByRoleCode(roleParam); Role role = roleService.getByRoleCode(roleParam);
user.setRoleId(role.getRoleId()); user.setRoleId(role.getRoleId());
if (userService.saveUser(user)) { if (userService.saveUser(user)) {
@@ -285,7 +285,7 @@ public class WxOfficialController extends BaseController {
} }
System.out.println("新微信公众号用户 userId = " + userId); System.out.println("新微信公众号用户 userId = " + userId);
} }
// 更新 // 更新
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list)) {
for (UserOauth item : list) { for (UserOauth item : list) {
@@ -295,7 +295,7 @@ public class WxOfficialController extends BaseController {
} }
System.out.println("其他平台有注册过 userId = " + userId); System.out.println("其他平台有注册过 userId = " + userId);
} }
// 保存第三方用户记录 // 保存第三方用户记录
final UserOauth userOauth = new UserOauth(); final UserOauth userOauth = new UserOauth();
userOauth.setOauthType(MP_OFFICIAL); userOauth.setOauthType(MP_OFFICIAL);
@@ -338,10 +338,10 @@ public class WxOfficialController extends BaseController {
} }
} }
} }
return userId; return userId;
} }
/** /**
* 完成扫码登录 * 完成扫码登录
*/ */
@@ -385,10 +385,10 @@ public class WxOfficialController extends BaseController {
} }
redisUtil.set(redisKey, qrLoginData, ttlSeconds, TimeUnit.SECONDS); redisUtil.set(redisKey, qrLoginData, ttlSeconds, TimeUnit.SECONDS);
log.info("扫码登录状态已更新token={}, userId={}, status={}, needBindPhone={}, message={}, ttlSeconds={}", log.info("扫码登录状态已更新token={}, userId={}, status={}, needBindPhone={}, message={}, ttlSeconds={}",
token, userId, qrLoginData.getStatus(), qrLoginData.getNeedBindPhone(), token, userId, qrLoginData.getStatus(), qrLoginData.getNeedBindPhone(),
qrLoginData.getMessage(), ttlSeconds); qrLoginData.getMessage(), ttlSeconds);
System.out.println("扫码登录完成token=" + token + ", userId=" + userId + System.out.println("扫码登录完成token=" + token + ", userId=" + userId +
", status=" + qrLoginData.getStatus() + ", message=" + qrLoginData.getMessage()); ", status=" + qrLoginData.getStatus() + ", message=" + qrLoginData.getMessage());
} catch (Exception e) { } catch (Exception e) {
log.error("完成扫码登录失败", e); log.error("完成扫码登录失败", e);
@@ -400,32 +400,32 @@ public class WxOfficialController extends BaseController {
JwtSubject jwtSubject = new JwtSubject(user.getUsername(), user.getTenantId()); JwtSubject jwtSubject = new JwtSubject(user.getUsername(), user.getTenantId());
return JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(), configProperties.getTokenKey()); return JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(), configProperties.getTokenKey());
} }
@Operation(summary = "生成微信扫码登录二维码") @Operation(summary = "生成微信扫码登录二维码")
@GetMapping("/qrcode/{token}") @GetMapping("/qrcode/{token}")
public ApiResult<?> generateQrCode(@PathVariable("token") String token) { public ApiResult<?> generateQrCode(@PathVariable("token") String token) {
try { try {
// 生成带参数的二维码scene 为 token // 生成带参数的二维码scene 为 token
String url = QRCODE_CREATE_URL + getAccessToken(); String url = QRCODE_CREATE_URL + getAccessToken();
// 创建临时二维码有效期7天scene_str 最大32个可见字符 // 创建临时二维码有效期7天scene_str 最大32个可见字符
JSONObject params = new JSONObject(); JSONObject params = new JSONObject();
params.put("action_info", new JSONObject().put("scene", new JSONObject().put("scene_str", token))); params.put("action_info", new JSONObject().put("scene", new JSONObject().put("scene_str", token)));
params.put("action_name", "QR_STR_SCENE"); params.put("action_name", "QR_STR_SCENE");
params.put("expire_seconds", 604800); // 7天有效期 params.put("expire_seconds", 604800); // 7天有效期
String result = HttpRequest.post(url) String result = HttpRequest.post(url)
.body(params.toJSONString()) .body(params.toJSONString())
.timeout(10000) .timeout(10000)
.execute().body(); .execute().body();
System.out.println("生成二维码结果: " + result); System.out.println("生成二维码结果: " + result);
JSONObject jsonResult = JSONObject.parseObject(result); JSONObject jsonResult = JSONObject.parseObject(result);
if (jsonResult.containsKey("ticket")) { if (jsonResult.containsKey("ticket")) {
String ticket = jsonResult.getString("ticket"); String ticket = jsonResult.getString("ticket");
String qrCodeUrl = QRCODE_SHOW_URL + java.net.URLEncoder.encode(ticket, "UTF-8"); String qrCodeUrl = QRCODE_SHOW_URL + java.net.URLEncoder.encode(ticket, "UTF-8");
return success(qrCodeUrl); return success(qrCodeUrl);
} else { } else {
return fail("生成二维码失败: " + result); return fail("生成二维码失败: " + result);
@@ -644,7 +644,7 @@ public class WxOfficialController extends BaseController {
new LambdaQueryWrapper<UserOauth>() new LambdaQueryWrapper<UserOauth>()
.eq(UserOauth::getUnionid, unionid) .eq(UserOauth::getUnionid, unionid)
.eq(UserOauth::getDeleted, 0)); .eq(UserOauth::getDeleted, 0));
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list)) {
for (UserOauth item : list) { for (UserOauth item : list) {
if (item.getUserId() != null) { if (item.getUserId() != null) {
@@ -654,7 +654,7 @@ public class WxOfficialController extends BaseController {
} }
System.out.println("数据不一致通过unionid找到其他平台的用户 userId = " + userId); System.out.println("数据不一致通过unionid找到其他平台的用户 userId = " + userId);
} }
// 如果没找到用户,创建一个新用户 // 如果没找到用户,创建一个新用户
if (userId == 0) { if (userId == 0) {
User user = new User(); User user = new User();
@@ -666,7 +666,7 @@ public class WxOfficialController extends BaseController {
user.setPassword(userService.encodePassword(CommonUtil.randomUUID16())); user.setPassword(userService.encodePassword(CommonUtil.randomUUID16()));
user.setTenantId(tenantId); user.setTenantId(tenantId);
user.setRecommend(0); user.setRecommend(0);
// 尝试获取"user"角色,不行就用"guest"再不行用默认6 // 尝试获取"user"角色,不行就用"guest"再不行用默认6
Role role = null; Role role = null;
try { try {
@@ -685,9 +685,9 @@ public class WxOfficialController extends BaseController {
System.out.println("获取guest角色也失败使用默认角色ID 6"); System.out.println("获取guest角色也失败使用默认角色ID 6");
} }
} }
user.setRoleId(role != null ? role.getRoleId() : 6); user.setRoleId(role != null ? role.getRoleId() : 6);
if (userService.saveUser(user)) { if (userService.saveUser(user)) {
userId = user.getUserId(); userId = user.getUserId();
// 添加用户角色 // 添加用户角色
@@ -707,7 +707,7 @@ public class WxOfficialController extends BaseController {
} }
System.out.println("数据不一致:创建新用户 userId = " + userId); System.out.println("数据不一致:创建新用户 userId = " + userId);
} }
// 创建oauth记录 // 创建oauth记录
final UserOauth userOauth = new UserOauth(); final UserOauth userOauth = new UserOauth();
userOauth.setOauthType(MP_OFFICIAL); userOauth.setOauthType(MP_OFFICIAL);
@@ -717,7 +717,7 @@ public class WxOfficialController extends BaseController {
userOauth.setTenantId(tenantId); userOauth.setTenantId(tenantId);
boolean save = userOauthService.save(userOauth); boolean save = userOauthService.save(userOauth);
System.out.println("创建oauth记录修复数据不一致结果 = " + save); System.out.println("创建oauth记录修复数据不一致结果 = " + save);
return userId; return userId;
} }
@@ -730,10 +730,10 @@ public class WxOfficialController extends BaseController {
List<UserRole> userRoles = userRoleService.list(new LambdaQueryWrapper<UserRole>() List<UserRole> userRoles = userRoleService.list(new LambdaQueryWrapper<UserRole>()
.eq(UserRole::getUserId, user.getUserId()) .eq(UserRole::getUserId, user.getUserId())
.eq(UserRole::getTenantId, tenantId)); .eq(UserRole::getTenantId, tenantId));
if (CollectionUtils.isEmpty(userRoles)) { if (CollectionUtils.isEmpty(userRoles)) {
System.out.println("用户 " + user.getUserId() + " 没有角色绑定,尝试分配角色"); System.out.println("用户 " + user.getUserId() + " 没有角色绑定,尝试分配角色");
// 获取合适的角色 // 获取合适的角色
Role role = null; Role role = null;
// 先尝试获取"user"角色 // 先尝试获取"user"角色
@@ -753,20 +753,20 @@ public class WxOfficialController extends BaseController {
System.out.println("获取guest角色也失败使用默认角色ID 6"); System.out.println("获取guest角色也失败使用默认角色ID 6");
} }
} }
Integer roleId = role != null ? role.getRoleId() : 6; Integer roleId = role != null ? role.getRoleId() : 6;
// 创建用户角色绑定 // 创建用户角色绑定
final UserRole userRole = new UserRole(); final UserRole userRole = new UserRole();
userRole.setUserId(user.getUserId()); userRole.setUserId(user.getUserId());
userRole.setTenantId(tenantId); userRole.setTenantId(tenantId);
userRole.setRoleId(roleId); userRole.setRoleId(roleId);
userRoleService.save(userRole); userRoleService.save(userRole);
// 更新用户的roleId // 更新用户的roleId
user.setRoleId(roleId); user.setRoleId(roleId);
userService.updateUser(user); userService.updateUser(user);
System.out.println("为用户 " + user.getUserId() + " 分配了角色ID: " + roleId); System.out.println("为用户 " + user.getUserId() + " 分配了角色ID: " + roleId);
} else { } else {
// 检查角色的有效性 // 检查角色的有效性
@@ -783,7 +783,7 @@ public class WxOfficialController extends BaseController {
break; break;
} }
} }
if (!hasValidRole) { if (!hasValidRole) {
System.out.println("用户 " + user.getUserId() + " 的角色绑定无效,重新分配"); System.out.println("用户 " + user.getUserId() + " 的角色绑定无效,重新分配");
// 重新分配角色简化逻辑使用默认角色ID 6 // 重新分配角色简化逻辑使用默认角色ID 6
@@ -792,10 +792,10 @@ public class WxOfficialController extends BaseController {
userRole.setTenantId(tenantId); userRole.setTenantId(tenantId);
userRole.setRoleId(6); userRole.setRoleId(6);
userRoleService.save(userRole); userRoleService.save(userRole);
user.setRoleId(6); user.setRoleId(6);
userService.updateUser(user); userService.updateUser(user);
System.out.println("重新为用户 " + user.getUserId() + " 分配了默认角色ID: 6"); System.out.println("重新为用户 " + user.getUserId() + " 分配了默认角色ID: 6");
} }
} }