package com.epmet.service.impl; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import com.epmet.common.token.constant.LoginConstant; import com.epmet.common.token.dto.TokenDto; import com.epmet.common.token.dto.form.LoginByPassWordFormDTO; import com.epmet.common.token.dto.form.LoginByWxCodeFormDTO; import com.epmet.common.token.dto.result.UserTokenResultDTO; import com.epmet.common.token.util.CpUserDetailRedis; import com.epmet.commons.tools.exception.ErrorCode; import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.security.password.PasswordUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.dto.CustomerUserDTO; import com.epmet.dto.form.PasswordLoginUserInfoFormDTO; import com.epmet.dto.form.WxLoginUserInfoFormDTO; import com.epmet.dto.result.PasswordLoginUserInfoResultDTO; import com.epmet.feign.EpmetUserFeignClient; import com.epmet.jwt.JwtTokenProperties; import com.epmet.jwt.JwtTokenUtils; 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; /** * 微信小程序登录 * * @param formDTO * @return com.epmet.commons.tools.utils.Result * @author yinzuomei * @since 2020/3/14 19:34 */ @Override public Result loginByWxCode(LoginByWxCodeFormDTO formDTO) { //1、根据wxCode获取微信信息 WxMaJscode2SessionResult wxMaJscode2SessionResult = this.getWxMaUser(formDTO); logger.info("openId=[" + wxMaJscode2SessionResult.getOpenid() + "]unionId=[" + wxMaJscode2SessionResult.getUnionid() + "]"); //2、根据openId查询数据库,没有则直接插入一条记录 String userId = this.getUserId(formDTO, wxMaJscode2SessionResult); if (StringUtils.isNotBlank(userId)) { //3、封装token且存到redis UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO(); userTokenResultDTO.setToken(this.packagingUserToken(formDTO, userId, wxMaJscode2SessionResult)); return new Result().ok(userTokenResultDTO); } return new Result().error("登录失败"); } /** * 解析微信code获取小程序用户信息 * * @param formDTO * @return cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult * @author yinzuomei * @date 2020/3/14 20:16 */ private WxMaJscode2SessionResult getWxMaUser(LoginByWxCodeFormDTO formDTO) { WxMaJscode2SessionResult wxMaJscode2SessionResult = null; try { if (LoginConstant.APP_GOV.equals(formDTO.getApp())) { wxMaJscode2SessionResult = wxMaServiceUtils.govWxMaService().jsCode2SessionInfo(formDTO.getWxCode()); } else if (LoginConstant.APP_OPER.equals(formDTO.getApp())) { wxMaJscode2SessionResult = wxMaServiceUtils.operWxMaService().jsCode2SessionInfo(formDTO.getWxCode()); } else if (LoginConstant.APP_RESI.equals(formDTO.getApp())) { wxMaJscode2SessionResult = wxMaServiceUtils.resiWxMaService().jsCode2SessionInfo(formDTO.getWxCode()); } } catch (WxErrorException e) { log.error("->[getMaOpenId]::error[{}]", "解析微信code失败"); } if (null == wxMaJscode2SessionResult) { throw new RenException("解析微信用户信息失败"); } else if (StringUtils.isBlank(wxMaJscode2SessionResult.getOpenid())) { throw new RenException("获取微信openid失败"); } return wxMaJscode2SessionResult; } /** * 根据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()); Result userResult=epmetUserFeignClient.selecWxLoginUserInfo(wxLoginUserInfoFormDTO); String userId=""; if(!userResult.success()){ throw new RenException("获取用户信息失败"+userResult.getMsg()); } userId= (String) userResult.getData(); if (StringUtils.isBlank(userId)&&LoginConstant.APP_GOV.equals(formDTO.getApp())) { //查询customer_staff待完善 } else if (StringUtils.isBlank(userId)&&LoginConstant.APP_OPER.equals(formDTO.getApp())) { //查询oper_user待完善 } else if (StringUtils.isBlank(userId)&&LoginConstant.APP_RESI.equals(formDTO.getApp())) { //查询customer_user WxMaUserInfo wxMaUserInfo = wxMaServiceUtils.resiWxMaService().getUserService() .getUserInfo(wxMaJscode2SessionResult.getSessionKey(), formDTO.getEncryptedData(), formDTO.getIv()); CustomerUserDTO customerUserDTO=this.packageCustomerUserDTO(wxMaUserInfo); Result saveCustomerUserResult=epmetUserFeignClient.saveCustomerUser(customerUserDTO); if(!saveCustomerUserResult.success()){ throw new RenException("创建用户失败"+userResult.getMsg()); } userId = saveCustomerUserResult.getData(); } return userId; } /** * @param wxMaUserInfo * @return com.epmet.dto.CustomerUserDTO * @Author yinzuomei * @Description 微信信息封装为customer_user记录 * @Date 2020/3/17 18:22 **/ private CustomerUserDTO packageCustomerUserDTO(WxMaUserInfo wxMaUserInfo) { CustomerUserDTO customerUserDTO = new CustomerUserDTO(); customerUserDTO.setCity(wxMaUserInfo.getCity()); customerUserDTO.setWxOpenId(wxMaUserInfo.getOpenId()); customerUserDTO.setNickname(wxMaUserInfo.getNickName()); customerUserDTO.setCountry(wxMaUserInfo.getCountry()); customerUserDTO.setHeadImgUrl(wxMaUserInfo.getAvatarUrl()); customerUserDTO.setCountry(wxMaUserInfo.getCountry()); customerUserDTO.setProvince(wxMaUserInfo.getProvince()); customerUserDTO.setSex(Integer.valueOf(wxMaUserInfo.getGender())); return customerUserDTO; } /** * 封装用户token值 * * @param formDTO * @param userId * @param wxMaJscode2SessionResult * @return java.lang.String * @author yinzuomei * @since 2020/3/14 19:34 */ private String packagingUserToken(LoginByWxCodeFormDTO formDTO, String userId, WxMaJscode2SessionResult wxMaJscode2SessionResult) { // 生成token Map 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.setOpenId(wxMaJscode2SessionResult.getOpenid()); tokenDto.setSessionKey(wxMaJscode2SessionResult.getSessionKey()); tokenDto.setUnionId(wxMaJscode2SessionResult.getUnionid()); cpUserDetailRedis.set(token,tokenDto, expire); return token; } /** * 手机号+密码登录接口 * * @param formDTO * @return com.epmet.commons.tools.utils.Result * @author yinzuomei * @since 2020/3/14 19:34 */ @Override public Result loginByPassword(LoginByPassWordFormDTO formDTO) { //1、验证码是否正确 boolean flag = captchaService.validate(formDTO.getUuid(), formDTO.getCaptcha()); if(!flag){ return new Result().error(ErrorCode.CAPTCHA_ERROR); } //2、账号是否存在 //获取用户信息 PasswordLoginUserInfoFormDTO passwordLoginUserInfoFormDTO=new PasswordLoginUserInfoFormDTO(); passwordLoginUserInfoFormDTO.setApp(formDTO.getApp()); passwordLoginUserInfoFormDTO.setPhone(formDTO.getPhone()); Result userInfoResult=epmetUserFeignClient.selectLoginUserInfoByPassword(passwordLoginUserInfoFormDTO); logger.info(userInfoResult.getCode()+userInfoResult.getMsg()); if(!userInfoResult.success()||null==userInfoResult.getData()){ return new Result().error("账号不存在"); } //3、密码是否正确 //密码错误 if(!PasswordUtils.matches(formDTO.getPassword(),userInfoResult.getData().getPassWord())){ throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); } //4、生成token返回,且将TokenDto存到redis UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO(); userTokenResultDTO.setToken(this.packagingUserToken(formDTO, userInfoResult.getData().getUserId())); return new Result().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 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); cpUserDetailRedis.set(token,tokenDto, expire); return token; } }