提交 2d13680f authored 作者: hzh's avatar hzh

Merge branch 'dev'

......@@ -21,11 +21,12 @@ public interface RemoteUserService {
* 通过用户名查询用户信息
*
* @param username 用户名
* @param phone 手机号
* @param tenantId 租户id
* @param userType 用户类型
* @return 结果
*/
LoginUser getUserInfo(String username, String tenantId, String userType) throws UserException;
LoginUser getUserInfo(String username, String phone, String tenantId, String userType) throws UserException;
/**
* 通过用户id查询用户信息
......@@ -61,7 +62,7 @@ public interface RemoteUserService {
* @param tenantId 租户id
* @return 结果
*/
XcxLoginUser getUserInfoByOpenid(String openid, String tenantId) throws UserException;
XcxLoginUser getUserInfoByOpenid(String openid, String phone, String tenantId) throws UserException;
/**
* 注册用户信息
......@@ -154,9 +155,10 @@ public interface RemoteUserService {
* 根据手机号查询租户id集合
*
* @param phone 手机号
* @param userType 手机号
* @return 租户id集合
*/
List<String> selectTenantIdsByPhone(String phone);
List<String> selectTenantIdsByPhone(String phone,String userType);
/**
* 注册用户到云上服务器
......
......@@ -22,6 +22,7 @@ import org.dromara.auth.service.SysLoginService;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.utils.*;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.json.utils.JsonUtils;
......@@ -213,7 +214,7 @@ public class TokenController {
//通过手机号过滤
if (StringUtils.isNotEmpty(phone)){
List<String> tenantIds = remoteUserService.selectTenantIdsByPhone(phone);
List<String> tenantIds = remoteUserService.selectTenantIdsByPhone(phone, UserType.SYS_USER.getUserType());
tenantList = StreamUtils.filter(tenantList, vo -> tenantIds.contains(vo.getTenantId()));
}
......
......@@ -19,10 +19,28 @@ public class XcxLoginBody extends LoginBody {
*/
private String appid;
/**
* 手机号
*/
private String phone;
/**
* 小程序code
*/
@NotBlank(message = "{xcx.code.not.blank}")
private String xcxCode;
/**
* 用户信息,base64编码
*/
private String encryptedData;
/**
* 加密算法的初始向量
*/
private String iv;
/**
* 用户登录凭证
*/
private String sessionKey;
}
......@@ -34,5 +34,9 @@ public class XcxPhoneLoginBody extends LoginBody {
*/
@NotBlank(message = "用户凭证不能为空")
private String sessionKey;
/**
* 手机号
*/
private String phone;
}
package org.dromara.auth.service.impl;
import cn.hutool.core.util.DesensitizedUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.auth.service.IAuthStrategy;
import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.mall.api.domain.member.RemoteMember;
import org.dromara.mall.api.domain.member.RemoteMemberSave;
......@@ -37,33 +39,28 @@ public abstract class AbstractMallStrategy implements IAuthStrategy {
@Nullable
Long getMemberId(LoginBody loginBody, XcxLoginUser loginUser) {
// 增加商城逻辑
Long thirdUserId = null;
if (StringUtils.equals(loginBody.getTenantId(), DEFAULT_TENANT_ID) && StringUtils.equals(loginUser.getUserType(), UserType.APP_USER.getUserType())) {
thirdUserId = loginUser.getUserId();
} else {
// 创建用户
RemoteUserBo remoteUserBo = new RemoteUserBo();
remoteUserBo.setTenantId(DEFAULT_TENANT_ID);
remoteUserBo.setUserName(StringUtils.isNotEmpty(loginUser.getPhone()) ? loginUser.getPhone() : loginUser.getUsername());
remoteUserBo.setNickName(remoteUserBo.getUserName());
remoteUserBo.setUserType(UserType.APP_USER.getUserType());
remoteUserBo.setPhonenumber(loginUser.getPhone());
Long thirdUserId;
String tenantId = DEFAULT_TENANT_ID;
String username = StringUtils.isNotEmpty(loginUser.getPhone()) ? loginUser.getPhone() : loginUser.getUsername();
String userType = UserType.APP_USER.getUserType();
String phone = loginUser.getPhone();
try {
thirdUserId = remoteUserService.getUserInfo(remoteUserBo.getUserName(), remoteUserBo.getTenantId(), remoteUserBo.getUserType()).getUserId();
thirdUserId = remoteUserService.getUserInfo(username, phone, tenantId, userType).getUserId();
} catch (Exception e) {
log.info("用户不存在:{},租户id:{},需要进行注册", remoteUserBo.getUserName(), remoteUserBo.getTenantId());
}
if (thirdUserId == null) {
// 创建用户
RemoteUserBo remoteUserBo = new RemoteUserBo();
remoteUserBo.setTenantId(tenantId);
remoteUserBo.setUserName(username);
remoteUserBo.setNickName(remoteUserBo.getUserName());
remoteUserBo.setUserType(userType);
remoteUserBo.setPhonenumber(phone);
try {
thirdUserId = remoteUserService.registerUserInfo(remoteUserBo);
} catch (Exception e) {
log.info("用户已存在:{},租户id:{}", remoteUserBo.getUserName(), remoteUserBo.getTenantId());
thirdUserId = remoteUserService.getUserInfo(remoteUserBo.getUserName(), remoteUserBo.getTenantId(), remoteUserBo.getUserType()).getUserId();
}
} catch (Exception ex) {
thirdUserId = remoteUserService.getUserInfo(username, phone, tenantId, userType).getUserId();
}
}
Long memberId = null;
......@@ -73,7 +70,7 @@ public abstract class AbstractMallStrategy implements IAuthStrategy {
rm = remoteMemberService.saveMember(
new RemoteMemberSave()
.setThirdUserId(thirdUserId)
.setPhonenumber(loginUser.getPhone())
.setPhonenumber(phone)
.setRegisterIp(getClientIP())
);
}
......@@ -82,4 +79,17 @@ public abstract class AbstractMallStrategy implements IAuthStrategy {
return memberId;
}
protected void validatePhone(String validatePhone, String loginPhone) {
if (StringUtils.isBlank(validatePhone)) {
return;
}
if (!StringUtils.equals(validatePhone, loginPhone)) {
throw new ServiceException(String.format("微信授权手机号%s与您输入的员工手机号%s不匹配,请核对后登录", desensitizedPhone(loginPhone), desensitizedPhone(validatePhone)));
}
}
private String desensitizedPhone(String phone) {
return DesensitizedUtil.mobilePhone(phone);
}
}
......@@ -68,7 +68,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
validateCaptcha(tenantId, username, code, uuid);
}
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
LoginUser user = remoteUserService.getUserInfo(username, tenantId, UserType.SYS_USER.getUserType());
LoginUser user = remoteUserService.getUserInfo(username, null, tenantId, UserType.SYS_USER.getUserType());
loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
return user;
});
......
......@@ -9,15 +9,18 @@ import org.dromara.auth.domain.vo.LoginVo;
import org.dromara.auth.form.XcxLoginBody;
import org.dromara.auth.service.IAuthStrategy;
import org.dromara.auth.service.SysLoginService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.weixin.dto.WxAuthPhoneParseReq;
import org.dromara.common.weixin.dto.WxAuthReq;
import org.dromara.common.weixin.dto.WxAuthResp;
import org.dromara.common.weixin.utils.WeixinUtils;
import org.dromara.server.api.RemoteServerService;
import org.dromara.server.api.domain.RemoteUser;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteWxUserBo;
import org.dromara.system.api.domain.vo.RemoteClientVo;
import org.dromara.system.api.model.XcxLoginUser;
import org.springframework.stereotype.Service;
......@@ -49,22 +52,42 @@ public class XcxAuthStrategy extends AbstractMallStrategy implements IAuthStrate
// xcxCode 为 小程序调用 wx.login 授权后获取
String xcxCode = loginBody.getXcxCode();
// 多个小程序识别使用
// String appid = loginBody.getAppid();
WxAuthResp auth = WeixinUtils.auth(new WxAuthReq()
.setCode(xcxCode)
.setAppid(client.getClientKey())
.setSecret(client.getClientSecret()));
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String openid = auth.getOpenId();
XcxLoginUser loginUser = remoteUserService.getUserInfoByOpenid(openid, loginBody.getTenantId());
String phone = null;
if (StringUtils.isNotBlank(loginBody.getEncryptedData())) {
phone = WeixinUtils.authParsePhone(new WxAuthPhoneParseReq()
.setEncryptedData(loginBody.getEncryptedData())
.setIv(loginBody.getIv())
.setSessionKey(auth.getSessionKey()));
remoteUserService.registerWxUserInfo(new RemoteWxUserBo()
.setTenantId(loginBody.getTenantId())
.setOpenId(openid)
.setPhonenumber(phone));
}
//校验手机号
validatePhone(loginBody.getPhone(), phone);
XcxLoginUser loginUser = remoteUserService.getUserInfoByOpenid(openid, phone, loginBody.getTenantId());
// 用户不存在 返回 openid
if (loginUser == null) {
if (phone == null) {
LoginVo loginVo = new LoginVo();
loginVo.setOpenid(openid);
loginVo.setScope(auth.getSessionKey());
return loginVo;
} else {
throw new RuntimeException("用户不存在");
}
}
loginUser.setClientKey(client.getClientKey());
......
......@@ -56,7 +56,11 @@ public class XcxPhoneAuthStrategy extends AbstractMallStrategy implements IAuthS
.setTenantId(loginBody.getTenantId())
.setOpenId(loginBody.getOpenId())
.setPhonenumber(phone));
XcxLoginUser loginUser = remoteUserService.getUserInfoByOpenid(loginBody.getOpenId(), loginBody.getTenantId());
//校验手机号
validatePhone(loginBody.getPhone(), phone);
XcxLoginUser loginUser = remoteUserService.getUserInfoByOpenid(loginBody.getOpenId(), phone, loginBody.getTenantId());
if (loginUser == null) {
throw new RuntimeException("用户不存在");
......
......@@ -78,7 +78,7 @@ public class ProductPropertyController {
public R<List<ProductPropertyRespVO>> getPropertySimpleList() {
List<ProductPropertyDO> list = productPropertyService.getPropertyList();
return R.ok(convertList(list, property -> new ProductPropertyRespVO() // 只返回 id、name 属性
.setId(property.getId()).setName(property.getName())));
.setId(property.getId()).setName(property.getName()).setType(property.getType())));
}
}
......@@ -17,6 +17,9 @@ public class ProductPropertyRespVO {
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String name;
@Schema(description = "类型", example = "文本")
private String type;
@Schema(description = "备注", example = "颜色")
private String remark;
......
......@@ -15,6 +15,9 @@ public class ProductPropertySaveReqVO {
@NotBlank(message = "名称不能为空")
private String name;
@Schema(description = "类型")
private String type;
@Schema(description = "备注", example = "颜色")
private String remark;
......
......@@ -67,6 +67,9 @@ public class ProductSkuSaveReqVO {
@Schema(description = "属性名字", example = "颜色")
private String propertyName;
@Schema(description = "属性类型", example = "文本")
private String propertyType;
@Schema(description = "属性值编号", example = "10")
private Long valueId;
......
package org.dromara.mall.domain.product;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import org.dromara.mall.enums.product.spu.ProductPropertyTypeEnum;
import java.io.Serial;
......@@ -29,6 +32,10 @@ public class ProductPropertyDO extends TenantEntity {
* SPU 单规格时,默认属性名字
*/
public static final String NAME_DEFAULT = "默认";
/**
* SPU 单规格时,默认属性类型
*/
public static final String TYPE_DEFAULT = ProductPropertyTypeEnum.TEXT.name();
/**
* 编号
......@@ -40,6 +47,10 @@ public class ProductPropertyDO extends TenantEntity {
* 名称
*/
private String name;
/**
* 类型
*/
private String type;
/**
* 备注
*/
......
package org.dromara.mall.domain.product;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
import java.util.List;
......@@ -108,11 +111,17 @@ public class ProductSkuDO extends TenantEntity {
/**
* 属性名字
* 冗余 {@link ProductPropertyDO#getName()}
*
* <p>
* 注意:每次属性名字发生变化时,需要更新该冗余
*/
private String propertyName;
/**
* 属性类型
* 冗余 {@link ProductPropertyDO#getType()}
*/
private String propertyType;
/**
* 属性值编号
* 关联 {@link ProductPropertyValueDO#getId()}
......
package org.dromara.mall.enums.product.spu;
import lombok.Getter;
/**
* @author wenhe
*/
@Getter
public enum ProductPropertyTypeEnum {
/**
* 文本
*/
TEXT,
/**
* 日期
*/
DATE;
}
......@@ -2,6 +2,7 @@ package org.dromara.mall.service.product.impl;
import cn.hutool.core.util.ObjUtil;
import jakarta.annotation.Resource;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mall.util.object.BeanUtils;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.mybatis.core.query.LambdaQueryWrapperX;
......@@ -56,6 +57,9 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
// 插入
ProductPropertyDO property = BeanUtils.toBean(createReqVO, ProductPropertyDO.class);
property.setDeptId(LoginHelper.getDeptId());
if (StringUtils.isEmpty(property.getType())) {
property.setType(ProductPropertyDO.TYPE_DEFAULT);
}
productPropertyMapper.insert(property);
// 返回
return property.getId();
......@@ -74,6 +78,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
// 更新
ProductPropertyDO updateObj = BeanUtils.toBean(updateReqVO, ProductPropertyDO.class);
updateObj.setType(null);
productPropertyMapper.updateById(updateObj);
// 更新 sku 相关属性
productSkuService.updateSkuProperty(updateObj.getId(), updateObj.getName());
......
......@@ -90,7 +90,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
ProductSkuSaveReqVO skuVO = skus.get(0);
List<ProductSkuSaveReqVO.Property> properties = new ArrayList<>();
ProductSkuSaveReqVO.Property property = new ProductSkuSaveReqVO.Property()
.setPropertyId(ProductPropertyDO.ID_DEFAULT).setPropertyName(ProductPropertyDO.NAME_DEFAULT)
.setPropertyId(ProductPropertyDO.ID_DEFAULT).setPropertyName(ProductPropertyDO.NAME_DEFAULT).setPropertyType(ProductPropertyDO.TYPE_DEFAULT)
.setValueId(ProductPropertyValueDO.ID_DEFAULT).setValueName(ProductPropertyValueDO.NAME_DEFAULT);
properties.add(property);
skuVO.setProperties(properties);
......
......@@ -66,14 +66,16 @@ public class RemoteUserServiceImpl implements RemoteUserService {
* 通过用户名查询用户信息
*
* @param username 用户名
* @param phone 手机号
* @param tenantId 租户id
* @return 结果
*/
@Override
public LoginUser getUserInfo(String username, String tenantId, String userType) throws UserException {
public LoginUser getUserInfo(String username, String phone, String tenantId, String userType) throws UserException {
return TenantHelper.dynamic(tenantId, () -> {
SysUserVo sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, username)
.eq(StringUtils.isNotBlank(phone), SysUser::getPhonenumber, phone)
.eq(StringUtils.isNotBlank(userType), SysUser::getUserType, userType)
);
if (ObjectUtil.isNull(sysUser)) {
......@@ -164,12 +166,17 @@ public class RemoteUserServiceImpl implements RemoteUserService {
* @return 结果
*/
@Override
public XcxLoginUser getUserInfoByOpenid(String openid, String tenantId) throws UserException {
WxUserVo wxUser = wxUserService.selectUserByOpenId(openid, tenantId);
public XcxLoginUser getUserInfoByOpenid(String openid, String phone, String tenantId) throws UserException {
List<WxUserVo> wxUserList = wxUserService.selectUserByOpenId(openid, phone, tenantId);
WxUserVo wxUser = CollectionUtils.isEmpty(wxUserList) ? null : wxUserList.get(0);
if (!ObjectUtil.isNotNull(wxUser)) {
return null;
}
if (StringUtils.isNotBlank(phone) && !StringUtils.equals(phone, wxUser.getPhonenumber())) {
throw new UserException("user.not.exists", phone);
}
//根据手机号查询用户信息
SysUserVo user = userService.selectUserByPhonenumber(wxUser.getPhonenumber(), wxUser.getTenantId());
if (!ObjectUtil.isNotNull(user)) {
......@@ -209,6 +216,7 @@ public class RemoteUserServiceImpl implements RemoteUserService {
}
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, sysUserBo.getUserName())
.eq(StringUtils.isNotBlank(sysUserBo.getPhonenumber()), SysUser::getPhonenumber, sysUserBo.getPhonenumber())
.eq(SysUser::getUserType, remoteUserBo.getUserType())
);
});
......@@ -223,8 +231,8 @@ public class RemoteUserServiceImpl implements RemoteUserService {
public Boolean registerWxUserInfo(RemoteWxUserBo remoteWxUserBo) {
WxUserBo user = BeanUtil.copyProperties(remoteWxUserBo, WxUserBo.class);
WxUserVo wx = wxUserService.selectUserByOpenId(remoteWxUserBo.getOpenId(), remoteWxUserBo.getTenantId());
if (ObjectUtil.isNotNull(wx)) {
List<WxUserVo> wxUserVoList = wxUserService.selectUserByOpenId(remoteWxUserBo.getOpenId(), remoteWxUserBo.getPhonenumber(), remoteWxUserBo.getTenantId());
if (CollectionUtils.isNotEmpty(wxUserVoList)) {
return true;
}
......@@ -381,10 +389,11 @@ public class RemoteUserServiceImpl implements RemoteUserService {
* 通过手机号查询租户id集合
*
* @param phone 手机号
* @param userType 手机号
* @return 租户id集合
*/
@Override
public List<String> selectTenantIdsByPhone(String phone) {
public List<String> selectTenantIdsByPhone(String phone, String userType) {
return userMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, phone))
.stream().map(SysUser::getTenantId).collect(Collectors.toList());
}
......
......@@ -3,6 +3,8 @@ package org.dromara.system.service;
import org.dromara.system.domain.bo.WxUserBo;
import org.dromara.system.domain.vo.WxUserVo;
import java.util.List;
/**
* 用户 业务层
*
......@@ -14,10 +16,11 @@ public interface IWxUserService {
* 通过openId查询用户
*
* @param openId openId
* @param phone phone
* @param tenantId 租户ID
* @return 用户对象信息
*/
WxUserVo selectUserByOpenId(String openId,String tenantId);
List<WxUserVo> selectUserByOpenId(String openId, String phone, String tenantId);
/**
* 注册用户
......
......@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.system.domain.WxUser;
import org.dromara.system.domain.bo.WxUserBo;
import org.dromara.system.domain.vo.WxUserVo;
......@@ -11,6 +12,8 @@ import org.dromara.system.mapper.WxUserMapper;
import org.dromara.system.service.IWxUserService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户 业务层处理
*
......@@ -32,8 +35,12 @@ public class WxUserServiceImpl implements IWxUserService {
* @return 用户对象信息
*/
@Override
public WxUserVo selectUserByOpenId(String openId, String tenantId) {
return baseMapper.selectVoOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenId, openId).eq(WxUser::getTenantId, tenantId));
public List<WxUserVo> selectUserByOpenId(String openId, String phone, String tenantId) {
return baseMapper.selectVoList(
new LambdaQueryWrapper<WxUser>()
.eq(WxUser::getOpenId, openId)
.eq(StringUtils.isNotBlank(phone), WxUser::getPhonenumber, phone)
.eq(WxUser::getTenantId, tenantId));
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论