|
|
@@ -6,11 +6,15 @@ import cn.hutool.core.date.DateTime;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.fs.app.annotation.Login;
|
|
|
import com.fs.app.param.*;
|
|
|
+import com.fs.app.utils.UniVerifyUtil;
|
|
|
import com.fs.app.utils.WxUtil;
|
|
|
import com.fs.common.VerifyCodeUtil;
|
|
|
+import com.fs.common.annotation.RateLimiter;
|
|
|
import com.fs.common.annotation.RepeatSubmit;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.common.enums.LimitType;
|
|
|
+import com.fs.common.exception.CustomException;
|
|
|
import com.fs.common.exception.ServiceException;
|
|
|
import com.fs.common.service.ISmsService;
|
|
|
import com.fs.common.utils.sign.Md5Utils;
|
|
|
@@ -71,6 +75,9 @@ public class AppLoginController extends AppBaseController{
|
|
|
@Autowired
|
|
|
private OpenIMService openIMService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private UniVerifyUtil uniVerifyUtil;
|
|
|
+
|
|
|
// @ApiOperation("注册app用户")
|
|
|
// @PostMapping("/register")
|
|
|
// @RepeatSubmit
|
|
|
@@ -127,6 +134,37 @@ public class AppLoginController extends AppBaseController{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @ApiOperation("UniApp一键登录(安全)")
|
|
|
+ @PostMapping("/loginByUniverify")
|
|
|
+ @Transactional
|
|
|
+ @RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
|
|
|
+ public R loginByUniverify(@RequestBody FsUserLoginParam param) {
|
|
|
+ if (StringUtils.isEmpty(param.getAccessToken()) || StringUtils.isEmpty(param.getOpenId())) {
|
|
|
+ return R.error("一键登录凭证不完整");
|
|
|
+ }
|
|
|
+// String tokenCacheKey = "univerify:used:" + param.getAccessToken();
|
|
|
+// if (redisCache.getCacheObject(tokenCacheKey) != null) {
|
|
|
+// return R.error("登录凭证已失效,请重新授权");
|
|
|
+// }
|
|
|
+ String phone;
|
|
|
+ try {
|
|
|
+ phone = uniVerifyUtil.getPhoneNumber(param.getAccessToken(), param.getOpenId());
|
|
|
+ } catch (CustomException e) {
|
|
|
+ return R.error(e.getMessage());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("UniVerify获取手机号失败: {}", e.getMessage());
|
|
|
+ return R.error("获取手机号失败,请重试");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(phone)) {
|
|
|
+ return R.error("获取手机号失败");
|
|
|
+ }
|
|
|
+// redisCache.setCacheObject(tokenCacheKey, "1", 1, TimeUnit.MINUTES);
|
|
|
+ param.setPhone(phone);
|
|
|
+ return handleSecurePhoneLogin(param);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
@PostMapping("/registerSendCode")
|
|
|
public R registerSendCode(@RequestBody Map<String, String> body){
|
|
|
String phone = body.get("phone");
|
|
|
@@ -458,6 +496,163 @@ public class AppLoginController extends AppBaseController{
|
|
|
return userService.updatePasswordByPhone(password,encryptPhone);
|
|
|
}
|
|
|
|
|
|
+ @ApiOperation("绑定手机号")
|
|
|
+ @PostMapping("/setIPhoneNumberOne")
|
|
|
+ public R setIPhoneNumberOne(@Validated @RequestBody FsUserEditPhoneParam param) {
|
|
|
+ if (StringUtils.isEmpty(param.getAccessToken()) || StringUtils.isEmpty(param.getOpenId())) {
|
|
|
+ return R.error("一键登录凭证不完整");
|
|
|
+ }
|
|
|
+ String phone;
|
|
|
+ try {
|
|
|
+ phone = uniVerifyUtil.getPhoneNumber(param.getAccessToken(), param.getOpenId());
|
|
|
+ } catch (CustomException e) {
|
|
|
+ return R.error(e.getMessage());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("UniVerify获取手机号失败: {}", e.getMessage());
|
|
|
+ return R.error("获取手机号失败,请重试");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(phone)) {
|
|
|
+ return R.error("获取手机号失败");
|
|
|
+ }
|
|
|
+ param.setPhone(phone);
|
|
|
+
|
|
|
+ FsUser userMap = findUserByPhone(param.getPhone());
|
|
|
+ if (userMap != null) {
|
|
|
+ if (StringUtils.isNotEmpty(userMap.getAppleKey()) && !param.getAppleKey().equals(userMap.getAppleKey())) {
|
|
|
+ return R.error("该手机号已绑定其他账号");
|
|
|
+ }
|
|
|
+ if (param.getSimExist() == 0 && !Md5Utils.hash(param.getPassword()).equals(userMap.getPassword())) {
|
|
|
+ return R.error("密码不正确");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ userMap = createNewAppleUser(param, param.getPhone());
|
|
|
+ }
|
|
|
+
|
|
|
+ userMap.setLoginDevice(param.getLoginDevice());
|
|
|
+ userMap.setHistoryApp("app");
|
|
|
+// if (userMap.getFirstLoginTime() == null) {
|
|
|
+// userMap.setFirstLoginTime(new Date());
|
|
|
+// }
|
|
|
+ userMap.setSource(param.getSource());
|
|
|
+ if (userMap.getNickName().equals("匿名用户**")) {
|
|
|
+ userMap.setNickName("苹果用户" + param.getPhone().substring(param.getPhone().length() - 4));
|
|
|
+ }
|
|
|
+ userMap.setAppleKey(param.getAppleKey());
|
|
|
+// addUserPortrait(userMap);
|
|
|
+ if (userService.updateFsUser(userMap)>0){
|
|
|
+ return generateTokenAndReturn(userMap);
|
|
|
+ }
|
|
|
+ return R.error("绑定手机号失败");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @ApiOperation("绑定手机号")
|
|
|
+ @PostMapping("/setPhoneOne")
|
|
|
+ public R setPhoneOne(@Validated @RequestBody FsUserEditPhoneParam param) {
|
|
|
+ if (StringUtils.isEmpty(param.getAccessToken()) || StringUtils.isEmpty(param.getOpenId())) {
|
|
|
+ return R.error("一键登录凭证不完整");
|
|
|
+ }
|
|
|
+ String phone;
|
|
|
+ try {
|
|
|
+ phone = uniVerifyUtil.getPhoneNumber(param.getAccessToken(), param.getOpenId());
|
|
|
+ } catch (CustomException e) {
|
|
|
+ return R.error(e.getMessage());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("UniVerify获取手机号失败: {}", e.getMessage());
|
|
|
+ return R.error("获取手机号失败,请重试");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(phone)) {
|
|
|
+ return R.error("获取手机号失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ param.setPhone(phone);
|
|
|
+
|
|
|
+ FsUser user = userService.selectFsUserByUnionid(param.getUnionId());
|
|
|
+ if (user == null) {
|
|
|
+ return R.error("用户数据不存在");
|
|
|
+ }
|
|
|
+ //验证码绑定,需要校验验证码
|
|
|
+ if (param.getBindType()!=null){
|
|
|
+ String encryptPhone = encryptPhone(param.getPhone());
|
|
|
+ String redisCode = redisCache.getCacheObject("sms:code:" + encryptPhone);
|
|
|
+ if (StringUtils.isEmpty(redisCode)){
|
|
|
+ return R.error("验证码已过期,请重新发送");
|
|
|
+ }
|
|
|
+ if (!redisCode.equals(param.getCode())) {
|
|
|
+ return R.error("验证码错误");
|
|
|
+ }
|
|
|
+ redisCache.deleteObject("sms:code:" + encryptPhone);
|
|
|
+ }
|
|
|
+ FsUser userMap = findUserByPhone(param.getPhone());
|
|
|
+ //绑定的手机号已存在用户的情况,将微信登录的时候创建的新号的UnionId移动到老号中,删除新号(将两个号合并)
|
|
|
+ if (userMap!=null){
|
|
|
+ if (userMap.getUserId().equals(user.getUserId())) {
|
|
|
+ user.setPhone(param.getPhone());
|
|
|
+ user.setLoginDevice(param.getLoginDevice());
|
|
|
+ user.setHistoryApp("app");
|
|
|
+// if (user.getFirstLoginTime() == null) {
|
|
|
+// user.setFirstLoginTime(new Date());
|
|
|
+// }
|
|
|
+ user.setSource(param.getSource());
|
|
|
+ userService.updateFsUser(user);
|
|
|
+// addUserPortrait(user);
|
|
|
+ return generateTokenAndReturn(user);
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(userMap.getUnionId())&&!userMap.getUnionId().equals(user.getUnionId())){
|
|
|
+ return R.error("该手机号已绑定其他微信");
|
|
|
+ }
|
|
|
+ //如果存在手机号也有用户,微信也有用户,保留创建时间比较久的用户
|
|
|
+ FsUser keepUser;
|
|
|
+ FsUser deleteUser;
|
|
|
+ if (userMap.getCreateTime().before(user.getCreateTime())){
|
|
|
+ keepUser = userMap;
|
|
|
+ deleteUser = user;
|
|
|
+ }else {
|
|
|
+ keepUser = user;
|
|
|
+ deleteUser = userMap;
|
|
|
+ }
|
|
|
+ keepUser.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null);
|
|
|
+ keepUser.setSource(param.getSource());
|
|
|
+ keepUser.setHistoryApp("app");
|
|
|
+// if (keepUser.getFirstLoginTime() == null) {
|
|
|
+// keepUser.setFirstLoginTime(new Date());
|
|
|
+// }
|
|
|
+ keepUser.setUnionId(user.getUnionId());
|
|
|
+ keepUser.setPhone(param.getPhone());
|
|
|
+ keepUser.setIntegral(keepUser.getIntegral()+deleteUser.getIntegral());
|
|
|
+ if (userService.updateFsUser(keepUser)>0){
|
|
|
+// userService.realDeleteFsUserByUserId(deleteUser.getUserId());
|
|
|
+ userService.deleteFsUserByUserId(deleteUser.getUserId());
|
|
|
+ return generateTokenAndReturn(keepUser);
|
|
|
+ }
|
|
|
+ return R.error("绑定手机号失败");
|
|
|
+ }
|
|
|
+ user.setPhone(param.getPhone());
|
|
|
+ user.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null );
|
|
|
+ user.setHistoryApp("app");
|
|
|
+// if (user.getFirstLoginTime() == null) {
|
|
|
+// user.setFirstLoginTime(new Date());
|
|
|
+// }
|
|
|
+ user.setSource(param.getSource()!= null ? param.getSource() : null);
|
|
|
+ userMap = new FsUser();
|
|
|
+ userMap.setLoginDevice(param.getLoginDevice());
|
|
|
+ userMap.setHistoryApp("app");
|
|
|
+// if (userMap.getFirstLoginTime() == null) {
|
|
|
+// userMap.setFirstLoginTime(new Date());
|
|
|
+// }
|
|
|
+ userMap.setSource(param.getSource());
|
|
|
+ if (user.getNickName().equals("匿名用户**")) {
|
|
|
+ userMap.setNickName("匿名用户" + param.getPhone().substring(param.getPhone().length() - 4));
|
|
|
+ }
|
|
|
+ userMap.setUserId(user.getUserId());
|
|
|
+ userMap.setPhone(param.getPhone());
|
|
|
+// addUserPortrait(user);
|
|
|
+ if (userService.updateFsUser(userMap)>0){
|
|
|
+ return generateTokenAndReturn(user);
|
|
|
+ }
|
|
|
+ return R.error("绑定手机号失败");
|
|
|
+ }
|
|
|
+
|
|
|
@ApiOperation("绑定手机号")
|
|
|
@PostMapping("/setPhone")
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@@ -870,6 +1065,158 @@ public class AppLoginController extends AppBaseController{
|
|
|
return generateTokenAndReturn(user);
|
|
|
}
|
|
|
|
|
|
+ @ApiOperation("UniApp一键登录选择账号(安全)")
|
|
|
+ @PostMapping("/loginByUserIdUniverify")
|
|
|
+ @Transactional
|
|
|
+ @RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
|
|
|
+ public R loginByUserIdUniverify(@RequestBody FsUserLoginParam param) {
|
|
|
+ if (StringUtils.isEmpty(param.getAccessToken()) || StringUtils.isEmpty(param.getOpenId())) {
|
|
|
+ return R.error("一键登录凭证不完整");
|
|
|
+ }
|
|
|
+// String tokenCacheKey = "univerify:used:" + param.getAccessToken();
|
|
|
+// if (redisCache.getCacheObject(tokenCacheKey) != null) {
|
|
|
+// return R.error("登录凭证已失效,请重新授权");
|
|
|
+// }
|
|
|
+ String phone;
|
|
|
+ try {
|
|
|
+ phone = uniVerifyUtil.getPhoneNumber(param.getAccessToken(), param.getOpenId());
|
|
|
+ } catch (CustomException e) {
|
|
|
+ return R.error(e.getMessage());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("UniVerify获取手机号失败: {}", e.getMessage());
|
|
|
+ return R.error("获取手机号失败,请重试");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(phone)) {
|
|
|
+ return R.error("获取手机号失败");
|
|
|
+ }
|
|
|
+// redisCache.setCacheObject(tokenCacheKey, "1", 1, TimeUnit.MINUTES);
|
|
|
+ param.setPhone(phone);
|
|
|
+ return handleSecurePhoneLoginByUserId(param);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * UniApp 一键登录(安全):手机号已由 uniCloud 校验,不信任客户端传入。
|
|
|
+ */
|
|
|
+ private R handleSecurePhoneLogin(FsUserLoginParam param) {
|
|
|
+ FsUser user = null;
|
|
|
+ String encryptPhone = encryptPhone(param.getPhone());
|
|
|
+ List<FsUser> usersByPhone = findUsersByPhone(encryptPhone);
|
|
|
+ if (CollectionUtil.isEmpty(usersByPhone)) {
|
|
|
+ R newUserResponse = buildNewAppUserLoginResponse(param, encryptPhone);
|
|
|
+ if (newUserResponse != null) {
|
|
|
+ return newUserResponse;
|
|
|
+ }
|
|
|
+ usersByPhone = findUsersByPhone(encryptPhone);
|
|
|
+ if (CollectionUtil.isEmpty(usersByPhone)) {
|
|
|
+ return R.error("注册失败,请重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (usersByPhone.size() == 1) {
|
|
|
+ user = usersByPhone.get(0);
|
|
|
+ if (user.getUnionId() == null) {
|
|
|
+ if (user.getPhone().length() <= 11) {
|
|
|
+ FsUser fsUser = new FsUser();
|
|
|
+ fsUser.setUserId(user.getUserId());
|
|
|
+ fsUser.setPhone(encryptPhone);
|
|
|
+ userMapper.updateFsUser(fsUser);
|
|
|
+ }
|
|
|
+ return R.ok().put("isNew", true).put("phone", encryptPhone);
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(param.getJpushId())) {
|
|
|
+ updateExistingUserJpushId(user, param.getJpushId());
|
|
|
+// try {
|
|
|
+// fsUserCouponService.sendRegisterCoupon(user);
|
|
|
+// } catch (Exception e) {
|
|
|
+// logger.error("发送注册优惠券失败:{}", e.getMessage());
|
|
|
+// }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (FsUser fsUser : usersByPhone) {
|
|
|
+ fsUser.setPhone("***********");
|
|
|
+ }
|
|
|
+ return R.ok().put("users", usersByPhone);
|
|
|
+ }
|
|
|
+ user.setPhone("***********");
|
|
|
+ return generateTokenAndReturn(user);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 多账号场景下按 userId 登录,手机号已由 uniCloud 校验。
|
|
|
+ */
|
|
|
+ private R handleSecurePhoneLoginByUserId(FsUserLoginParam param) {
|
|
|
+ List<FsUser> usersByPhone = findUsersByPhone(param.getPhone());
|
|
|
+ if (CollectionUtil.isEmpty(usersByPhone)){
|
|
|
+ FsUser newUser = createNewUser(param);
|
|
|
+ if (StringUtils.isNotEmpty(newUser.getJpushId())) {
|
|
|
+// try {
|
|
|
+// //发送注册优惠券
|
|
|
+// fsUserCouponService.sendRegisterCoupon(newUser);
|
|
|
+// } catch (Exception e) {
|
|
|
+// logger.error("发送注册优惠券失败:{}",e.getMessage());
|
|
|
+// }
|
|
|
+ }
|
|
|
+ return R.ok().put("isNew",true).put("phone",encryptPhone(param.getPhone()));
|
|
|
+ }
|
|
|
+ if (usersByPhone.size() == 1) {
|
|
|
+ FsUser user = usersByPhone.get(0);
|
|
|
+ if (StringUtils.isNotEmpty(param.getJpushId())) {
|
|
|
+ updateExistingUserJpushId(user, param.getJpushId());
|
|
|
+ }
|
|
|
+ return generateTokenAndReturn(user);
|
|
|
+ }
|
|
|
+ if (param.getUserId() == null) {
|
|
|
+ return R.error("请选择登录账号");
|
|
|
+ }
|
|
|
+ for (FsUser fsUser : usersByPhone) {
|
|
|
+ if (fsUser.getUserId().equals(param.getUserId())) {
|
|
|
+ if (StringUtils.isNotEmpty(param.getJpushId())) {
|
|
|
+ updateExistingUserJpushId(fsUser, param.getJpushId());
|
|
|
+ }
|
|
|
+ return generateTokenAndReturn(fsUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.error("账号不匹配,请检查账号");
|
|
|
+ }
|
|
|
+
|
|
|
+ private R buildNewAppUserLoginResponse(FsUserLoginParam param, String encryptedPhone) {
|
|
|
+ FsUser newUser = createNewUser(param);
|
|
|
+ if (newUser.getUserId() == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+// if (StringUtils.isNotEmpty(newUser.getJpushId())) {
|
|
|
+// try {
|
|
|
+// fsUserCouponService.sendRegisterCoupon(newUser);
|
|
|
+// } catch (Exception e) {
|
|
|
+// logger.error("发送注册优惠券失败:{}", e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// String json = configService.selectConfigByKey("his.integral");
|
|
|
+// IntegralConfig config = JSONUtil.toBean(json, IntegralConfig.class);
|
|
|
+// FsCourseReward rewardConfig = courseRewardMapper.selectFsCourseRewardById(config.getRewardId());
|
|
|
+// if (Objects.isNull(rewardConfig)) {
|
|
|
+// throw new CustomException("销售公司未配置" + ",请选择其他奖励类型");
|
|
|
+// }
|
|
|
+// if (com.fs.common.utils.StringUtils.isBlank(rewardConfig.getActualRewards())) {
|
|
|
+// throw new CustomException("配置错误,请联系管理员#1");
|
|
|
+// }
|
|
|
+// JSONArray jsonArray;
|
|
|
+// try {
|
|
|
+//// JSONArray jsonArrayOld = JSON.parseArray(rewardConfig.getActualRewards());
|
|
|
+// jsonArray = buildGrandGiftArrayLls(jsonArrayOld, newUser.getUserId());
|
|
|
+// } catch (Exception e) {
|
|
|
+// logger.error("解析{}配置JSON失败", e);
|
|
|
+// throw new CustomException("配置错误,请联系管理员#2");
|
|
|
+// }
|
|
|
+// if (jsonArray == null || jsonArray.isEmpty()) {
|
|
|
+// throw new CustomException("配置错误,请联系管理员#3");
|
|
|
+// }
|
|
|
+ return R.ok().put("isNew", true).put("phone", encryptedPhone);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
private FsUser createNewUser(FsUserLoginParam param) {
|
|
|
FsUser newUser = new FsUser();
|
|
|
newUser.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null);
|