Merge remote-tracking branch 'origin/s209' into s209

This commit is contained in:
2025-09-08 08:01:50 +08:00
2 changed files with 315 additions and 4 deletions

View File

@@ -77,6 +77,13 @@ public class WxLoginController extends BaseController {
return success("操作成功", getAccessToken());
}
@ApiOperation("获取微信AccessToken支持指定租户ID")
@Transactional(rollbackFor = {Exception.class})
@PostMapping("/getAccessToken/{tenantId}")
public ApiResult<String> getMpAccessToken(@PathVariable("tenantId") Integer tenantId) {
return success("操作成功", getAccessToken(tenantId));
}
@ApiOperation("清理并统一AccessToken存储格式")
@PostMapping("/cleanAccessTokenFormat")
public ApiResult<String> cleanAccessTokenFormat() {
@@ -262,6 +269,152 @@ public class WxLoginController extends BaseController {
}
}
@ApiOperation("微信授权手机号码并登录支持指定租户ID")
@Transactional(rollbackFor = {Exception.class})
@PostMapping("/loginByMpWxPhone/{tenantId}")
public ApiResult<LoginResult> loginByMpWxPhoneWithTenant(@RequestBody UserParam userParam, HttpServletRequest request, @PathVariable("tenantId") Integer tenantId) {
System.out.println("接收到的参数: code=" + userParam.getCode() + ", authCode=" + userParam.getAuthCode() + ", openid=" + userParam.getOpenid() + ", tenantId=" + tenantId);
// 获取手机号码使用指定的tenantId
String phone = getPhoneByCode(userParam, tenantId);
if (phone == null) {
String key = ACCESS_TOKEN_KEY.concat(":").concat(tenantId.toString());
redisTemplate.delete(key);
throw new BusinessException("授权失败,请重试");
}
User user = null;
// 超级管理员验证
if (userParam.getIsSuperAdmin() != null) {
final LoginParam loginParam = new LoginParam();
loginParam.setIsAdmin(true);
loginParam.setPhone(phone);
final List<User> adminsByPhone = userService.getAdminsByPhone(loginParam);
if (!CollectionUtils.isEmpty(adminsByPhone)) {
user = adminsByPhone.get(0);
}
} else {
// 先查询管理员用户
user = userService.getAdminByPhone(userParam);
// 如果不是管理员再查询普通用户使用指定的tenantId
if (user == null) {
user = userService.getByPhone(phone, tenantId);
}
}
// 如果用户存在,直接登录
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) {
UserReferee userReferee = new UserReferee();
userReferee.setDealerId(userParam.getRefereeId());
userReferee.setUserId(user.getUserId());
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 {
// 确保获取openid - 优先使用已有的openid否则通过code获取
if (StrUtil.isBlank(userParam.getOpenid())) {
String codeToUse = null;
// 优先使用authCode如果没有则使用code
if (StrUtil.isNotBlank(userParam.getAuthCode())) {
codeToUse = userParam.getAuthCode();
} else if (StrUtil.isNotBlank(userParam.getCode())) {
codeToUse = userParam.getCode();
}
if (StrUtil.isNotBlank(codeToUse)) {
try {
System.out.println("尝试使用code获取openid: " + codeToUse);
UserParam userParam2 = new UserParam();
userParam2.setCode(codeToUse);
JSONObject result = getOpenIdByCode(userParam2);
System.out.println("获取openid结果: " + result);
if (result != null) {
// 检查微信接口是否返回错误
Object errcode = result.get("errcode");
if (errcode != null && !errcode.equals(0)) {
String errmsg = result.getString("errmsg");
System.err.println("微信获取openid失败: errcode=" + errcode + ", errmsg=" + errmsg);
// 如果是code无效错误提示前端重新获取
if (errcode.equals(40029)) {
System.err.println("授权码已过期或无效建议前端重新调用wx.login()获取新的code");
}
} else {
// 成功获取openid
String openid = result.getString("openid");
String unionid = result.getString("unionid");
if (StrUtil.isNotBlank(openid)) {
userParam.setOpenid(openid);
System.out.println("成功获取openid: " + openid);
}
if (StrUtil.isNotBlank(unionid)) {
userParam.setUnionid(unionid);
System.out.println("成功获取unionid: " + unionid);
}
}
}
} catch (Exception e) {
System.err.println("获取openid异常但继续注册流程: " + e.getMessage());
e.printStackTrace();
// 不抛出异常允许没有openid的情况下继续注册
}
} else {
System.out.println("警告没有提供code或authCode无法获取openid将创建没有openid的用户");
}
} else {
System.out.println("使用已有的openid: " + userParam.getOpenid());
}
userParam.setPhone(phone);
// 设置租户ID
userParam.setTenantId(tenantId);
user = addUserWithTenant(userParam, tenantId);
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);
return success("注册并登录成功", new LoginResult(access_token, user));
} catch (BusinessException e) {
// 如果注册时提示手机号已存在,说明存在并发情况,重新查询用户并登录
if (e.getMessage().contains("手机号已存在")) {
System.out.println("注册时发现手机号已存在,重新查询用户进行登录");
user = userService.getByPhone(phone, tenantId);
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})
@PostMapping("/updatePhoneByMpWx")
@@ -282,6 +435,13 @@ public class WxLoginController extends BaseController {
* 新用户注册
*/
private User addUser(UserParam userParam) {
return addUserWithTenant(userParam, getTenantId());
}
/**
* 新用户注册支持指定租户ID
*/
private User addUserWithTenant(UserParam userParam, Integer tenantId) {
User addUser = new User();
// 注册用户
addUser.setStatus(0);
@@ -302,7 +462,7 @@ public class WxLoginController extends BaseController {
addUser.setUnionid(userParam.getUnionid());
}
addUser.setPassword(userService.encodePassword(CommonUtil.randomUUID16()));
addUser.setTenantId(getTenantId());
addUser.setTenantId(tenantId != null ? tenantId : getTenantId());
addUser.setRecommend(1);
Role role = roleService.getOne(new QueryWrapper<Role>().eq("role_code", "user"), false);
addUser.setRoleId(role.getRoleId());
@@ -364,6 +524,19 @@ public class WxLoginController extends BaseController {
* @param userParam 需要传微信凭证code或encryptedData等参数
*/
private String getPhoneByCode(UserParam userParam) {
return getPhoneByCode(userParam, null);
}
/**
* 获取微信手机号码支持指定租户ID
* 支持两种方式:
* 1. 新版API方式使用code直接获取手机号
* 2. 旧版解密方式使用encryptedData、iv、sessionKey解密获取手机号
*
* @param userParam 需要传微信凭证code或encryptedData等参数
* @param tenantId 租户ID为null时使用当前租户ID
*/
private String getPhoneByCode(UserParam userParam, Integer tenantId) {
// 方式1如果有encryptedData使用解密方式获取手机号
if (StrUtil.isNotBlank(userParam.getEncryptedData()) &&
StrUtil.isNotBlank(userParam.getIv()) &&
@@ -383,7 +556,7 @@ public class WxLoginController extends BaseController {
// 方式2使用新版API方式获取手机号
if (StrUtil.isNotBlank(userParam.getCode())) {
try {
String apiUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken();
String apiUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken(tenantId);
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("code", userParam.getCode());
// 执行post请求
@@ -464,7 +637,22 @@ public class WxLoginController extends BaseController {
* <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html">...</a>
*/
private String getAccessToken() {
String key = ACCESS_TOKEN_KEY.concat(":").concat(getTenantId().toString());
return getAccessToken(getTenantId());
}
/**
* 获取接口调用凭据AccessToken支持指定租户ID
* <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html">...</a>
*
* @param tenantId 租户ID
* @return access_token
*/
private String getAccessToken(Integer tenantId) {
if (tenantId == null) {
tenantId = getTenantId();
}
String key = ACCESS_TOKEN_KEY.concat(":").concat(tenantId.toString());
// 获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKey("mp-weixin");
if (setting == null) {
@@ -672,7 +860,11 @@ public class WxLoginController extends BaseController {
@ApiOperation("获取微信小程序码-订单核销码-数量极多的业务场景")
@GetMapping("/getOrderQRCodeUnlimited/{orderNo}")
public ApiResult<?> getOrderQRCodeUnlimited(@PathVariable("orderNo") String orderNo) {
String apiUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken();
final User loginUser = getLoginUser();
if(loginUser == null){
return fail("请先登录");
}
String apiUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken(loginUser.getTenantId());
final HashMap<String, Object> map = new HashMap<>();
map.put("scene", "orderNo=".concat(orderNo));
map.put("page", "package/admin/order-scan");