package com.xzx.gc.user.controller;
|
|
import cn.hutool.core.codec.Base64;
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONUtil;
|
import com.aliyuncs.exceptions.ClientException;
|
import com.xzx.gc.common.Result;
|
import com.xzx.gc.common.annotations.PassToken;
|
import com.xzx.gc.common.annotations.valid.InsertExtend;
|
import com.xzx.gc.common.constant.Constants;
|
import com.xzx.gc.common.constant.PayEnum;
|
import com.xzx.gc.common.constant.RedisKeyConstant;
|
import com.xzx.gc.common.dto.CommonDto;
|
import com.xzx.gc.common.dto.log.OperationAppLog;
|
import com.xzx.gc.common.exception.RestException;
|
import com.xzx.gc.common.request.BaseController;
|
import com.xzx.gc.common.utils.*;
|
import com.xzx.gc.common.utils.image.GraphicsUtils;
|
import com.xzx.gc.common.utils.wxpay.WxUtil;
|
import com.xzx.gc.entity.*;
|
import com.xzx.gc.model.user.UserInfoVo;
|
import com.xzx.gc.model.user.UserReq;
|
import com.xzx.gc.user.dto.*;
|
import com.xzx.gc.user.mapper.AccountMapper;
|
import com.xzx.gc.user.mapper.OtherUserMapper;
|
import com.xzx.gc.user.mapper.UserDeviceMapper;
|
import com.xzx.gc.user.mapper.UserMapper;
|
import com.xzx.gc.user.service.*;
|
import io.swagger.annotations.Api;
|
import io.swagger.annotations.ApiOperation;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import javax.crypto.Cipher;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import javax.servlet.http.HttpServletRequest;
|
import java.security.NoSuchAlgorithmException;
|
import java.security.spec.AlgorithmParameterSpec;
|
import java.util.List;
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
/**
|
* @author:andylei
|
* @title
|
* @Description
|
* @date 2018/11/22/022
|
* @修改历史
|
*/
|
@Api(tags = "登录验证码相关")
|
@RequestMapping("/")
|
@RestController
|
@Slf4j
|
@Validated
|
public class LoginController extends BaseController {
|
|
@Autowired
|
private BusinessUtil businessUtil;
|
|
@Autowired
|
private AccountService accountService;
|
|
@Autowired
|
private GraphicsUtils graphicsUtils;
|
@Autowired
|
public UserLoginService userLoginService;
|
@Autowired
|
public UserService userService;
|
|
@Autowired
|
private WxUtil wxUtil;
|
|
@Autowired
|
private RedisUtil redisUtil;
|
|
@Autowired
|
private TokenUtil tokenUtil;
|
|
@Autowired
|
private OtherUserService otherUserService;
|
|
@Autowired
|
private UserStatService userStatService;
|
|
@Autowired
|
private AccountMapper accountMapper;
|
|
@Autowired
|
private OtherUserMapper otherUserMapper;
|
|
@Autowired
|
private UserDeviceMapper userDeviceMapper;
|
|
@Autowired
|
private UserMapper userMapper;
|
|
@Autowired
|
private AccountBindService accountBindService;
|
|
|
@Autowired
|
private MqUtil mqUtil;
|
|
|
|
/**
|
* 用户密码登录
|
*/
|
@ApiOperation( value = "手机号加密码登录")
|
@PostMapping("/loginPwd")
|
@PassToken
|
public Result<LoginPwdResDto> login(HttpServletRequest request,@Validated @RequestBody LoginPwdDto loginPwdDto) throws NoSuchAlgorithmException {
|
Result result = new Result();
|
LoginPwdResDto loginPwdResDto = null;
|
String openId = loginPwdDto.getOpenId();
|
if(StrUtil.isBlank(openId)) {
|
try {
|
loginPwdDto.setPwd(SecurityUtil.decrypt(Constants.PWD_DECRET, loginPwdDto.getPwd()));
|
} catch (Exception e) {
|
log.warn("解密失败:" + loginPwdDto.getPwd(), e);
|
result.setCode(-1);
|
result.setMsg("密码格式错误");
|
return result;
|
}
|
}else {
|
|
//分两种情况 一种是带手机号及密码和openid的登录绑定 第二种是只有openId的判断是否绑定
|
|
if(StrUtil.isBlank(loginPwdDto.getPwd())){
|
List<OtherUserInfo> byOpenId = otherUserService.findByOpenId(openId);
|
if(CollUtil.isNotEmpty(byOpenId)){
|
loginPwdDto.setMobile(byOpenId.get(0).getMobilePhone());
|
loginPwdDto.setPwd(SecurityUtil.decrypt(byOpenId.get(0).getSalt(), byOpenId.get(0).getPassword()));
|
}else {
|
loginPwdResDto=new LoginPwdResDto();
|
loginPwdResDto.setBindFlag(Convert.toShort(Constants.DEL_FLAG));
|
return Result.success(loginPwdResDto);
|
}
|
}else{
|
String decrypt = SecurityUtil.decrypt(Constants.PWD_DECRET, loginPwdDto.getPwd());
|
if(StrUtil.isBlank(decrypt)){
|
log.warn("解密失败:" + loginPwdDto.getPwd());
|
result.setCode(-1);
|
result.setMsg("密码格式错误");
|
return result;
|
}else {
|
loginPwdDto.setPwd(decrypt);
|
}
|
}
|
|
}
|
|
if(StringUtils.isBlank(loginPwdDto.getDevCode())){
|
throw new RestException(-1,"设备标识不能为空");
|
}
|
|
|
loginPwdResDto = otherUserService.findByMobileAndPwd(loginPwdDto.getMobile(), loginPwdDto.getPwd());
|
|
int flag = loginPwdResDto.getFlag();
|
if(flag==-1){
|
result.setCode(-1);
|
result.setMsg("用户被禁用");
|
}else if(flag==-2){
|
result.setCode(-1);
|
result.setMsg("用户名或密码不正确");
|
}else if(flag==-3){
|
result.setCode(-1);
|
result.setMsg("用户不存在");
|
}else{
|
|
//openid绑定
|
if(StrUtil.isNotBlank(openId)){
|
otherUserService.updateOpenIdByMobile(openId,loginPwdResDto.getMobilePhone());
|
|
//自动绑定
|
String userId = loginPwdResDto.getUserId();
|
AccountInfo byUserId = accountService.findByUserId(userId);
|
|
AccountBindInfo byAccountIdAndType = accountBindService.findByAccountIdAndType(byUserId.getAccountId(), Convert.toShort(PayEnum.微信.getValue()));
|
if(byAccountIdAndType==null){
|
AccountBindInfo accountBindInfo=new AccountBindInfo();
|
accountBindInfo.setAccountId(byUserId.getAccountId());
|
accountBindInfo.setAccountType(Convert.toShort(PayEnum.微信.getValue()));
|
accountBindInfo.setAccountNumber(openId);
|
accountBindService.add(accountBindInfo);
|
}else{
|
//openid不一致则更新绑定
|
if(!openId.equals(byAccountIdAndType.getAccountNumber())) {
|
byAccountIdAndType.setAccountNumber(openId);
|
accountBindService.updateById(byAccountIdAndType);
|
}
|
}
|
}
|
|
//设备绑定
|
if(StrUtil.isNotBlank(loginPwdDto.getDevCode())){
|
UserDevice userDevice=new UserDevice();
|
userDevice.setDeviceCode(loginPwdDto.getDevCode());
|
userDevice.setUserId(loginPwdResDto.getUserId());
|
List<UserDevice> deviceList = userDeviceMapper.select(userDevice);
|
if(CollUtil.isNotEmpty(deviceList)){
|
UserDevice select = deviceList.get(0);
|
select.setCreateTime(DateUtil.now());
|
select.setDeviceVersion(loginPwdDto.getDeviceVersion());
|
select.setDeviceName(loginPwdDto.getDeviceName());
|
userDeviceMapper.updateByPrimaryKeySelective(select);
|
}else {
|
userDevice.setCreateTime(DateUtil.now());
|
userDevice.setDeviceVersion(loginPwdDto.getDeviceVersion());
|
userDevice.setDeviceName(loginPwdDto.getDeviceName());
|
userDeviceMapper.insertSelective(userDevice);
|
}
|
}
|
|
//token
|
String token=tokenUtil.generateToken();
|
redisUtil.setex(Constants.REDIS_USER_KEY+"token:"+loginPwdResDto.getUserId(),token,tokenUtil.getTimeOut());
|
loginPwdResDto.setToken(token);
|
loginPwdResDto.setBindFlag(Convert.toShort(Constants.DEL_NOT_FLAG));
|
result.setData(loginPwdResDto);
|
|
}
|
return result;
|
}
|
|
|
@ApiOperation( value = "修改密码")
|
@PostMapping("/updatePwd")
|
public Result updatePwd(HttpServletRequest request,@Validated @RequestBody UpdatePwdDto updatePwdDto) {
|
|
Result result=new Result();
|
|
if (decrptPwd(updatePwdDto, result)) return result;
|
|
//检验手机是否是自己的
|
String mobile = updatePwdDto.getMobile();
|
String userId = getUserId(request);
|
OtherUserInfo byId = otherUserService.findById(userId);
|
if(byId==null||!byId.getMobilePhone().equals(mobile)){
|
return Result.error(-1,"手机号码不正确");
|
}
|
|
otherUserService.pwdUpdate(updatePwdDto, result, mobile);
|
|
String mobilePhone = userService.findOtherByUserId(getUserId(request),0);
|
OperationAppLog build = OperationAppLog.builder().appPrograme(getFrontClient(request)).opreateName(mobilePhone)
|
.methodName(Constants.USER_MODUL_NAME).operateAction("修改密码-"+getUserId(request)).build();
|
mqUtil.sendApp(build);
|
|
return result;
|
|
}
|
|
|
@ApiOperation( value = "忘记密码")
|
@PostMapping("/forgetPwd")
|
@PassToken
|
public Result forgetPwd(@Validated @RequestBody UpdatePwdDto updatePwdDto,HttpServletRequest request) {
|
|
Result result=new Result();
|
|
if (decrptPwd(updatePwdDto, result)){
|
return result;
|
}
|
|
//检验手机是否是当前系统中的
|
String mobile = updatePwdDto.getMobile();
|
List<AccountInfo> select =accountService.findByMobile(mobile);
|
if(CollUtil.isEmpty(select)){
|
return Result.error(-1,"手机号码不正确");
|
}
|
|
otherUserService.pwdUpdate(updatePwdDto, result, mobile);
|
|
String mobilePhone = userService.findOtherByUserId(getUserId(request),0);
|
OperationAppLog build = OperationAppLog.builder().appPrograme(getFrontClient(request)).opreateName(mobilePhone)
|
.methodName(Constants.USER_MODUL_NAME).operateAction("找回密码-"+getUserId(request)).build();
|
mqUtil.sendApp(build);
|
|
return result;
|
|
}
|
|
private boolean decrptPwd(@Validated @RequestBody UpdatePwdDto updatePwdDto, Result result) {
|
try {
|
updatePwdDto.setNewPwd(SecurityUtil.decrypt(Constants.PWD_DECRET,updatePwdDto.getNewPwd()));
|
updatePwdDto.setNewPwdSure(SecurityUtil.decrypt(Constants.PWD_DECRET,updatePwdDto.getNewPwdSure()));
|
} catch (Exception e) {
|
log.warn("解密失败:"+updatePwdDto.getNewPwd(),e);
|
result.setCode(-1);
|
result.setMsg("密码格式错误");
|
return true;
|
}
|
return false;
|
}
|
|
|
/**
|
* 用户登录
|
* @param userReq
|
*/
|
@ApiOperation( value = "手机号+验证码登录")
|
@PostMapping("/login")
|
@PassToken
|
public Result<List<UserInfoVo>> login(HttpServletRequest request,@RequestBody UserReq userReq) throws NoSuchAlgorithmException {
|
Result result = new Result();
|
int returnvalue = userLoginService.login(userReq);
|
if (returnvalue==-1){
|
result.setCode(-1);
|
result.setMsg("验证码已经失效,有效期两分钟");
|
}else if (returnvalue==-2){
|
result.setCode(-1);
|
result.setMsg("验证码错误");
|
}else if (returnvalue==-3){
|
result.setCode(-1);
|
result.setMsg("同一微信用户只能绑定一个手机号码,请用正确的手机号码登录");
|
}else if(returnvalue==-4){
|
result.setCode(-4);
|
result.setMsg("用户OPENID不能为空");
|
}else if (returnvalue>=0){
|
//返回用户信息及token给前台
|
List<UserInfoVo> userList = userService.queryUserInfo(userReq);
|
UserInfoVo userInfoVo = userList.get(0);
|
//保存token
|
String token=tokenUtil.generateToken();
|
redisUtil.setex(Constants.REDIS_USER_KEY+"token:"+userInfoVo.getUserId(),token,tokenUtil.getTimeOut());
|
userInfoVo.setToken(token);
|
redisUtil.hset(RedisKeyConstant.USER_INFO,userReq.getOpenId(),JSONUtil.toJsonStr(userInfoVo));
|
result.setData(userList);
|
redisUtil.del(Constants.REDIS_USER_KEY + "code:channel:" + userReq.getMobilePhone());
|
}
|
return result;
|
}
|
|
@ApiOperation( value = "获取用户信息",notes = "id为openId")
|
@PostMapping("/login/getUserInfo")
|
@PassToken
|
public Result<UserInfoVo> getUserInfo(HttpServletRequest request,@RequestBody CommonDto commonDto){
|
|
UserInfo byOpenId = userService.findByOpenId(commonDto.getId());
|
|
if(byOpenId!=null){
|
String userId = byOpenId.getUserId();
|
if(redisUtil.exists(RedisKeyConstant.TOKEN+userId)) {
|
String hget = redisUtil.hget(RedisKeyConstant.USER_INFO, commonDto.getId());
|
if (StrUtil.isNotBlank(hget)) {
|
UserInfoVo userInfoVo = JSONUtil.toBean(hget, UserInfoVo.class);
|
userInfoVo.setNickName(StringUtils.decode(userInfoVo.getNickName()));
|
userInfoVo.setAvatarUrl(userInfoVo.getAvatar());
|
return Result.success(userInfoVo);
|
}
|
}
|
}
|
|
return Result.error(-3,"用户不存在");
|
}
|
|
/**
|
* 根据手机号获取验证码
|
* @param userReq
|
*/
|
@ApiOperation( value = "根据手机号获取验证码")
|
@PostMapping("/login/verifycode")
|
@PassToken
|
public Result<UserInfoVo> getVerifyCode(HttpServletRequest request,@RequestBody UserReq userReq) throws ClientException {
|
|
String phoneNum = userReq.getMobilePhone();
|
Result result = new Result();
|
if (phoneNum==null || "".equals(phoneNum)){
|
result.setCode(-1);
|
result.setMsg("手机号为空");
|
}
|
|
String key="";
|
key=Constants.REDIS_USER_KEY+"code:"+phoneNum;
|
String code = redisUtil.get(key);
|
if (StringUtils.isNotBlank(code)){
|
result.setCode(-1);
|
result.setMsg("验证码需60秒后重新获取");
|
return result;
|
}
|
|
|
//忘记密码
|
if(userReq.getSmsType()==1) {
|
List<AccountInfo> select = accountService.findByMobile(phoneNum);
|
if (CollUtil.isEmpty(select)) {
|
return Result.error(-1, "手机号码不正确");
|
}
|
}
|
|
|
|
String verifyCode = userLoginService.getVerifyCode(phoneNum, userReq.getSmsType());
|
|
if(Convert.toStr(Constants.RESULT_SUCCESS).equals(verifyCode)){
|
UserInfoVo userInfoVo = new UserInfoVo();
|
long currentTime = System.currentTimeMillis();
|
userInfoVo.setTimestamp(String.valueOf(currentTime));
|
result.setData(userInfoVo);
|
return result;
|
}else{
|
result.setCode(-1);
|
result.setMsg(verifyCode);
|
return result;
|
}
|
}
|
|
|
|
|
@ApiOperation(value = "调用微信接口生成二维码")
|
@PostMapping(value = "/acode")
|
public Result getacodepost(HttpServletRequest request,@Validated(value = {InsertExtend.class}) @RequestBody AcodeDto acodeDto) {
|
Result result=new Result();
|
String userId=getUserId(request);
|
String path=null;
|
//个人二维码
|
if(acodeDto.getType()==1){
|
//二维码图名称
|
String imgName="/user_" + userId + "_acode.jpg";
|
UserInfo userInfo = userMapper.selectByPrimaryKey(userId);
|
if(userInfo!=null){
|
|
AtomicInteger atomicInteger=new AtomicInteger(1);
|
while (1==1) {
|
|
if(atomicInteger.get()>10){
|
break;
|
}
|
|
path = wxUtil.generateAcode("poster=" + userInfo.getMobilePhone(), "pages/login/login", imgName, "800px");
|
|
if(StrUtil.isNotBlank(path)){
|
break;
|
}
|
log.debug("小程序二维码格式异常,重新生成:{},重试次数:{}",acodeDto.getUserId(),atomicInteger.get());
|
atomicInteger.getAndIncrement();
|
}
|
|
|
}else{
|
log.warn("用户不存在:{}",userId);
|
}
|
}else {
|
//设置推广员的经纬度
|
AddressDto addressDto=new AddressDto();
|
// addressDto.setLatitude(acodeDto.getLatitude());
|
// addressDto.setLongitude(acodeDto.getLongitude());
|
// addressDto.setTime(System.currentTimeMillis());
|
addressDto.setUserId(acodeDto.getUserId());
|
String imgName="/promoter_" + acodeDto.getUserId() + "_acode.jpg";
|
AtomicInteger atomicInteger=new AtomicInteger(1);
|
while (1==1) {
|
|
if(atomicInteger.get()>10){
|
break;
|
}
|
|
path = wxUtil.generateAcode("scene=" + acodeDto.getUserId(), "pages/login/login", imgName, "430px");
|
|
if(StrUtil.isNotBlank(path)){
|
break;
|
}
|
log.debug("小程序二维码格式异常,重新生成:{},重试次数:{}",acodeDto.getUserId(),atomicInteger.get());
|
atomicInteger.getAndIncrement();
|
}
|
}
|
result.setData(path);
|
return result;
|
}
|
|
|
/**
|
* 获取微信用户openId
|
*/
|
@ApiOperation( value = "获取微信openId")
|
@PostMapping("/login/openid")
|
@PassToken
|
public Result<UserInfoVo> getOpenId(@RequestBody UserReq userReq) {
|
//微信小程序传入的code
|
String code = userReq.getCode();
|
Result<UserInfoVo> result = wxUtil.getOpenId(code);
|
if(result.getCode()==0){
|
UserInfoVo data = result.getData();
|
//会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
|
data.setSessionKey(null);
|
}
|
return result;
|
}
|
|
@ApiOperation( value = "获取微信手机号")
|
@PostMapping("/login/getWxInfo")
|
@PassToken
|
public Result getWxInfo(@RequestBody GetPhoneNumberDto getPhoneNumberDto) {
|
|
Result<UserInfoVo> result = wxUtil.getOpenId(getPhoneNumberDto.getCode());
|
if(result.getCode()==0) {
|
UserInfoVo data = result.getData();
|
String sessionKey = data.getSessionKey();
|
byte[] decode = Base64.decode(sessionKey);
|
byte[] decode1 = Base64.decode(getPhoneNumberDto.getEncryptedData());
|
String s1=null;
|
try {
|
// AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, decode, Base64.decode(getPhoneNumberDto.getIv()));
|
AlgorithmParameterSpec ivSpec = new IvParameterSpec(Base64.decode(getPhoneNumberDto.getIv()));
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
SecretKeySpec keySpec = new SecretKeySpec(decode, "AES");
|
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
s1 =new String(cipher.doFinal(decode1),"UTF-8");
|
// String s1 = aes.decryptStr(decode1);
|
}catch (Exception e){
|
try {
|
AlgorithmParameterSpec ivSpec = new IvParameterSpec(Base64.decode(getPhoneNumberDto.getIv()));
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
|
SecretKeySpec keySpec = new SecretKeySpec(decode, "AES");
|
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
s1 =new String(cipher.doFinal(decode1),"UTF-8");
|
} catch (Exception e1) {
|
|
}
|
}
|
if(s1!=null) {
|
JSONObject jsonObject = JSONUtil.parseObj(s1);
|
String phoneNumber = jsonObject.getStr("phoneNumber");
|
if (StrUtil.isNotBlank(phoneNumber)) {
|
return Result.success(phoneNumber);
|
}
|
}
|
return Result.error(-1,"获取微信手机号失败");
|
}else {
|
return Result.error(-1,result.getMsg());
|
}
|
}
|
|
|
/**
|
* 获取微信用户openId
|
*/
|
@ApiOperation( value = "获取app授权openId")
|
@PostMapping("/login/app/openid")
|
@PassToken
|
public Result getAppOpenId(@RequestBody CommonDto commonDto) {
|
Result result=new Result();
|
String openId = wxUtil.getAppOpenId(commonDto.getExtra());
|
if(openId!=null){
|
result.setData(openId);
|
}else{
|
result.setCode(-1);
|
result.setMsg("获取openId失败");
|
}
|
return result;
|
}
|
|
|
|
}
|