fix: 微信登录,接口修改。

This commit is contained in:
tianyongbao
2026-01-18 20:23:15 +08:00
parent 32844af3dd
commit a2e6579a3a
4 changed files with 178 additions and 29 deletions

View File

@@ -40,6 +40,7 @@ import com.intc.web.service.SysLoginService;
import com.intc.web.service.SysRegisterService;
import com.intc.weixin.domain.bo.ReqWxLogin;
import com.intc.weixin.service.WxLoginService;
import com.intc.weixin.config.WxMaProperties;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -83,6 +84,9 @@ public class AuthController {
@Autowired(required = false)
private WxLoginService wxLoginService;
@Autowired(required = false)
private WxMaProperties wxMaProperties;
/**
* 登录方法
@@ -250,14 +254,27 @@ public class AuthController {
/**
* 微信小程序登录
*
* @param request 微信登录请求
* @param body 微信登录请求JSON字符串
* @return 结果
*/
@ApiEncrypt
@PostMapping("/wechat_login")
public R<AquUser> wechatLogin(@Validated @RequestBody ReqWxLogin request) {
public R<LoginVo> wechatLogin(@RequestBody String body) {
try {
log.info("收到微信登录请求: clientId={}, tenantId={}", request.getClientId(), request.getTenantId());
ReqWxLogin request = JsonUtils.parseObject(body, ReqWxLogin.class);
ValidatorUtils.validate(request);
// 如果未传递 clientId使用默认配置的 clientId
if (StringUtils.isBlank(request.getClientId()) && wxMaProperties != null) {
request.setClientId(wxMaProperties.getDefaultClientId());
// 更新 body 中的 clientId
body = JsonUtils.toJsonString(request);
}
String clientId = request.getClientId();
String grantType = "wechat"; // 微信登录的授权类型
log.info("收到微信登录请求: clientId={}, tenantId={}", clientId, request.getTenantId());
// 1. 检查服务是否可用
if (wxLoginService == null) {
@@ -266,43 +283,33 @@ public class AuthController {
}
// 2. 校验客户端
SysClientVo client = clientService.queryByClientId(request.getClientId());
SysClientVo client = clientService.queryByClientId(clientId);
if (ObjectUtil.isNull(client)) {
log.error("客户端不存在: clientId={}", request.getClientId());
log.error("客户端不存在: clientId={}", clientId);
return R.fail(MessageUtils.message("auth.grant.type.error"));
}
// 校验 client 内是否包含 grantType
if (!StringUtils.contains(client.getGrantType(), grantType)) {
log.error("客户端不支持该授权类型: clientId={}, grantType={}", clientId, grantType);
return R.fail(MessageUtils.message("auth.grant.type.error"));
}
if (!SystemConstants.NORMAL.equals(client.getStatus())) {
log.error("客户端已被禁用: clientId={}, status={}", request.getClientId(), client.getStatus());
log.error("客户端已被禁用: clientId={}, status={}", clientId, client.getStatus());
return R.fail(MessageUtils.message("auth.grant.type.blocked"));
}
// 3. 校验租户
if (StringUtils.isNotBlank(request.getTenantId())) {
try {
loginService.checkTenant(request.getTenantId());
} catch (Exception e) {
log.error("租户校验失败: tenantId={}", request.getTenantId(), e);
return R.fail("租户校验失败: " + e.getMessage());
}
loginService.checkTenant(request.getTenantId());
}
// 4. 执行微信登录
AquUser aquUser = wxLoginService.loginByWeChat(
request.getCode(),
request.getJsCode(),
request.getTenantId()
);
// 4. 使用标准的 IAuthStrategy 登录方法
LoginVo loginVo = IAuthStrategy.login(body, client, grantType);
log.info("微信登录成功: userId={}, accessToken={}",
loginVo.getUserId(), loginVo.getAccessToken() != null ? "***" : "null");
if (aquUser == null) {
log.error("微信登录失败,未返回用户信息");
return R.fail("登录失败,请重试");
}
// 5. 返回用户信息
log.info("微信登录成功: userId={}, mobilePhone={}",
aquUser.getId(), aquUser.getMobilePhone());
return R.ok(aquUser);
return R.ok(loginVo);
} catch (ServiceException e) {
log.error("微信登录业务异常: {}", e.getMessage(), e);

View File

@@ -0,0 +1,136 @@
package com.intc.web.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.intc.common.core.constant.SystemConstants;
import com.intc.common.core.domain.model.LoginUser;
import com.intc.common.core.exception.ServiceException;
import com.intc.common.core.exception.user.UserException;
import com.intc.common.core.utils.StringUtils;
import com.intc.common.core.utils.ValidatorUtils;
import com.intc.common.json.utils.JsonUtils;
import com.intc.common.satoken.utils.LoginHelper;
import com.intc.common.tenant.helper.TenantHelper;
import com.intc.fishery.domain.AquUser;
import com.intc.system.domain.SysUser;
import com.intc.system.domain.vo.SysClientVo;
import com.intc.system.domain.vo.SysUserVo;
import com.intc.system.mapper.SysUserMapper;
import com.intc.web.domain.vo.LoginVo;
import com.intc.web.service.IAuthStrategy;
import com.intc.web.service.SysLoginService;
import com.intc.weixin.domain.bo.ReqWxLogin;
import com.intc.weixin.service.WxLoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 微信小程序认证策略
*
* @author intc
*/
@Slf4j
@Service("wechat" + IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class WechatAuthStrategy implements IAuthStrategy {
private final WxLoginService wxLoginService;
private final SysLoginService loginService;
private final SysUserMapper userMapper;
@Override
public LoginVo login(String body, SysClientVo client) {
ReqWxLogin loginBody = JsonUtils.parseObject(body, ReqWxLogin.class);
ValidatorUtils.validate(loginBody);
String tenantId = loginBody.getTenantId();
String code = loginBody.getCode();
String jsCode = loginBody.getJsCode();
// 在租户上下文中执行登录
AquUser[] aquUserHolder = new AquUser[1]; // 用于保存 AquUser
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
// 1. 调用微信登录服务获取或创建渔业用户用于获取手机号和openId
AquUser aquUser = wxLoginService.loginByWeChat(code, jsCode, tenantId);
if (aquUser == null) {
log.error("微信登录失败,未返回用户信息");
throw new ServiceException("登录失败,请重试");
}
aquUserHolder[0] = aquUser; // 保存以便后续使用
log.info("获取微信用户信息成功: aquUserId={}, mobilePhone={}",
aquUser.getId(), aquUser.getMobilePhone());
// 2. 根据手机号查询系统用户
String mobilePhone = aquUser.getMobilePhone();
if (StringUtils.isBlank(mobilePhone)) {
log.error("微信用户手机号为空: aquUserId={}", aquUser.getId());
throw new ServiceException("获取手机号失败,请重新授权");
}
SysUserVo sysUser = loadUserByPhone(mobilePhone);
log.info("找到对应的系统用户: sysUserId={}, userName={}",
sysUser.getUserId(), sysUser.getUserName());
// 3. 使用系统用户构建 LoginUser包含完整的权限信息
return loginService.buildLoginUser(sysUser);
});
// 3. 设置客户端信息
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
// 4. 配置登录参数
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
// 5. 执行登录,生成 token
LoginHelper.login(loginUser, model);
// 6. 构建返回对象
LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue());
loginVo.setExpireIn(StpUtil.getTokenTimeout());
loginVo.setClientId(client.getClientId());
loginVo.setOpenid(aquUserHolder[0].getWxOpenId()); // 从 AquUser 中获取 openId
loginVo.setUserId(loginUser.getUserId());
loginVo.setUserName(loginUser.getUsername());
loginVo.setNickName(loginUser.getNickname());
return loginVo;
}
/**
* 根据手机号加载系统用户
*
* @param phone 手机号
* @return 系统用户信息
*/
private SysUserVo loadUserByPhone(String phone) {
SysUserVo user = userMapper.selectVoOne(
new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getPhonenumber, phone)
);
if (ObjectUtil.isNull(user)) {
log.error("系统中不存在该手机号的用户: phone={}", phone);
throw new UserException("user.not.exists", phone);
}
if (SystemConstants.DISABLE.equals(user.getStatus())) {
log.error("用户已被停用: phone={}, userId={}", phone, user.getUserId());
throw new UserException("user.blocked", phone);
}
return user;
}
}

View File

@@ -39,4 +39,9 @@ public class WxMaProperties {
*/
private String msgDataFormat;
/**
* 默认客户端ID小程序登录使用
*/
private String defaultClientId = "miniapp-client";
}

View File

@@ -1,5 +1,6 @@
package com.intc.weixin.domain.bo;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@@ -27,12 +28,12 @@ public class ReqWxLogin implements Serializable {
* 登录时获取的jsCode用于获取openId
*/
@NotBlank(message = "jsCode不能为空")
@JsonProperty("js_code")
private String jsCode;
/**
* 客户端ID
*/
@NotBlank(message = "客户端ID不能为空")
private String clientId;
/**