forked from rongchao/epmet-cloud-rizhao
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
415 lines
16 KiB
415 lines
16 KiB
package com.epmet.service.impl;
|
|
|
|
import cn.binarywang.wx.miniapp.api.WxMaService;
|
|
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
|
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
|
|
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.epmet.common.token.constant.LoginConstant;
|
|
import com.epmet.commons.tools.constant.AppClientConstant;
|
|
import com.epmet.commons.tools.exception.EpmetErrorCode;
|
|
import com.epmet.commons.tools.exception.RenException;
|
|
import com.epmet.commons.tools.redis.common.CustomerStaffRedis;
|
|
import com.epmet.commons.tools.security.dto.TokenDto;
|
|
import com.epmet.commons.tools.security.password.PasswordUtils;
|
|
import com.epmet.commons.tools.utils.CpUserDetailRedis;
|
|
import com.epmet.commons.tools.utils.DateUtils;
|
|
import com.epmet.commons.tools.utils.Result;
|
|
import com.epmet.commons.tools.validator.ValidatorUtils;
|
|
import com.epmet.dto.UserDTO;
|
|
import com.epmet.dto.UserWechatDTO;
|
|
import com.epmet.dto.form.*;
|
|
import com.epmet.dto.result.PasswordLoginUserInfoResultDTO;
|
|
import com.epmet.dto.result.UserTokenResultDTO;
|
|
import com.epmet.feign.EpmetUserFeignClient;
|
|
import com.epmet.feign.OperAccessOpenFeignClient;
|
|
import com.epmet.jwt.JwtTokenProperties;
|
|
import com.epmet.jwt.JwtTokenUtils;
|
|
import com.epmet.redis.CustomerAppWxServiceUtil;
|
|
import com.epmet.service.CaptchaService;
|
|
import com.epmet.service.LoginService;
|
|
import com.epmet.utils.WxMaServiceUtils;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import me.chanjar.weixin.common.error.WxErrorException;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* @Description
|
|
* @Author yinzuomei
|
|
* @Date 2020/3/14 20:31
|
|
*/
|
|
@Slf4j
|
|
@Service
|
|
public class LoginServiceImpl implements LoginService {
|
|
private static final Logger logger = LoggerFactory.getLogger(AuthServiceImpl.class);
|
|
|
|
@Autowired
|
|
private EpmetUserFeignClient epmetUserFeignClient;
|
|
|
|
@Autowired
|
|
private WxMaServiceUtils wxMaServiceUtils;
|
|
|
|
@Autowired
|
|
private JwtTokenUtils jwtTokenUtils;
|
|
|
|
@Autowired
|
|
private JwtTokenProperties jwtTokenProperties;
|
|
|
|
@Autowired
|
|
private CpUserDetailRedis cpUserDetailRedis;
|
|
|
|
@Autowired
|
|
private CaptchaService captchaService;
|
|
|
|
@Autowired
|
|
private OperAccessOpenFeignClient operAccessOpenFeignClient;
|
|
|
|
/**
|
|
* 居民端微信小程序登录
|
|
*
|
|
* @param formDTO
|
|
* @return com.epmet.commons.tools.utils.Result<com.epmet.dto.UserTokenResultDTO>
|
|
* @author yinzuomei
|
|
* @since 2020/3/14 19:34
|
|
*/
|
|
@Override
|
|
public Result<UserTokenResultDTO> loginByWxCode(LoginByWxCodeFormDTO formDTO) {
|
|
if(!(LoginConstant.APP_RESI.equals(formDTO.getApp())&&LoginConstant.CLIENT_WXMP.equals(formDTO.getClient()))){
|
|
logger.error("当前接口只适用于居民端微信小程序登录");
|
|
throw new RenException("参数错误");
|
|
}
|
|
//1、根据wxCode获取微信信息
|
|
WxMaJscode2SessionResult wxMaJscode2SessionResult = this.getWxMaUser(formDTO.getApp(),formDTO.getWxCode(),formDTO.getAppId());
|
|
logger.info("openId=[" + wxMaJscode2SessionResult.getOpenid() + "]unionId=[" + wxMaJscode2SessionResult.getUnionid() + "]");
|
|
//2、根据openId查询数据库,没有则直接插入一条记录
|
|
String userId = this.getUserId(formDTO, wxMaJscode2SessionResult);
|
|
if (StringUtils.isNotBlank(userId)) {
|
|
//3、封装token且存到redis
|
|
String token=this.generateToken(formDTO,userId);
|
|
this.saveTokenDto(formDTO,userId,wxMaJscode2SessionResult,token);
|
|
UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO();
|
|
userTokenResultDTO.setToken(token);
|
|
return new Result<UserTokenResultDTO>().ok(userTokenResultDTO);
|
|
}else{
|
|
logger.error("登录失败userId为空");
|
|
throw new RenException("登录失败");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 解析微信code获取小程序用户信息
|
|
*
|
|
* @param app
|
|
* @param wxCode
|
|
* @return cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult
|
|
* @author yinzuomei
|
|
* @date 2020/3/14 20:16
|
|
*/
|
|
@Override
|
|
public WxMaJscode2SessionResult getWxMaUser(String app,String wxCode,String appId) {
|
|
WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
|
|
try {
|
|
if (StringUtils.isNotBlank(appId)){
|
|
WxMaService wxMaService = CustomerAppWxServiceUtil.getWxMaService(appId);
|
|
if (wxMaService == null){
|
|
throw new RenException("解析微信用户信息失败");
|
|
}
|
|
wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(wxCode);
|
|
}else{
|
|
if (LoginConstant.APP_GOV.equals(app)) {
|
|
wxMaJscode2SessionResult = wxMaServiceUtils.govWxMaService().jsCode2SessionInfo(wxCode);
|
|
} else if (LoginConstant.APP_OPER.equals(app)) {
|
|
wxMaJscode2SessionResult = wxMaServiceUtils.operWxMaService().jsCode2SessionInfo(wxCode);
|
|
} else if (LoginConstant.APP_RESI.equals(app)) {
|
|
wxMaJscode2SessionResult = wxMaServiceUtils.resiWxMaService().jsCode2SessionInfo(wxCode);
|
|
}
|
|
}
|
|
} catch (WxErrorException e) {
|
|
log.warn("->[getMaOpenId]::error[{}]", "解析微信code失败",e);
|
|
}
|
|
if (null == wxMaJscode2SessionResult) {
|
|
log.warn(String.format("解析微信用户信息失败,app[%s],wxCode[%s],result:[%S]",app,wxCode, JSON.toJSONString(wxMaJscode2SessionResult)));
|
|
throw new RenException("解析微信用户信息失败");
|
|
} else if (StringUtils.isBlank(wxMaJscode2SessionResult.getOpenid())) {
|
|
log.warn(String.format("获取微信openid失败,app[%s],wxCode[%s]",app,wxCode));
|
|
throw new RenException("获取微信openid失败");
|
|
}
|
|
return wxMaJscode2SessionResult;
|
|
}
|
|
|
|
@Override
|
|
public String getResiWxPhone(ResiWxPhoneFormDTO formDTO) {
|
|
String phone="";
|
|
try {
|
|
ValidatorUtils.validateEntity(formDTO, ResiWxPhoneFormDTO.AddUserInternalGroup.class);
|
|
WxMaService wxMaService = null;
|
|
if (StringUtils.isNotBlank(formDTO.getAppId())){
|
|
wxMaService = CustomerAppWxServiceUtil.getWxMaService(formDTO.getAppId());
|
|
}else{
|
|
wxMaService = wxMaServiceUtils.resiWxMaService();
|
|
}
|
|
WxMaJscode2SessionResult wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(formDTO.getWxCode());
|
|
WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(wxMaJscode2SessionResult.getSessionKey(),
|
|
formDTO.getEncryptedData(),
|
|
formDTO.getIv());
|
|
if (null != phoneNoInfo) {
|
|
phone= phoneNoInfo.getPurePhoneNumber();
|
|
}
|
|
} catch (WxErrorException e) {
|
|
log.error("method exception", e);
|
|
log.error(String.format("获取用户微信绑定的手机号接口异常%s",e.getMessage()));
|
|
} catch(Exception e){
|
|
log.error("method exception", e);
|
|
log.error(String.format("获取用户微信绑定的手机号接口异常%s",e.getMessage()));
|
|
}
|
|
return phone;
|
|
}
|
|
|
|
/**
|
|
* 根据openId查询用户id
|
|
*
|
|
* @param formDTO
|
|
* @param wxMaJscode2SessionResult
|
|
* @return java.lang.String
|
|
* @author yinzuomei
|
|
* @since 2020/3/14 19:34
|
|
*/
|
|
private String getUserId(LoginByWxCodeFormDTO formDTO, WxMaJscode2SessionResult wxMaJscode2SessionResult) {
|
|
WxLoginUserInfoFormDTO wxLoginUserInfoFormDTO = new WxLoginUserInfoFormDTO();
|
|
wxLoginUserInfoFormDTO.setApp(formDTO.getApp());
|
|
wxLoginUserInfoFormDTO.setOpenId(wxMaJscode2SessionResult.getOpenid());
|
|
//1、先根据app、client、openId查询
|
|
Result<UserDTO> userResult = epmetUserFeignClient.selecWxLoginUserInfo(wxLoginUserInfoFormDTO);
|
|
String userId = "";
|
|
if (!userResult.success()) {
|
|
logger.error("根据openId、app获取用户信息失败" + userResult.getMsg());
|
|
throw new RenException("获取用户信息失败" + userResult.getMsg());
|
|
}
|
|
if(null!=userResult.getData()&&StringUtils.isNotBlank(userResult.getData().getId())){
|
|
userId = userResult.getData().getId();
|
|
}
|
|
//2、如果已经存在userId,则更新微信信息
|
|
if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(formDTO.getEncryptedData()) && StringUtils.isNotBlank(formDTO.getIv())) {
|
|
this.updateWxInfO(userId,formDTO,wxMaJscode2SessionResult);
|
|
}
|
|
//3、数据库不存在此用户则创建此用户
|
|
if (StringUtils.isBlank(userId)) {
|
|
userId = createUser(formDTO, wxMaJscode2SessionResult);
|
|
}
|
|
return userId;
|
|
}
|
|
|
|
/**
|
|
* @return com.epmet.commons.tools.utils.Result
|
|
* @param userId
|
|
* @param wxMaJscode2SessionResult
|
|
* @Author yinzuomei
|
|
* @Description 获取用户微信基本信息更新到本地
|
|
* @Date 2020/3/20 19:51
|
|
**/
|
|
private Result updateWxInfO(String userId,
|
|
LoginByWxCodeFormDTO formDTO,
|
|
WxMaJscode2SessionResult wxMaJscode2SessionResult) {
|
|
WxMaUserInfo wxMaUserInfo = wxMaServiceUtils.resiWxMaService().getUserService()
|
|
.getUserInfo(wxMaJscode2SessionResult.getSessionKey(),
|
|
formDTO.getEncryptedData(),
|
|
formDTO.getIv());
|
|
UserWechatDTO userWechatDTO = this.packageCustomerUserDTO(wxMaUserInfo);
|
|
userWechatDTO.setUserId(userId);
|
|
Result<UserDTO> updateUserDtoResult=epmetUserFeignClient.saveOrUpdateUserWechatDTO(userWechatDTO);
|
|
return new Result();
|
|
}
|
|
|
|
/**
|
|
* @param formDTO
|
|
* @param wxMaJscode2SessionResult
|
|
* @return java.lang.String
|
|
* @Author yinzuomei
|
|
* @Description 陌生人首次授权,创建用户信息
|
|
* @Date 2020/3/20 19:42
|
|
**/
|
|
private String createUser(LoginByWxCodeFormDTO formDTO, WxMaJscode2SessionResult wxMaJscode2SessionResult) {
|
|
String userId = "";
|
|
//查询customer_user
|
|
UserWechatDTO userWechatDTO = new UserWechatDTO();
|
|
if (StringUtils.isNotBlank(formDTO.getIv()) && StringUtils.isNotBlank(formDTO.getEncryptedData())) {
|
|
WxMaUserInfo wxMaUserInfo = wxMaServiceUtils.resiWxMaService().getUserService()
|
|
.getUserInfo(wxMaJscode2SessionResult.getSessionKey(),
|
|
formDTO.getEncryptedData(),
|
|
formDTO.getIv());
|
|
userWechatDTO = this.packageCustomerUserDTO(wxMaUserInfo);
|
|
} else {
|
|
userWechatDTO.setWxOpenId(wxMaJscode2SessionResult.getOpenid());
|
|
userWechatDTO.setUnionId(wxMaJscode2SessionResult.getUnionid());
|
|
}
|
|
Result<UserDTO> saveUserWechatResult = epmetUserFeignClient.saveOrUpdateUserWechatDTO(userWechatDTO);
|
|
if (!saveUserWechatResult.success()||null==saveUserWechatResult.getData()) {
|
|
throw new RenException("创建用户失败" + saveUserWechatResult.getMsg());
|
|
}
|
|
userId = saveUserWechatResult.getData().getId();
|
|
return userId;
|
|
}
|
|
|
|
/**
|
|
* @param wxMaUserInfo
|
|
* @return com.epmet.dto.UserWechatDTO
|
|
* @Author yinzuomei
|
|
* @Description 微信信息封装为customer_user记录
|
|
* @Date 2020/3/17 18:22
|
|
**/
|
|
private UserWechatDTO packageCustomerUserDTO(WxMaUserInfo wxMaUserInfo) {
|
|
UserWechatDTO userWechatDTO = new UserWechatDTO();
|
|
userWechatDTO.setCity(wxMaUserInfo.getCity());
|
|
userWechatDTO.setWxOpenId(wxMaUserInfo.getOpenId());
|
|
userWechatDTO.setUnionId(wxMaUserInfo.getUnionId());
|
|
userWechatDTO.setNickname(wxMaUserInfo.getNickName());
|
|
userWechatDTO.setCountry(wxMaUserInfo.getCountry());
|
|
userWechatDTO.setHeadImgUrl(wxMaUserInfo.getAvatarUrl());
|
|
userWechatDTO.setProvince(wxMaUserInfo.getProvince());
|
|
userWechatDTO.setSex(Integer.valueOf(wxMaUserInfo.getGender()));
|
|
return userWechatDTO;
|
|
}
|
|
|
|
|
|
/**
|
|
* 手机号+密码登录接口
|
|
*
|
|
* @param formDTO
|
|
* @return com.epmet.commons.tools.utils.Result<com.epmet.dto.UserTokenResultDTO>
|
|
* @author yinzuomei
|
|
* @since 2020/3/14 19:34
|
|
*/
|
|
@Override
|
|
public Result<UserTokenResultDTO> loginByPassword(LoginByPassWordFormDTO formDTO) {
|
|
if(!(LoginConstant.APP_OPER.equals(formDTO.getApp())&&LoginConstant.CLIENT_WEB.equals(formDTO.getClient()))){
|
|
logger.error("当前接口只适用于运营端管理后台");
|
|
throw new RenException("当前接口只适用于运营端管理后台");
|
|
}
|
|
//1、验证码是否正确
|
|
boolean flag = captchaService.validate(formDTO.getUuid(), formDTO.getCaptcha());
|
|
if (!flag) {
|
|
logger.warn(String.format("用户%s登录,验证码输入错误", formDTO.getPhone()));
|
|
//2020-05-21去除验证码校验
|
|
//return new Result<UserTokenResultDTO>().error(EpmetErrorCode.ERR10019.getCode());
|
|
}
|
|
//2、账号是否存在
|
|
//获取用户信息
|
|
PasswordLoginUserInfoFormDTO passwordLoginUserInfoFormDTO = new PasswordLoginUserInfoFormDTO();
|
|
passwordLoginUserInfoFormDTO.setApp(formDTO.getApp());
|
|
passwordLoginUserInfoFormDTO.setPhone(formDTO.getPhone());
|
|
Result<PasswordLoginUserInfoResultDTO> userInfoResult = epmetUserFeignClient.selectLoginUserInfoByPassword(passwordLoginUserInfoFormDTO);
|
|
if (!userInfoResult.success() || null == userInfoResult.getData()) {
|
|
// logger.error("根据手机号查询运营人员信息失败,返回10003账号不存在");
|
|
throw new RenException(EpmetErrorCode.ERR10003.getCode());
|
|
}
|
|
//3、密码是否正确
|
|
//密码错误
|
|
if (!PasswordUtils.matches(formDTO.getPassword(), userInfoResult.getData().getPassWord())) {
|
|
throw new RenException(EpmetErrorCode.ERR10004.getCode());
|
|
}
|
|
//4、生成token返回,且将TokenDto存到redis
|
|
UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO();
|
|
userTokenResultDTO.setToken(this.packagingUserToken(formDTO, userInfoResult.getData().getUserId()));
|
|
return new Result<UserTokenResultDTO>().ok(userTokenResultDTO);
|
|
}
|
|
|
|
/**
|
|
* 封装用户token值
|
|
*
|
|
* @param formDTO
|
|
* @param userId
|
|
* @return java.lang.String
|
|
* @author yinzuomei
|
|
* @since 2020/3/14 19:34
|
|
*/
|
|
private String packagingUserToken(LoginByPassWordFormDTO formDTO,
|
|
String userId) {
|
|
// 生成token
|
|
Map<String, Object> map = new HashMap<>();
|
|
map.put("app", formDTO.getApp());
|
|
map.put("client", formDTO.getClient());
|
|
map.put("userId", userId);
|
|
String token = jwtTokenUtils.createToken(map);
|
|
logger.info("app:"+formDTO.getApp()+";client:"+formDTO.getClient()+";userId:"+userId+";生成token["+token+"]");
|
|
int expire = jwtTokenProperties.getExpire();
|
|
TokenDto tokenDto = new TokenDto();
|
|
tokenDto.setApp(formDTO.getApp());
|
|
tokenDto.setClient(formDTO.getClient());
|
|
tokenDto.setUserId(userId);
|
|
tokenDto.setToken(token);
|
|
tokenDto.setUpdateTime(System.currentTimeMillis());
|
|
tokenDto.setExpireTime(jwtTokenUtils.getExpiration(token).getTime());
|
|
cpUserDetailRedis.set(tokenDto, expire);
|
|
logger.info("截止时间:"+ DateUtils.format(jwtTokenUtils.getExpiration(token),"yyyy-MM-dd HH:mm:ss"));
|
|
return token;
|
|
}
|
|
|
|
|
|
@Override
|
|
public Result logoutByToken(TokenDto tokenDto) {
|
|
//记录登出日志
|
|
//删除redis
|
|
if (null == tokenDto) {
|
|
logger.error("运营端用户退出系统错误:账号不存在,接口继续执行返回成功");
|
|
return new Result();
|
|
}
|
|
cpUserDetailRedis.logout(tokenDto.getApp(), tokenDto.getClient(), tokenDto.getUserId());
|
|
//web端清空菜单栏和权限
|
|
Result operAccessResult = operAccessOpenFeignClient.clearOperUserAccess();
|
|
if (operAccessResult.success()) {
|
|
logger.info(String.format("运营人员%s退出成功,清空菜单和权限redis成功", tokenDto.getUserId()));
|
|
} else {
|
|
logger.error(String.format("运营人员%s退出成功,清空菜单和权限redis异常", tokenDto.getUserId()));
|
|
}
|
|
//如果是工作端退出,删除当前工作人员缓存
|
|
if(AppClientConstant.APP_GOV.equals(tokenDto.getApp())){
|
|
CustomerStaffRedis.delStaffInfoFormCache(tokenDto.getCustomerId(),tokenDto.getUserId());
|
|
}
|
|
return new Result();
|
|
}
|
|
|
|
/**
|
|
* @Description 生成token
|
|
* @Date 2020/4/18 23:04
|
|
**/
|
|
private String generateToken(LoginCommonFormDTO formDTO,String userId){
|
|
Map<String, Object> map = new HashMap<>();
|
|
map.put("app", formDTO.getApp());
|
|
map.put("client", formDTO.getClient());
|
|
map.put("userId", userId);
|
|
String token = jwtTokenUtils.createToken(map);
|
|
logger.info("app:"+formDTO.getApp()+";client:"+formDTO.getClient()+";userId:"+userId+";生成token["+token+"]");
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* @Description 生成token
|
|
* @Date 2020/4/18 23:04
|
|
**/
|
|
private String saveTokenDto(LoginCommonFormDTO formDTO,
|
|
String userId,
|
|
WxMaJscode2SessionResult wxMaJscode2SessionResult,
|
|
String token) {
|
|
int expire = jwtTokenProperties.getExpire();
|
|
TokenDto tokenDto = new TokenDto();
|
|
tokenDto.setApp(formDTO.getApp());
|
|
tokenDto.setClient(formDTO.getClient());
|
|
tokenDto.setUserId(userId);
|
|
tokenDto.setOpenId(wxMaJscode2SessionResult.getOpenid());
|
|
tokenDto.setSessionKey(wxMaJscode2SessionResult.getSessionKey());
|
|
tokenDto.setUnionId(wxMaJscode2SessionResult.getUnionid());
|
|
tokenDto.setToken(token);
|
|
tokenDto.setUpdateTime(System.currentTimeMillis());
|
|
tokenDto.setExpireTime(jwtTokenUtils.getExpiration(token).getTime());
|
|
cpUserDetailRedis.set(tokenDto, expire);
|
|
logger.info("截止时间:"+ DateUtils.format(jwtTokenUtils.getExpiration(token),"yyyy-MM-dd HH:mm:ss"));
|
|
return token;
|
|
}
|
|
}
|
|
|