fix(system): 优化微信登录接口的响应处理和异常处理

- 改进了微信手机号和 access_token 获取接口的响应清理逻辑
- 增加了对响应格式的验证和错误处理
-优化了缓存 access_token 的存储和解析
- 提升了代码的健壮性和错误提示的详细性
This commit is contained in:
2025-09-04 23:18:01 +08:00
parent 54a840dea2
commit 0b88c39cab

View File

@@ -77,6 +77,40 @@ public class WxLoginController extends BaseController {
return success("操作成功", getAccessToken());
}
@ApiOperation("清理并统一AccessToken存储格式")
@PostMapping("/cleanAccessTokenFormat")
public ApiResult<String> cleanAccessTokenFormat() {
String key = ACCESS_TOKEN_KEY.concat(":").concat(getTenantId().toString());
String value = redisTemplate.opsForValue().get(key);
if (value != null) {
try {
// 尝试解析为JSON
JSONObject response = JSON.parseObject(value);
String accessToken = response.getString("access_token");
if (StrUtil.isNotBlank(accessToken)) {
return success("AccessToken格式已经是标准JSON格式", accessToken);
}
} catch (Exception e) {
// 如果是字符串格式转换为JSON格式
if (StrUtil.isNotBlank(value) && !value.startsWith("{")) {
JSONObject tokenData = new JSONObject();
tokenData.put("access_token", value);
tokenData.put("expires_in", 7200); // 默认2小时
// 重新存储为JSON格式
redisTemplate.opsForValue().set(key, tokenData.toJSONString(), 7000L, TimeUnit.SECONDS);
return success("已将字符串格式转换为JSON格式", value);
}
}
}
// 如果没有缓存或格式异常,重新获取
redisTemplate.delete(key);
String newToken = getAccessToken();
return success("已重新获取并统一格式", newToken);
}
@ApiOperation("获取微信openId")
@Transactional(rollbackFor = {Exception.class})
@PostMapping("/getOpenId")
@@ -112,9 +146,9 @@ public class WxLoginController extends BaseController {
redisTemplate.delete(key);
throw new BusinessException("授权失败,请重试");
}
// 查询是否存在
User user = userService.getAdminByPhone(userParam);
User user = null;
// 超级管理员验证
if (userParam.getIsSuperAdmin() != null) {
final LoginParam loginParam = new LoginParam();
@@ -124,23 +158,21 @@ public class WxLoginController extends BaseController {
if (!CollectionUtils.isEmpty(adminsByPhone)) {
user = adminsByPhone.get(0);
}
}
// 不存在则注册
if (user == null) {
if ((userParam.getOpenid() == null || userParam.getOpenid().isEmpty()) && userParam.getAuthCode() != null) {
UserParam userParam2 = new UserParam();
userParam2.setCode(userParam.getAuthCode());
JSONObject result = getOpenIdByCode(userParam2);
System.out.println("userInfo res:" + result);
String openid = result.getString("openid");
// String unionid = result.getString("unionid");
userParam.setOpenid(openid);
}
userParam.setPhone(phone);
user = addUser(userParam);
user.setRecommend(1);
} else {
// 存在则检查绑定上级
// 先查询管理员用户
user = userService.getAdminByPhone(userParam);
// 如果不是管理员,再查询普通用户
if (user == null) {
user = userService.getByPhone(phone, getTenantId());
}
}
// 如果用户存在,直接登录
if (user != null) {
System.out.println("用户已存在,直接登录: " + user.getPhone());
// 检查绑定上级关系
if (userParam.getSceneType() != null && userParam.getSceneType().equals("save_referee") && userParam.getRefereeId() != null && userParam.getRefereeId() != 0) {
UserReferee check = userRefereeService.check(user.getUserId(), userParam.getRefereeId());
if (check == null) {
@@ -150,15 +182,53 @@ public class WxLoginController extends BaseController {
userRefereeService.save(userReferee);
}
}
// 签发token
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_LOGIN, null, user.getTenantId(), request);
return success("登录成功", new LoginResult(access_token, user));
}
// 用户不存在,注册新用户
System.out.println("用户不存在,注册新用户: " + phone);
try {
if ((userParam.getOpenid() == null || userParam.getOpenid().isEmpty()) && userParam.getAuthCode() != null) {
UserParam userParam2 = new UserParam();
userParam2.setCode(userParam.getAuthCode());
JSONObject result = getOpenIdByCode(userParam2);
System.out.println("userInfo res:" + result);
String openid = result.getString("openid");
userParam.setOpenid(openid);
}
userParam.setPhone(phone);
user = addUser(userParam);
user.setRecommend(1);
// 签发token
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REGISTER, null, user.getTenantId(), request);
// 附加体育中心项目用户信息
// user.setBookingUser();
return success("注册并登录成功", new LoginResult(access_token, user));
} catch (BusinessException e) {
// 如果注册时提示手机号已存在,说明存在并发情况,重新查询用户并登录
if (e.getMessage().contains("手机号已存在")) {
System.out.println("注册时发现手机号已存在,重新查询用户进行登录");
user = userService.getByPhone(phone, getTenantId());
if (user != null) {
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_LOGIN, null, user.getTenantId(), request);
return success("登录成功", new LoginResult(access_token, user));
}
}
throw e;
}
}
@ApiOperation("微信授权手机号码并更新")
@Transactional(rollbackFor = {Exception.class})
@@ -372,14 +442,20 @@ public class WxLoginController extends BaseController {
String value = redisTemplate.opsForValue().get(key);
if (value != null) {
try {
// 解析access_token
// 尝试解析为JSON格式
JSONObject response = JSON.parseObject(value);
String accessToken = response.getString("access_token");
if (StrUtil.isNotBlank(accessToken)) {
System.out.println("从缓存获取access_token: " + accessToken);
System.out.println("从缓存获取access_token(JSON格式): " + accessToken);
return accessToken;
}
} catch (Exception e) {
// 如果JSON解析失败可能是旧的字符串格式直接使用
if (StrUtil.isNotBlank(value) && !value.startsWith("{")) {
System.out.println("从缓存获取access_token(字符串格式): " + value);
System.out.println("检测到旧格式的access_token将在下次更新时统一为JSON格式");
return value;
}
System.err.println("解析缓存的access_token失败: " + e.getMessage());
// 缓存数据异常,删除缓存,重新获取
redisTemplate.delete(key);
@@ -437,9 +513,16 @@ public class WxLoginController extends BaseController {
String accessToken = response.getString("access_token");
if (StrUtil.isNotBlank(accessToken)) {
// 构造标准的JSON格式存储对象
JSONObject tokenData = new JSONObject();
tokenData.put("access_token", accessToken);
tokenData.put("expires_in", response.get("expires_in"));
// 存入缓存设置过期时间为7000秒约2小时微信access_token有效期为2小时
redisTemplate.opsForValue().set(key, cleanResult, 7000L, TimeUnit.SECONDS);
// 统一使用JSON格式存储确保格式一致性
redisTemplate.opsForValue().set(key, tokenData.toJSONString(), 7000L, TimeUnit.SECONDS);
System.out.println("获取新的access_token成功: " + accessToken);
System.out.println("已统一存储为JSON格式: " + tokenData.toJSONString());
return accessToken;
} else {
System.err.println("响应中没有access_token字段: " + cleanResult);