|
|
@@ -3,8 +3,17 @@ package com.ruoyi.user.service.impl;
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.date.DateTime;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alipay.api.AlipayApiException;
|
|
|
+import com.alipay.api.AlipayClient;
|
|
|
+import com.alipay.api.DefaultAlipayClient;
|
|
|
+import com.alipay.api.request.AlipaySystemOauthTokenRequest;
|
|
|
+import com.alipay.api.request.AlipayUserInfoShareRequest;
|
|
|
+import com.alipay.api.response.AlipaySystemOauthTokenResponse;
|
|
|
+import com.alipay.api.response.AlipayUserInfoShareResponse;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
@@ -13,14 +22,21 @@ import com.ruoyi.common.core.domain.PageQuery;
|
|
|
import com.ruoyi.common.core.page.TableDataInfo;
|
|
|
import com.ruoyi.common.enums.ExceptionEnum;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
+import com.ruoyi.common.properties.AlipayProperties;
|
|
|
+import com.ruoyi.common.properties.WeChatProperties;
|
|
|
+import com.ruoyi.common.utils.IOSToeknUtils;
|
|
|
import com.ruoyi.common.utils.ShareCodeUtils;
|
|
|
+import com.ruoyi.common.utils.SmsSend;
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
+import com.ruoyi.common.utils.rest.RestUtil;
|
|
|
import com.ruoyi.user.domain.User;
|
|
|
import com.ruoyi.user.domain.UserThirdIdentity;
|
|
|
-import com.ruoyi.user.domain.bo.PersonalDataBo;
|
|
|
-import com.ruoyi.user.domain.bo.UserBo;
|
|
|
+import com.ruoyi.user.domain.bo.*;
|
|
|
+import com.ruoyi.user.domain.vo.UserBindingVo;
|
|
|
+import com.ruoyi.user.domain.vo.UserLoginVo;
|
|
|
import com.ruoyi.user.domain.vo.UserStatisticsVo;
|
|
|
import com.ruoyi.user.domain.vo.UserVo;
|
|
|
+import com.ruoyi.user.enums.UserThirdType;
|
|
|
import com.ruoyi.user.exception.UserExceptionEnum;
|
|
|
import com.ruoyi.user.mapper.UserMapper;
|
|
|
import com.ruoyi.user.mapper.UserThirdIdentityMapper;
|
|
|
@@ -50,9 +66,13 @@ public class UserServiceImpl implements IUserService {
|
|
|
|
|
|
private final UserThirdIdentityMapper userThirdIdentityMapper;
|
|
|
|
|
|
+ private final SmsSend smsSend;
|
|
|
|
|
|
+ private final RestUtil restUtil;
|
|
|
|
|
|
+ private final WeChatProperties wxPayConfig;
|
|
|
|
|
|
+ private final AlipayProperties aliPayConfig;
|
|
|
|
|
|
/**
|
|
|
* 查询小程序用户管理
|
|
|
@@ -224,15 +244,17 @@ public class UserServiceImpl implements IUserService {
|
|
|
if (ObjectUtil.isNotNull(userThirdIdentity)) {
|
|
|
return this.getById(userThirdIdentity.getUserId(), true);
|
|
|
}
|
|
|
+ return registerOrLogin(wxUserDto, UserThirdType.WX_MINI_PROGRAM.getCode(), openId);
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
+ private User registerOrLogin(WxUserDto wxUserDto, Integer thirdType, String identityCode) {
|
|
|
User user = this.loadByMobile(wxUserDto.getMobile(), false);
|
|
|
- if(ObjectUtil.isNotNull(user))
|
|
|
- {
|
|
|
- return user;
|
|
|
+ if (ObjectUtil.isNotNull(user)) {
|
|
|
+ user.setLastLoginTime(new Date());
|
|
|
+ this.baseMapper.updateById(user);
|
|
|
+ return user;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+ wxUserDto.setIsReg(true);
|
|
|
//创建用户
|
|
|
user = new User();
|
|
|
user.setNickname(wxUserDto.getNickname());
|
|
|
@@ -249,12 +271,13 @@ public class UserServiceImpl implements IUserService {
|
|
|
insertByBo(BeanUtil.toBean(user, UserBo.class));
|
|
|
|
|
|
//保存第三方关系
|
|
|
- userThirdIdentity = new UserThirdIdentity();
|
|
|
- userThirdIdentity.setUserId(user.getId());
|
|
|
- userThirdIdentity.setThirdType(0);
|
|
|
- userThirdIdentity.setIdentityCode(openId);
|
|
|
- userThirdIdentityMapper.insert(userThirdIdentity);
|
|
|
-
|
|
|
+ if (ObjectUtil.isNotNull(thirdType)) {
|
|
|
+ UserThirdIdentity userThirdIdentity = new UserThirdIdentity();
|
|
|
+ userThirdIdentity.setUserId(user.getId());
|
|
|
+ userThirdIdentity.setThirdType(thirdType);
|
|
|
+ userThirdIdentity.setIdentityCode(identityCode);
|
|
|
+ userThirdIdentityMapper.insert(userThirdIdentity);
|
|
|
+ }
|
|
|
return user;
|
|
|
}
|
|
|
|
|
|
@@ -343,12 +366,7 @@ public class UserServiceImpl implements IUserService {
|
|
|
@Override
|
|
|
public User loginAuthorization(String openId) {
|
|
|
//查询此openid是否绑定过用户
|
|
|
- UserThirdIdentity userThirdIdentity = userThirdIdentityMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<UserThirdIdentity>()
|
|
|
- .eq(UserThirdIdentity::getThirdType, 0)
|
|
|
- .eq(UserThirdIdentity::getIdentityCode, openId)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
+ UserThirdIdentity userThirdIdentity = getUserThirdIdentity(UserThirdType.WX_MINI_PROGRAM.getCode(), openId, null);
|
|
|
if (ObjectUtil.isNull(userThirdIdentity)) {
|
|
|
throw new ServiceException(UserExceptionEnum.USER_THIRD_ID_NOT_EXISTS);
|
|
|
}
|
|
|
@@ -359,6 +377,16 @@ public class UserServiceImpl implements IUserService {
|
|
|
return user;
|
|
|
}
|
|
|
|
|
|
+ private UserThirdIdentity getUserThirdIdentity(Integer thirdType, String identityCode, Long userId) {
|
|
|
+ return userThirdIdentityMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<UserThirdIdentity>()
|
|
|
+ .eq(UserThirdIdentity::getThirdType, thirdType)
|
|
|
+ .eq(ObjectUtil.isNotNull(userId), UserThirdIdentity::getUserId, userId)
|
|
|
+ .eq(StringUtils.isNotEmpty(identityCode), UserThirdIdentity::getIdentityCode, identityCode)
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void personalDataUpdate(PersonalDataBo bo, Long userId) {
|
|
|
User user = this.getById(userId, true);
|
|
|
@@ -403,6 +431,193 @@ public class UserServiceImpl implements IUserService {
|
|
|
return dataList;
|
|
|
}
|
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public UserLoginVo loginByCaptcha(UserLoginBo bo) {
|
|
|
+ //验证码验证
|
|
|
+ smsSend.check(bo.getMobile(), bo.getCaptcha());
|
|
|
+ //登录或注册
|
|
|
+ WxUserDto wxUserDto = new WxUserDto();
|
|
|
+ wxUserDto.setMobile(bo.getMobile());
|
|
|
+ User user = registerOrLogin(wxUserDto, null, null);
|
|
|
+
|
|
|
+ UserLoginVo userLoginVo = new UserLoginVo();
|
|
|
+ userLoginVo.setUser(user);
|
|
|
+ userLoginVo.setIsReg(wxUserDto.getIsReg());
|
|
|
+ return userLoginVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public UserLoginVo loginByThird(ThirdLoginBo bo) {
|
|
|
+ //根据code获取唯一标识
|
|
|
+ String identityCode = loadIdentityCodeByCode(bo.getThirdType(), bo.getCode());
|
|
|
+ //查询用户身份
|
|
|
+ UserThirdIdentity userThirdIdentity = getUserThirdIdentity(bo.getThirdType().getCode(), identityCode, null);
|
|
|
+ UserLoginVo userLoginVo = new UserLoginVo();
|
|
|
+ if (ObjectUtil.isNull(userThirdIdentity)) {
|
|
|
+ //用户身份不存在,请先注册
|
|
|
+ userLoginVo.setIsReg(false);
|
|
|
+ userLoginVo.setIdentityCode(identityCode);
|
|
|
+ return userLoginVo;
|
|
|
+ }
|
|
|
+ //查询用户
|
|
|
+ User user = loadByIdForLock(userThirdIdentity.getUserId(), false);
|
|
|
+ if (ObjectUtil.isNull(user)) {
|
|
|
+ //如果用户不存在,则清理数据,重新注册
|
|
|
+ userThirdIdentityMapper.delete(new LambdaQueryWrapper<UserThirdIdentity>().eq(UserThirdIdentity::getUserId, userThirdIdentity.getUserId())
|
|
|
+ .eq(UserThirdIdentity::getThirdType, userThirdIdentity.getThirdType()));
|
|
|
+ userLoginVo.setIsReg(false);
|
|
|
+ userLoginVo.setIdentityCode(identityCode);
|
|
|
+ return userLoginVo;
|
|
|
+ }
|
|
|
+ user.setLastLoginTime(new Date());
|
|
|
+ this.baseMapper.updateById(user);
|
|
|
+ userLoginVo.setUser(user);
|
|
|
+ return userLoginVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public UserLoginVo registerByThird(ThirdRegisterBo bo) {
|
|
|
+ smsSend.check(bo.getMobile(), bo.getCaptcha());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public UserLoginVo loginByMobile(UserLoginBo bo) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public UserBindingVo thirdBindingInfo(Long userId) {
|
|
|
+ User user = loadByIdForLock(userId, true);
|
|
|
+ UserBindingVo vo = new UserBindingVo();
|
|
|
+ vo.setMobile(user.getMobile());
|
|
|
+ //是否绑定微信
|
|
|
+ if (ObjectUtil.isNotNull(getUserThirdIdentity(UserThirdType.WX_MINI_PROGRAM.getCode(), null, userId))) {
|
|
|
+ vo.setBindingWechat(true);
|
|
|
+ }
|
|
|
+ //是否绑定支付宝
|
|
|
+ if (ObjectUtil.isNotNull(getUserThirdIdentity(UserThirdType.ALI_MINI_PROGRAM.getCode(), null, userId))) {
|
|
|
+ vo.setBindingAlipay(true);
|
|
|
+ }
|
|
|
+ //是否绑定苹果
|
|
|
+ if (ObjectUtil.isNotNull(getUserThirdIdentity(UserThirdType.APPLE.getCode(), null, userId))) {
|
|
|
+ vo.setBindingApple(true);
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String loadIdentityCodeByCode(UserThirdType thirdType, String code) {
|
|
|
+ switch (thirdType) {
|
|
|
+ case WX_MINI_PROGRAM:
|
|
|
+ return getWeChatIdByCode(code);
|
|
|
+ case ALI_MINI_PROGRAM:
|
|
|
+ return getAlipayIdByCode(code);
|
|
|
+ case APPLE:
|
|
|
+ return getAppleIdByCode(code);
|
|
|
+ default:
|
|
|
+ throw new ServiceException("第三方身份错误");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取微信OpenId
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String getWeChatIdByCode(String code) {
|
|
|
+ if (StringUtils.isBlank(code)) {
|
|
|
+ throw new ServiceException("请求参数code不能为空");
|
|
|
+ }
|
|
|
+ //微信开放平台
|
|
|
+ try {
|
|
|
+ String url = String.format(wxPayConfig.getAccessTokenUrl(), wxPayConfig.getAppId(), wxPayConfig.getAppSecret(), code);
|
|
|
+
|
|
|
+ Map result = restUtil.getForEntity(url, Map.class, null);
|
|
|
+ Integer errcode = MapUtil.getInt(result, "errcode");
|
|
|
+ if (ObjectUtil.isNotNull(errcode) && errcode == 40029) {
|
|
|
+ throw new ServiceException("请求参数code错误");
|
|
|
+ }
|
|
|
+ String openid = MapUtil.getStr(result, "openid").replaceAll("\"", "");
|
|
|
+ if (StringUtils.isBlank(openid)) {
|
|
|
+ throw new ServiceException("获取微信唯一标识异常");
|
|
|
+ }
|
|
|
+ return openid;
|
|
|
+ } catch (Exception ex) {
|
|
|
+ throw new ServiceException("获取微信唯一标识异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取支付宝ID
|
|
|
+ *
|
|
|
+ * @param code
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String getAlipayIdByCode(String code) {
|
|
|
+ //使用支付宝小程序的固定方法获取auth_code
|
|
|
+ if (StringUtils.isBlank(code)) {
|
|
|
+ throw new ServiceException("请求参数code不能为空");
|
|
|
+ } else {
|
|
|
+ AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getServerUrl(), // 支付宝网关(固定)
|
|
|
+ aliPayConfig.getAppId(), // APPID 即创建应用后生成
|
|
|
+ aliPayConfig.getAppPrivateKey(), // 开发者私钥,由开发者自己生成
|
|
|
+ aliPayConfig.getFormat(), // 参数返回格式,只支持json
|
|
|
+ aliPayConfig.getCharset(), // 编码集,支持GBK/UTF-8
|
|
|
+ aliPayConfig.getAlipayPublicKey(), // 支付宝公钥,由支付宝生成
|
|
|
+ aliPayConfig.getSignType()); // 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
|
|
|
+
|
|
|
+ //获取accessToken
|
|
|
+ AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
|
|
|
+ request.setCode(code);
|
|
|
+ request.setGrantType("authorization_code");
|
|
|
+ try {
|
|
|
+ AlipaySystemOauthTokenResponse responseToken = alipayClient.execute(request);
|
|
|
+ if (responseToken.isSuccess()) {
|
|
|
+ //获取用户信息
|
|
|
+ AlipayUserInfoShareRequest alipayUserInfoShareRequest = new AlipayUserInfoShareRequest();
|
|
|
+ AlipayUserInfoShareResponse response = alipayClient.execute(alipayUserInfoShareRequest, responseToken.getAccessToken());
|
|
|
+ if (response.isSuccess()) {
|
|
|
+ //新商户建议使用open_id替代该字段。对于新商户,user_id字段未来计划逐步回收,存量商户可继续使用。如使用open_id,请确认 应用-开发配置-openid配置管理 已启用。无该配置项
|
|
|
+ return response.getOpenId();
|
|
|
+ } else {
|
|
|
+ throw new ServiceException("获取用户信息调用失败");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ throw new ServiceException("获取accessToken调用失败");
|
|
|
+ }
|
|
|
+ } catch (AlipayApiException e) {
|
|
|
+ throw new ServiceException("获取支付宝唯一标识异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取苹果用户唯一标识
|
|
|
+ *
|
|
|
+ * @param identityToken
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String getAppleIdByCode(String identityToken) {
|
|
|
+ // 解码后的消息体
|
|
|
+ JSONObject playloadObj = IOSToeknUtils.parserIdentityToken(identityToken);
|
|
|
+ Boolean success;
|
|
|
+ try {
|
|
|
+ success = IOSToeknUtils.verifyExc(identityToken, playloadObj);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!success) {
|
|
|
+ // TODO 校验token失败具体操作
|
|
|
+ throw new ServiceException("苹果验证失败");
|
|
|
+ }
|
|
|
+ return playloadObj.getString("sub");
|
|
|
+ }
|
|
|
+
|
|
|
public static List<UserStatisticsVo> completionDate(String start, String end) {
|
|
|
//日期格式化
|
|
|
List<UserStatisticsVo> dateList = new ArrayList<>();
|