代码提交

This commit is contained in:
2023-06-08 11:28:13 +08:00
parent b53456d41c
commit ec6e27a4eb
23 changed files with 1308 additions and 4 deletions

View File

@@ -0,0 +1,141 @@
package com.njcn.user.controller.app;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
import com.njcn.user.service.IAppUserService;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.app.AESUtil;
import com.njcn.web.utils.app.XssFilterUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.ocsp.ResponseData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 类的介绍:
*
* @author xuyang
* @version 1.0.0
* @createTime 2023/6/7 8:51
*/
@Validated
@Slf4j
@RestController
@RequestMapping("/appUser")
@Api(tags = "App用户信息管理")
@AllArgsConstructor
public class AppUserController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(AppUserController.class);
private final IAppUserService appUserService;
/**
* 获取(登录、注册、忘记密码、重新绑定手机)验证码
*/
@PostMapping("authCode")
@OperateInfo
@ApiOperation(value = "获取验证码", notes = "获取验证码")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
@ApiImplicitParam(name = "type", value = "验证码类型", required = true, paramType = "query"),
})
public HttpResult<String> authCode(String phone, String devCode, String type) {
String methodDescribe = getMethodDescribe("authCode");
appUserService.setMessage(phone,devCode,type);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, "success", methodDescribe);
}
/**
* 手机app注册
*/
@PostMapping("register")
@OperateInfo
@ApiOperation(value = "注册入口", notes = "用户注册")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<AppUserResultVO> register(String phone, String code, String devCode) {
String methodDescribe = getMethodDescribe("register");
AppUserResultVO appUserResultVo = appUserService.register(phone,code,devCode);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, appUserResultVo, methodDescribe);
}
/**
* 手机app密码设置
*/
@PostMapping("setPsd")
@OperateInfo
@ApiOperation(value = "设置密码", notes = "设置密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户索引", required = true, paramType = "query"),
@ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<String> setPsd(String userId, String password, String devCode) {
String methodDescribe = getMethodDescribe("setPsd");
appUserService.setPsd(userId, devCode, password);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, "success", methodDescribe);
}
/**
* 手机app登录入口
*/
@PostMapping("login")
@OperateInfo
@ApiOperation(value = "登录入口", notes = "APP登录")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "type", value = "登录类型", required = true, paramType = "query"),
@ApiImplicitParam(name = "key", value = "验证码/密码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<AppUserResultVO> login(String phone, String type, String key, String devCode, HttpServletRequest request) {
String methodDescribe = getMethodDescribe("login");
AppUserResultVO appUserResultVo = appUserService.login(phone,type,key,devCode);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, appUserResultVo, methodDescribe);
}
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
/**
* <p>
* APP用户消息配置表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
public interface AppInfoSetMapper extends BaseMapper<AppInfoSet> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppSendMsg;
/**
* <p>
* App手机验证码发送记录表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface AppSendMsgMapper extends BaseMapper<AppSendMsg> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppUser;
/**
* <p>
* App用户表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface AppUserMapper extends BaseMapper<AppUser> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.user.pojo.po.app.AppInfoSet;
/**
* <p>
* APP用户消息配置表 服务类
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
public interface IAppInfoSetService extends IService<AppInfoSet> {
}

View File

@@ -0,0 +1,15 @@
package com.njcn.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.user.pojo.po.app.AppSendMsg;
/**
* <p>
* App手机验证码发送记录表 服务类
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface IAppSendMsgService extends IService<AppSendMsg> {
}

View File

@@ -0,0 +1,43 @@
package com.njcn.user.service;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
/**
* @author xuyang
*/
public interface IAppUserService {
/**
* 发送短信
* @param phone 手机号
* @param devCode 设备码
* @param type 验证码类型
*/
void setMessage(String phone, String devCode, String type);
/**
* 手机app注册(所有用户初始统一为游客,需要特定的码升级)
* @param phone 手机号
* @param code 验证码
* @param devCode 设备码
*/
AppUserResultVO register(String phone, String code, String devCode);
/**
* 用户设置密码
* @param userId 用户id
* @param devCode 设备码
* @param password 密码
*/
void setPsd(String userId, String devCode, String password);
/**
* 用户设置密码
* @param phone 手机号
* @param type 登陆类型
* @param key 验证码/密码
* @param devCode 设备码
*/
AppUserResultVO login(String phone, String type, String key, String devCode);
}

View File

@@ -0,0 +1,20 @@
package com.njcn.user.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.user.mapper.AppInfoSetMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
import com.njcn.user.service.IAppInfoSetService;
import org.springframework.stereotype.Service;
/**
* <p>
* APP用户消息配置表 服务实现类
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
@Service
public class AppInfoSetServiceImpl extends ServiceImpl<AppInfoSetMapper, AppInfoSet> implements IAppInfoSetService {
}

View File

@@ -0,0 +1,20 @@
package com.njcn.user.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.user.mapper.AppSendMsgMapper;
import com.njcn.user.pojo.po.app.AppSendMsg;
import com.njcn.user.service.IAppSendMsgService;
import org.springframework.stereotype.Service;
/**
* <p>
* App手机验证码发送记录表 服务实现类
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
@Service
public class AppSendMsgServiceImpl extends ServiceImpl<AppSendMsgMapper, AppSendMsg> implements IAppSendMsgService {
}

View File

@@ -0,0 +1,305 @@
package com.njcn.user.service.impl;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.user.enums.MessageEnum;
import com.njcn.user.enums.UserLevelEnum;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.mapper.AppUserMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
import com.njcn.user.pojo.po.app.AppSendMsg;
import com.njcn.user.pojo.po.app.AppUser;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
import com.njcn.user.service.IAppInfoSetService;
import com.njcn.user.service.IAppSendMsgService;
import com.njcn.user.service.IAppUserService;
import com.njcn.web.utils.app.AESUtil;
import com.njcn.web.utils.app.XssFilterUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Random;
/**
* 类的介绍:
*
* @author xuyang
* @version 1.0.0
* @createTime 2023/6/7 14:42
*/
@Service
@AllArgsConstructor
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements IAppUserService {
private static final Logger logger = LoggerFactory.getLogger(AppUserServiceImpl.class);
private final RedisUtil redisUtil;
private final IAppSendMsgService appSendMsgService;
private final IAppInfoSetService appInfoSetService;
@Override
@Transactional(rollbackFor = Exception.class)
public void setMessage(String phone, String devCode, String type) {
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
String msgTemplate;
switch (type) {
case "0":
msgTemplate = MessageEnum.getTemplateByCode(0);
break;
case "1":
msgTemplate = MessageEnum.getTemplateByCode(1);
break;
case "2":
msgTemplate = MessageEnum.getTemplateByCode(2);
break;
case "3":
msgTemplate = MessageEnum.getTemplateByCode(3);
break;
case "4":
msgTemplate = MessageEnum.getTemplateByCode(4);
break;
case "5":
msgTemplate = MessageEnum.getTemplateByCode(5);
break;
default:
throw new BusinessException(UserResponseEnum.CODE_TYPE_ERROR);
}
//type为4账号替换为新手机号
if (!msgTemplate.equalsIgnoreCase(MessageEnum.REGISTER.getTemplateCode())) {
AppUser appUser = this.lambdaQuery().eq(AppUser::getPhone,phone).one();
if ("4".equalsIgnoreCase(type)) {
//注册,无需判断手机号与设备的匹配
if (appUser != null) {
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_FAIL);
}
} else {
if (null == appUser) {
throw new BusinessException(UserResponseEnum.LOGIN_USERNAME_NOT_FOUND);
} else {
appUser.setDevCode(devCode);
logger.info("更新手机id" + devCode);
this.updateById(appUser);
}
}
}
//开始执行短信发送
//设置超时时间-可自行调整
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化ascClient需要的几个参数
//短信API产品名称短信产品名固定无需修改
final String product = "Dysmsapi";
//短信API产品域名接口地址固定无需修改
final String domain = "dysmsapi.aliyuncs.com";
//替换成你的AK
//你的accessKeyId,参考本文档步骤2
final String accessKeyId = "LTAI4FxsR76x2dq3w9c5puUe";
//你的accessKeySecret参考本文档步骤2
final String accessKeySecret = "GxkTR8fsrvHtixTlD9UPmOGli35tZs";
//初始化ascClient,暂时不支持多region请勿修改
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setMethod(MethodType.POST);
request.setPhoneNumbers(phone);
//必填:短信签名-可在短信控制台中找到
request.setSignName("灿能云");
//必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版
request.setTemplateCode(msgTemplate);
String vcode = getMessageCode();
String code = "{\"code\":\"" + vcode + "\"}";
request.setTemplateParam(code);
//请求失败这里会抛ClientException异常
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
String key = phone + devCode;
if (sendSmsResponse.getCode() != null && "OK".equals(sendSmsResponse.getCode())) {
//成功发送短信验证码后保存进redis
redisUtil.saveByKeyWithExpire(key, vcode, 300L);
} else {
throw new BusinessException(UserResponseEnum.SEND_CODE_FAIL);
}
AppSendMsg appSendMsg = new AppSendMsg();
appSendMsg.setPhone(phone);
appSendMsg.setMessage(vcode);
appSendMsg.setSendTime(LocalDateTime.now());
appSendMsg.setSendStatus(sendSmsResponse.getCode() == null ? "无状态" : sendSmsResponse.getCode());
appSendMsgService.save(appSendMsg);
} catch (Exception e) {
logger.error("发送短信异常,异常为:"+e.getMessage());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.SEND_CODE_FAIL);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public AppUserResultVO register(String phone, String code, String devCode) {
AppUserResultVO appUserResultVo = new AppUserResultVO();
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
judgeCode(phone, code, devCode);
//先根据手机号查询是否已被注册
AppUser appUser = this.lambdaQuery().eq(AppUser::getPhone,phone).one();
if (!Objects.isNull(appUser)){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_REPEAT);
} else {
appUser = new AppUser();
appUser.setPhone(phone);
appUser.setLoginErrorTimes(0);
appUser.setLoginTime(LocalDateTime.now());
appUser.setPsdValidity(appUser.getLoginTime());
appUser.setRegisterTime(appUser.getLoginTime());
appUser.setUserLevel("5");
appUser.setDevCode(devCode);
logger.info("插入手机id" + devCode);
appUser.setReferralCode("DUCxda");
appUser.setState(1);
this.save(appUser);
//消息默认配置
AppInfoSet appInfoSet = new AppInfoSet();
appInfoSet.setUserIndex(appUser.getUserIndex());
appInfoSet.setDeviceInfo(1);
appInfoSet.setEventInfo(1);
appInfoSet.setSystemInfo(1);
appInfoSet.setHarmonicInfo(1);
appInfoSetService.save(appInfoSet);
//配置返回数据
appUserResultVo.setUserId(appUser.getUserIndex());
appUserResultVo.setRoleName(UserLevelEnum.getMsgByCode(appUser.getUserLevel()));
appUserResultVo.setPhone(appUser.getPhone());
appUserResultVo.setRoleCode(appUser.getUserLevel());
appUserResultVo.setUserName(StringUtils.isEmpty(appUser.getName()) ? null : appUser.getName());
}
} catch (Exception e) {
logger.error("app用户注册异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.REGISTER_FAIL);
}
}
return appUserResultVo;
}
@Override
public void setPsd(String userId, String devCode, String password) {
//参数校验
if (StringUtils.isBlank(userId)) {
throw new BusinessException(UserResponseEnum.LOGIN_USER_INDEX_INVALID);
}
if (StringUtils.isBlank(userId)) {
throw new BusinessException(UserResponseEnum.PASSWORD_INVALID);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
//查看是否存在该用户
AppUser appUser = this.lambdaQuery().eq(AppUser::getUserIndex,userId).one();
if (Objects.isNull(appUser)){
throw new BusinessException(UserResponseEnum.LOGIN_USERNAME_NOT_FOUND);
} else {
String appPwd = AESUtil.aesPKCS5PaddingEncrypt(password);
appUser.setPassword(appPwd);
appUser.setDevCode(devCode);
logger.info("更新手机id" + devCode);
this.updateById(appUser);
}
} catch (Exception e) {
logger.error("app用户设置密码异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.PASSWORD_SET_ERROR);
}
}
}
@Override
public AppUserResultVO login(String phone, String type, String key, String devCode) {
//参数校验
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
if (StringUtils.isBlank(key)) {
throw new BusinessException(UserResponseEnum.KEY_WRONG);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
AppUserResultVO vo = new AppUserResultVO();
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
} catch (Exception e) {
logger.error("app用户设置密码异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.LOGIN_ERROR);
}
}
return vo;
}
/**
* 自定义获取验证码,固定为字母和数字的组合
*/
private String getMessageCode() {
String result = "";
char[] numbers = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
//填充数字
for (int i = 0; i < 6; i++) {
int numberIndex = new Random().nextInt(10);
result = result + numbers[numberIndex];
}
return result;
}
private void judgeCode(String phone, String code, String devCode) {
String key = phone + devCode;
String redisCode = redisUtil.getStringByKey(key);
if (StringUtils.isEmpty(redisCode) || !code.equalsIgnoreCase(redisCode)) {
throw new BusinessException(UserResponseEnum.LOGIN_WRONG_CODE);
} else {
//存在且正确的验证,用完即删
redisUtil.delete(key);
}
}
}