package com.epmet.service.impl; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.aliyun.dingtalk.module.DingTalkResult; import com.epmet.auth.constants.AuthOperationConstants; import com.epmet.common.token.constant.LoginConstant; import com.epmet.commons.rocketmq.messages.LoginMQMsg; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.ServiceConstant; import com.epmet.commons.tools.enums.DingMiniAppEnum; import com.epmet.commons.tools.enums.EnvEnum; import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetException; import com.epmet.commons.tools.exception.ExceptionUtils; import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.feign.ResultDataResolver; import com.epmet.commons.tools.security.dto.GovTokenDto; import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.commons.tools.security.password.PasswordUtils; import com.epmet.commons.tools.security.user.LoginUserUtil; import com.epmet.commons.tools.utils.*; import com.epmet.commons.tools.validator.PhoneValidatorUtils; import com.epmet.constant.AuthHttpUrlConstant; import com.epmet.constant.SmsTemplateConstant; import com.epmet.dto.*; import com.epmet.dto.form.*; import com.epmet.dto.result.*; import com.epmet.feign.EpmetMessageOpenFeignClient; import com.epmet.feign.EpmetUserOpenFeignClient; import com.epmet.feign.GovOrgOpenFeignClient; import com.epmet.jwt.JwtTokenProperties; import com.epmet.jwt.JwtTokenUtils; import com.epmet.redis.CaptchaRedis; import com.epmet.service.ThirdLoginService; import com.taobao.api.ApiException; import com.taobao.dingtalk.client.DingTalkClientToken; import com.taobao.dingtalk.client.DingTalkClientUser; import com.taobao.dingtalk.vo.result.AccessTokenResult; import com.taobao.dingtalk.vo.result.UserBaseInfo; import lombok.extern.slf4j.Slf4j; 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 org.springframework.util.CollectionUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; /** * @author sun * @Description 第三方-居民端、政府端登陆服务 */ @Slf4j @Service public class ThirdLoginServiceImpl implements ThirdLoginService, ResultDataResolver { private static final Logger logger = LoggerFactory.getLogger(ThirdLoginServiceImpl.class); @Autowired private JwtTokenUtils jwtTokenUtils; @Autowired private CaptchaRedis captchaRedis; @Autowired private JwtTokenProperties jwtTokenProperties; @Autowired private CpUserDetailRedis cpUserDetailRedis; @Autowired private EpmetUserOpenFeignClient epmetUserOpenFeignClient; @Autowired private GovOrgOpenFeignClient govOrgOpenFeignClient; @Autowired private EpmetMessageOpenFeignClient epmetMessageOpenFeignClient; @Autowired private EpmetMessageOpenFeignClient messageOpenFeignClient; @Autowired private LoginUserUtil loginUserUtil; @Autowired private DingTalkClientToken dingTalkClientToken; @Autowired private DingTalkClientUser dingTalkClientUser; /** * @param formDTO * @return * @Author sun * @Description 单客户-居民端微信小程序登录 **/ @Override public UserTokenResultDTO resiLogin(LoginFormDTO formDTO) { //1.调用epmet_third服务,校验appId是否有效以及是否授权,校验通过的调用微信API获取用户基本信息 WxLoginFormDTO resiLoginFormDTO = new WxLoginFormDTO(); resiLoginFormDTO.setAppId(formDTO.getAppId()); resiLoginFormDTO.setWxCode(formDTO.getWxCode()); UserWechatDTO userWechatDTO = this.getUserWeChat(resiLoginFormDTO); //2.调用epmet-user服务,新增用户信息(先判断用户是否存在,不存在则新增存在则更新) WxUserFormDTO wxUserFormDTO = new WxUserFormDTO(); wxUserFormDTO.setWechatDTO(userWechatDTO); wxUserFormDTO.setApp(formDTO.getApp()); Result userResult = epmetUserOpenFeignClient.saveWxUser(wxUserFormDTO); if (!userResult.success()) { throw new RenException(userResult.getCode()); } UserDTO userDTO = userResult.getData(); //3.生成业务token String userId = userDTO.getId(); String token = this.generateToken(formDTO, userId); //4.存放Redis this.saveTokenDto(formDTO, userId, userWechatDTO, token, userWechatDTO.getCustomerId()); //5.接口返参 UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO(); userTokenResultDTO.setToken(token); return userTokenResultDTO; } /** * @Description 居民端登陆生成业务token的key **/ private String generateToken(LoginCommonFormDTO formDTO, String userId) { 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 + "]"); return token; } /** * @Description 将token存入redis **/ private String saveTokenDto(LoginCommonFormDTO formDTO, String userId, UserWechatDTO userWechatDTO, String token, String customerId) { int expire = jwtTokenProperties.getExpire(); TokenDto tokenDto = new TokenDto(); tokenDto.setCustomerId(customerId); tokenDto.setApp(formDTO.getApp()); tokenDto.setClient(formDTO.getClient()); tokenDto.setUserId(userId); tokenDto.setOpenId(userWechatDTO.getWxOpenId()); tokenDto.setSessionKey(userWechatDTO.getSessionKey()); tokenDto.setUnionId(userWechatDTO.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; } /** * @param formDTO * @return * @Author sun * @Description 单客户-政府端微信小程序登录 **/ @Override public UserTokenResultDTO workLogin(LoginFormDTO formDTO) { //1.调用epmet_third服务,校验appId是否有效以及是否授权,校验通过的调用微信API获取用户基本信息 WxLoginFormDTO resiLoginFormDTO = new WxLoginFormDTO(); resiLoginFormDTO.setAppId(formDTO.getAppId()); resiLoginFormDTO.setWxCode(formDTO.getWxCode()); UserWechatDTO userWechatDTO = this.getUserWeChat(resiLoginFormDTO); //2.根据openid查询用户是否存在历史登陆信息 Result latestStaffWechat = epmetUserOpenFeignClient.getLatestStaffWechatLoginRecord(userWechatDTO.getWxOpenId()); if (!latestStaffWechat.success() || null == latestStaffWechat.getData()) { logger.warn(String.format("没有获取到用户最近一次登录账户信息,code[%s],msg[%s]", EpmetErrorCode.PLEASE_LOGIN.getCode(), EpmetErrorCode.PLEASE_LOGIN.getMsg())); throw new RenException(EpmetErrorCode.PLEASE_LOGIN.getCode()); } StaffLatestAgencyResultDTO staffLatestAgencyResultDTO = latestStaffWechat.getData(); //3.记录staff_wechat this.savestaffwechat(staffLatestAgencyResultDTO.getStaffId(), userWechatDTO.getWxOpenId(), staffLatestAgencyResultDTO.getCustomerId()); //4.记录登录日志 this.saveStaffLoginRecord(staffLatestAgencyResultDTO); //5.获取用户token String token = this.generateGovWxmpToken(staffLatestAgencyResultDTO.getStaffId()); //6.保存到redis this.saveLatestGovTokenDto(staffLatestAgencyResultDTO, userWechatDTO, token); UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO(); userTokenResultDTO.setToken(token); //7.发送登录事件 try { sendLoginEvent(staffLatestAgencyResultDTO.getStaffId(), formDTO.getAppId(), AppClientConstant.APP_GOV, AppClientConstant.CLIENT_WXMP); } catch (RenException e) { log.error(e.getInternalMsg()); } catch (Exception e) { log.error("【工作端workLogin登录】发送登录事件失败,程序继续执行。"); } return userTokenResultDTO; } /** * @param userId openid * @return * @Author sun * @Description 保存微信和当前登录用户关系 **/ private Result savestaffwechat(String userId, String openid, String customerId) { StaffWechatFormDTO staffWechatFormDTO = new StaffWechatFormDTO(); staffWechatFormDTO.setUserId(userId); staffWechatFormDTO.setWxOpenId(openid); staffWechatFormDTO.setCustomerId(customerId); return epmetUserOpenFeignClient.saveStaffWechat(staffWechatFormDTO); } /** * @param latestStaffWechatLoginDTO * @return * @Author sun * @Description 保存登录日志 **/ private Result saveStaffLoginRecord(StaffLatestAgencyResultDTO latestStaffWechatLoginDTO) { StaffLoginAgencyRecordFormDTO staffLoginAgencyRecordFormDTO = new StaffLoginAgencyRecordFormDTO(); staffLoginAgencyRecordFormDTO.setCustomerId(latestStaffWechatLoginDTO.getCustomerId()); staffLoginAgencyRecordFormDTO.setStaffId(latestStaffWechatLoginDTO.getStaffId()); staffLoginAgencyRecordFormDTO.setWxOpenId(latestStaffWechatLoginDTO.getWxOpenId()); staffLoginAgencyRecordFormDTO.setMobile(latestStaffWechatLoginDTO.getMobile()); staffLoginAgencyRecordFormDTO.setAgencyId(latestStaffWechatLoginDTO.getAgencyId()); Result staffLoginRecordResult = epmetUserOpenFeignClient.saveStaffLoginRecord(staffLoginAgencyRecordFormDTO); return staffLoginRecordResult; } /** * @Description 生成政府端小程序业务token Key * @Author sun **/ private String generateGovWxmpToken(String staffId) { Map map = new HashMap<>(); map.put("app", LoginConstant.APP_GOV); map.put("client", LoginConstant.CLIENT_WXMP); map.put("userId", staffId); String token = jwtTokenUtils.createToken(map); logger.info("app:" + LoginConstant.APP_GOV + ";client:" + LoginConstant.CLIENT_WXMP + ";userId:" + staffId + ";生成token[" + token + "]"); return token; } /** * @Description 保存tokenDto到redis * @Author sun **/ private void saveLatestGovTokenDto(StaffLatestAgencyResultDTO staffLatestAgency, UserWechatDTO userWechatDTO, String token) { int expire = jwtTokenProperties.getExpire(); GovTokenDto govTokenDto = new GovTokenDto(); govTokenDto.setApp(LoginConstant.APP_GOV); govTokenDto.setClient(LoginConstant.CLIENT_WXMP); govTokenDto.setUserId(staffLatestAgency.getStaffId()); govTokenDto.setOpenId(userWechatDTO.getWxOpenId()); govTokenDto.setSessionKey(userWechatDTO.getSessionKey()); govTokenDto.setUnionId(userWechatDTO.getUnionId()); govTokenDto.setToken(token); govTokenDto.setUpdateTime(System.currentTimeMillis()); govTokenDto.setExpireTime(jwtTokenUtils.getExpiration(token).getTime()); govTokenDto.setRootAgencyId(staffLatestAgency.getAgencyId()); govTokenDto.setCustomerId(staffLatestAgency.getCustomerId()); //设置部门,网格,角色列表 govTokenDto.setDeptIdList(getDeptartmentIdList(staffLatestAgency.getStaffId())); govTokenDto.setGridIdList(getGridIdList(staffLatestAgency.getStaffId())); CustomerAgencyDTO agency = getAgencyByStaffId(staffLatestAgency.getStaffId()); if (agency != null) { govTokenDto.setAgencyId(agency.getId()); govTokenDto.setRoleList(queryGovStaffRoles(staffLatestAgency.getStaffId(), agency.getId())); } govTokenDto.setOrgIdPath(getOrgIdPath(staffLatestAgency.getStaffId())); cpUserDetailRedis.set(govTokenDto, expire); logger.info("截止时间:" + DateUtils.format(jwtTokenUtils.getExpiration(token), "yyyy-MM-dd HH:mm:ss")); } public Set getDeptartmentIdList(String staffId) { try { Result> deptListResult = govOrgOpenFeignClient.getDepartmentListByStaffId(staffId); if (deptListResult.success()) { if (!CollectionUtils.isEmpty(deptListResult.getData())) { Set deptIdLists = deptListResult.getData().stream().map(dept -> dept.getDepartmentId()).collect(Collectors.toSet()); return deptIdLists; } } else { logger.error("登录:查询部门列表,远程调用返回错误:{}", deptListResult.getMsg()); } } catch (Exception e) { String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); logger.error("登录:查询部门列表异常:{}", errorStackTrace); } return new HashSet<>(); } /** * 根据工作人员ID查询网格ID列表 * * @param staffId * @return */ public Set getGridIdList(String staffId) { Result> result = govOrgOpenFeignClient.listGridsbystaffid(staffId); if (!result.success()) { logger.error("登录:查询网格列表,远程调用返回错误:{}", result.getMsg()); return null; } else { List grids = result.getData(); return grids.stream().map(grid -> grid.getGridId()).collect(Collectors.toSet()); } } /** * 根据staffId查询所属的组织机构 * * @param staffId */ public CustomerAgencyDTO getAgencyByStaffId(String staffId) { Result result = govOrgOpenFeignClient.getAgencyByStaff(staffId); if (!result.success()) { logger.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg()); return null; } return result.getData(); } /** * 查询人员在某机关单位下的角色列表 * * @param staffId orgId */ public List queryGovStaffRoles(String staffId, String orgId) { StaffRoleFormDTO formDTO = new StaffRoleFormDTO(); formDTO.setStaffId(staffId); formDTO.setOrgId(orgId); Result> gridResult = epmetUserOpenFeignClient.getRolesOfStaff(formDTO); if (!CollectionUtils.isEmpty(gridResult.getData())) { //return gridResult.getData().stream().map(role -> role.getId()).collect(Collectors.toSet()); return ConvertUtils.sourceToTarget(gridResult.getData(), GovTokenDto.Role.class); } return null; } /** * 查询工作人员的OrgIdPath * * @param staffId * @return */ public String getOrgIdPath(String staffId) { Result result = govOrgOpenFeignClient.getAgencyByStaff(staffId); if (!result.success()) { logger.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg()); return null; } CustomerAgencyDTO agency = result.getData(); if (agency != null) { if ("0".equals(agency.getPid())) { // 顶级 return agency.getId(); } else { return agency.getPids().concat(":").concat(agency.getId()); } } return null; } /** * @param formDTO * @return * @Author sun * @Description 单客户-选择组织,进入首页 **/ @Override public UserTokenResultDTO enterOrg(ThirdWxmpEnteOrgFormDTO formDTO) { //1、需要校验要登录的客户,是否被禁用 CustomerStaffFormDTO customerStaffFormDTO = new CustomerStaffFormDTO(); customerStaffFormDTO.setCustomerId(formDTO.getCustomerId()); customerStaffFormDTO.setMobile(formDTO.getMobile()); Result customerStaffDTOResult = epmetUserOpenFeignClient.getCustomerStaffInfo(customerStaffFormDTO); if (!customerStaffDTOResult.success() || null == customerStaffDTOResult.getData()) { logger.error(String.format("获取工作人员信息失败,手机号[%s],客户id:[%s],code[%s],msg[%s]", formDTO.getMobile(), formDTO.getCustomerId(), customerStaffDTOResult.getCode(), customerStaffDTOResult.getMsg())); throw new RenException(customerStaffDTOResult.getCode()); } CustomerStaffDTO customerStaff = customerStaffDTOResult.getData(); //2020.7.24 获取微信信息接口调整,改调用微信api的方式 sun start //2.调用epmet_third服务,校验appId是否有效以及是否授权,校验通过的调用微信API获取用户基本信息 WxLoginFormDTO resiLoginFormDTO = new WxLoginFormDTO(); resiLoginFormDTO.setAppId(formDTO.getAppId()); resiLoginFormDTO.setWxCode(formDTO.getWxCode()); UserWechatDTO userWechatDTO = this.getUserWeChat(resiLoginFormDTO); WxMaJscode2SessionResult wxMaJscode2SessionResult = new WxMaJscode2SessionResult(); wxMaJscode2SessionResult.setOpenid(userWechatDTO.getWxOpenId()); wxMaJscode2SessionResult.setSessionKey(userWechatDTO.getSessionKey()); wxMaJscode2SessionResult.setUnionid(""); // end //3、记录staff_wechat,并记录用户激活状态,激活时间 this.savestaffwechat(customerStaff.getUserId(), userWechatDTO.getWxOpenId(), formDTO.getCustomerId()); //4、记录登录日志 StaffLatestAgencyResultDTO staffLatestAgencyResultDTO = new StaffLatestAgencyResultDTO(); staffLatestAgencyResultDTO.setCustomerId(formDTO.getCustomerId()); staffLatestAgencyResultDTO.setStaffId(customerStaff.getUserId()); staffLatestAgencyResultDTO.setWxOpenId(userWechatDTO.getWxOpenId()); staffLatestAgencyResultDTO.setMobile(formDTO.getMobile()); staffLatestAgencyResultDTO.setAgencyId(formDTO.getRootAgencyId()); this.saveStaffLoginRecord(staffLatestAgencyResultDTO); //5.1、获取用户token String token = this.generateGovWxmpToken(customerStaff.getUserId()); //5.2、保存到redis StaffLatestAgencyResultDTO staffLatestAgency = new StaffLatestAgencyResultDTO(); staffLatestAgency.setAgencyId(formDTO.getRootAgencyId()); staffLatestAgency.setCustomerId(formDTO.getCustomerId()); staffLatestAgency.setStaffId(customerStaff.getUserId()); this.saveLatestGovTokenDto(staffLatestAgency, userWechatDTO, token); UserTokenResultDTO userTokenResultDTO = new UserTokenResultDTO(); userTokenResultDTO.setToken(token); //6.发送登录事件 try { sendLoginEvent(customerStaff.getUserId(), formDTO.getAppId(), AppClientConstant.APP_GOV, AppClientConstant.CLIENT_WXMP); } catch (RenException e) { log.error(e.getInternalMsg()); } catch (Exception e) { log.error("【工作端enterOrg登录】发送登录事件失败,程序继续执行。错误信息"); } return userTokenResultDTO; } /** * @param formDTO * @return * @Author sun * @Description 单客户-手机验证码获取组织 **/ @Override public List getMyOrg(ThirdStaffOrgsFormDTO formDTO) { //0、验证码是否正确 String rightSmsCode = captchaRedis.getSmsCode(formDTO.getMobile()); if (!formDTO.getSmsCode().equals(rightSmsCode)) { logger.warn(String.format("验证码错误code[%s],msg[%s]",EpmetErrorCode.MOBILE_CODE_ERROR.getCode(),EpmetErrorCode.MOBILE_CODE_ERROR.getMsg())); throw new RenException(EpmetErrorCode.MOBILE_CODE_ERROR.getCode()); } //1.根据appId查询对应客户Id PaCustomerDTO customer = this.getCustomerInfo(formDTO.getAppId()); //7.28 根据appId只能存在一个客户Id,后边的批量操作逻辑 //2.根据手机号查询到用户信息 ThirdCustomerStaffFormDTO dto = new ThirdCustomerStaffFormDTO(); dto.setCustomerId(customer.getId()); dto.setMobile(formDTO.getMobile()); Result> customerStaffResult = epmetUserOpenFeignClient.getCustsomerStaffByIdAndPhone(dto); if (!customerStaffResult.success()) { logger.error(String.format("手机验证码登录异常,手机号[%s],code[%s],msg[%s]", formDTO.getMobile(), customerStaffResult.getCode(), customerStaffResult.getMsg())); throw new RenException(customerStaffResult.getCode()); } //3、查询用户所有的组织信息 List customerIdList = new ArrayList<>(); for (CustomerStaffDTO customerStaffDTO : customerStaffResult.getData()) { customerIdList.add(customerStaffDTO.getCustomerId()); } StaffOrgFormDTO staffOrgFormDTO = new StaffOrgFormDTO(); staffOrgFormDTO.setCustomerIdList(customerIdList); Result> result = govOrgOpenFeignClient.getStaffOrgList(staffOrgFormDTO); if(result.success()&&null!=result.getData()){ return result.getData(); } logger.error(String .format("手机验证码获取组织,调用%s服务失败,入参手机号%s,验证码%s,返回错误码%s,错误提示信息%s", ServiceConstant.GOV_ORG_SERVER,formDTO.getMobile(),formDTO.getSmsCode(),result.getCode(),result.getMsg())); return new ArrayList<>(); } /** * @param formDTO * @return * @author sun * @description 单客户-手机号密码获取组织 **/ @Override public List getMyOrgByPassword(ThirdStaffOrgsFormDTO formDTO) { //0.根据appId查询对应客户Id // Result resultDTO = epmetThirdFeignClient.getCustomerMsg(formDTO.getAppId()); PaCustomerDTO customer = this.getCustomerInfo(formDTO.getAppId()); //7.28 上边根据appId只能锁定一条客户id,后边的批量循环操作暂不做调整,还是使用之前的代码 sun //1、根据手机号查询到用户信息 ThirdCustomerStaffFormDTO dto = new ThirdCustomerStaffFormDTO(); dto.setCustomerId(customer.getId()); dto.setMobile(formDTO.getMobile()); Result> customerStaffResult = epmetUserOpenFeignClient.getCustsomerStaffByIdAndPhone(dto); if (!customerStaffResult.success()) { logger.warn(String.format("手机密码登录异常,手机号[%s],code[%s],msg[%s]", formDTO.getMobile(), customerStaffResult.getCode(), customerStaffResult.getMsg())); throw new RenException(customerStaffResult.getCode()); } //2、密码是否正确 List customerStaffList=customerStaffResult.getData(); //3、查询用户所有的组织信息 List customerIdList = new ArrayList<>(); //是否设置过密码 boolean havePasswordFlag=false; //密码是否正确 boolean passwordRightFlag=false; for (CustomerStaffDTO customerStaffDTO : customerStaffList) { if(StringUtils.isNotBlank(customerStaffDTO.getPassword())){ havePasswordFlag=true; }else{ logger.warn(String.format("当前用户:手机号%s,客户Id%s下未设置密码.",formDTO.getMobile(),customerStaffDTO.getCustomerId())); continue; } if (!PasswordUtils.matches(formDTO.getPassword(), customerStaffDTO.getPassword())) { logger.warn(String.format("当前用户:手机号%s,客户Id%s密码匹配错误.",formDTO.getMobile(),customerStaffDTO.getCustomerId())); }else{ logger.warn(String.format("当前用户:手机号%s,客户Id%s密码匹配正确.",formDTO.getMobile(),customerStaffDTO.getCustomerId())); passwordRightFlag=true; customerIdList.add(customerStaffDTO.getCustomerId()); } } //根据手机号查出来所有用户,密码都为空,表明用户未激活账户,未设置密码 if(!havePasswordFlag){ logger.warn(String.format("当前手机号(%s)下所有账户都未设置密码,请先使用验证码登录激活账户",formDTO.getMobile())); throw new RenException(EpmetErrorCode.PASSWORD_ERROR.getCode()); } //密码错误 if(!passwordRightFlag){ logger.warn(String.format("根据当前手机号(%s)密码未找到所属组织,密码错误",formDTO.getMobile())); throw new RenException(EpmetErrorCode.PASSWORD_ERROR.getCode()); } StaffOrgFormDTO staffOrgFormDTO = new StaffOrgFormDTO(); staffOrgFormDTO.setCustomerIdList(customerIdList); Result> result = govOrgOpenFeignClient.getStaffOrgList(staffOrgFormDTO); if(result.success()&&null!=result.getData()){ return result.getData(); } logger.warn(String .format("手机验证码获取组织,调用%s服务失败,入参手机号%s,密码%s,返回错误码%s,错误提示信息%s", ServiceConstant.GOV_ORG_SERVER, formDTO.getMobile(), formDTO.getPassword(), result.getCode(), result.getMsg())); return new ArrayList<>(); } /** * @Description 获取客户信息 * @param appId * @author zxc */ public PaCustomerDTO getCustomerInfo(String appId){ JSONObject jsonObject = new JSONObject(); String data = HttpClientManager.getInstance().sendPostByJSON(AuthHttpUrlConstant.CUSTOMER_MSG_URL + appId, JSON.toJSONString(jsonObject)).getData(); logger.info("ThirdLoginServiceImpl.getCustomerInfo:httpclient->url:"+AuthHttpUrlConstant.CUSTOMER_MSG_URL+",结果->"+data); JSONObject toResult = JSON.parseObject(data); Result mapToResult = ConvertUtils.mapToEntity(toResult, Result.class); if (null != toResult.get("code")) { mapToResult.setCode(((Integer) toResult.get("code")).intValue()); } if (!mapToResult.success()) { logger.error(String.format("根据appId查询客户Id失败,对应appId->" + appId)); throw new RenException(mapToResult.getMsg()); } Object PublicCustomerResultDTO = mapToResult.getData(); JSONObject json = JSON.parseObject(PublicCustomerResultDTO.toString()); Map map = (Map)json.get("customer"); PaCustomerDTO customer = ConvertUtils.mapToEntity(map, PaCustomerDTO.class); logger.info("小程序登陆third服务获取客户用户信息PaCustomerDTO->"+customer); return customer; } /** * @Description 获取UserWechatDTO * @param resiLoginFormDTO * @author zxc */ public UserWechatDTO getUserWeChat(WxLoginFormDTO resiLoginFormDTO){ String data = HttpClientManager.getInstance().sendPostByJSON(AuthHttpUrlConstant.RESI_AND_WORK_LOGIN_URL, JSON.toJSONString(resiLoginFormDTO)).getData(); logger.info("ThirdLoginServiceImpl.getUserWeChat:httpclient->url:"+AuthHttpUrlConstant.RESI_AND_WORK_LOGIN_URL+",结果->"+data); JSONObject toResult = JSON.parseObject(data); Result mapToResult = ConvertUtils.mapToEntity(toResult, Result.class); if (null != toResult.get("code")) { mapToResult.setCode(((Integer) toResult.get("code")).intValue()); } if (!mapToResult.success()) { logger.error("居民端小程序登陆,调用epmet_third服务获取数据失败"); throw new RenException(mapToResult.getCode()); } Object UserWeChatDTO = mapToResult.getData(); JSONObject json = JSON.parseObject(UserWeChatDTO.toString()); UserWechatDTO userWechatDTO = ConvertUtils.mapToEntity(json, UserWechatDTO.class); logger.info("小程序登陆third服务获取微信用户信息userWechatDTO->"+userWechatDTO); return userWechatDTO; } /** * @param formDTO * @return * @author sun * @description 单客户-获取微信用户手机号 * 【此接口只适配第三方客户,对于党群e事通客户还是走原接口】 **/ @Override public String getResiWxPhone(GetResiWxPhoneFormDTO formDTO) { String phone = ""; try { //1.根据wxcode获取sessionKey WxLoginFormDTO resiLoginFormDTO = new WxLoginFormDTO(); resiLoginFormDTO.setAppId(formDTO.getAppId()); resiLoginFormDTO.setWxCode(formDTO.getWxCode()); //此方法会校验appId是否授权,然后在判断客户是否存在,之后才是获取sessionKey,如果只想获取sessionKey需要写新接口 UserWechatDTO userWechatDTO = this.getUserWeChat(resiLoginFormDTO); if (null == userWechatDTO || null == userWechatDTO.getSessionKey()) { logger.error(String.format("调用生成third服务wxcode获取sessionKey失败,对应appId->" + formDTO.getAppId())); throw new RenException("获取本机号码失败"); } //2.使用sessionKey解密获取手机号 WxMaPhoneNumberInfo phoneNoInfo = WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(userWechatDTO.getSessionKey(), formDTO.getEncryptedData(), formDTO.getIv())); if (null != phoneNoInfo) { phone = phoneNoInfo.getPurePhoneNumber(); } } catch (Exception e) { log.error("method exception", e); log.error(String.format("获取用户微信绑定的手机号接口异常%s", e.getMessage())); } return phone; } /** * @param formDTO * @author sun * @description 单客户-工作端微信小程序登录-发送验证码 **/ @Override public void sendSmsCode(ThirdSendSmsCodeFormDTO formDTO) { String str = "发送短信验证码异常,手机号[%s],code[%s],msg[%s]"; //1.校验手机号是否符合规范 if (!PhoneValidatorUtils.isMobile(formDTO.getMobile())) { logger.warn(String.format(str, formDTO.getMobile(), EpmetErrorCode.ERROR_PHONE.getCode(), EpmetErrorCode.ERROR_PHONE.getMsg())); throw new RenException(EpmetErrorCode.ERROR_PHONE.getCode()); } //2.根据手机号校验用户是否存在 //2-1.根据appId查询对应客户Id PaCustomerDTO customer = this.getCustomerInfo(formDTO.getAppId()); //2-2.根据手机号查询到用户信息 ThirdCustomerStaffFormDTO dto = new ThirdCustomerStaffFormDTO(); dto.setCustomerId(customer.getId()); dto.setMobile(formDTO.getMobile()); Result> customerStaffResult = epmetUserOpenFeignClient.getCustsomerStaffByIdAndPhone(dto); if (!customerStaffResult.success()) { logger.warn(String.format(str, formDTO.getMobile(), customerStaffResult.getCode(), customerStaffResult.getMsg())); throw new RenException(customerStaffResult.getCode()); } //3.发送短信验证码 SendVerificationCodeFormDTO sendVerificationCodeFormDTO = new SendVerificationCodeFormDTO(); sendVerificationCodeFormDTO.setMobile(formDTO.getMobile()); sendVerificationCodeFormDTO.setAliyunTemplateCode(SmsTemplateConstant.LGOIN_CONFIRM); Result smsCodeResult = epmetMessageOpenFeignClient.sendVerificationCode(sendVerificationCodeFormDTO); if (!smsCodeResult.success()) { logger.warn(String.format(str, formDTO.getMobile(), smsCodeResult.getCode(), smsCodeResult.getMsg())); throw new RenException(smsCodeResult.getCode()); } //4.保存短信验证码(删除现有短信验证码 将新的短信验证码存入Redis) SendSmsCodeFormDTO sendSmsCodeFormDTO = new SendSmsCodeFormDTO(); sendSmsCodeFormDTO.setMobile(formDTO.getMobile()); captchaRedis.saveSmsCode(sendSmsCodeFormDTO, smsCodeResult.getData().getCode()); logger.info(String.format("发送短信验证码成功,手机号[%s]", formDTO.getMobile())); } /** * @Description 发送登录事件 * @return * @author wxz * @date 2021.06.08 15:27 */ private void sendLoginEvent(String userId, String appId, String fromApp, String fromClient) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); LoginMQMsg loginMQMsg = new LoginMQMsg(); loginMQMsg.setUserId(userId); loginMQMsg.setLoginTime(new Date()); loginMQMsg.setAppId(appId); loginMQMsg.setIp(IpUtils.getIpAddr(request)); loginMQMsg.setFromApp(fromApp); loginMQMsg.setFromClient(fromClient); SystemMsgFormDTO form = new SystemMsgFormDTO(); form.setMessageType(AuthOperationConstants.LOGIN); form.setContent(loginMQMsg); messageOpenFeignClient.sendSystemMsgByMQ(form); //getResultDataOrThrowsException(result, ServiceConstant.EPMET_MESSAGE_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "调用Message服务,发送登录事件到MQ失败"); } // 接入流程:https://open.dingtalk.com/document/isvapp-server/unified-authorization-suite-access-process // 1、获取个人用户token:https://open.dingtalk.com/document/isvapp-server/obtain-user-token // 2、获取用户通讯录个人信息:https://open.dingtalk.com/document/isvapp-server/dingtalk-retrieve-user-information // 接口逻辑: // (1)根据clientId去XXX表找到customerId // (2)通过1、2拿到手机号之后,根据mobile+customerId去user_base_info表找userId, // 是否注册居民:register_relation // (3)没有则生成user、user_Base_info表记录 /** * 钉钉应用的登录-居民端 * * @param formDTO * @return */ @Override public ResiDingAppLoginResDTO resiLoginDing(ResiDingAppLoginFormDTO formDTO) { //获取用户手机号 log.info("1、钉钉居民端应用登录入参:"+ JSON.toJSONString(formDTO)); ResiDingAppLoginResDTO resDTO= null; try { resDTO = new ResiDingAppLoginResDTO(); EnvEnum currentEnv = EnvEnum.getCurrentEnv(); if (EnvEnum.PROD.getCode().equals(currentEnv.getCode())) { //烟台的客户id resDTO.setCustomerId("1535072605621841922"); }else if(EnvEnum.TEST.getCode().equals(currentEnv.getCode())){ //最美琴岛 resDTO.setCustomerId("0c41b272ee9ee95ac6f184ad548a30eb"); }else{ //其余统一走开发环境 resDTO.setCustomerId("45687aa479955f9d06204d415238f7cc"); } //1、获取用户手机号 String clientId = formDTO.getClientId(); DingTalkResult userAccessToken = dingTalkClientToken.getUserAccessToken(formDTO.getAuthCode(), clientId, DingMiniAppEnum.getEnum(clientId).getSuiteSecret()); log.info("2、resiLoginDing userAccessToken:{}",JSON.toJSONString(userAccessToken)); if (!userAccessToken.success() || null == userAccessToken.getData()) { throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "调用微信api异常:" + JSON.toJSONString(userAccessToken), EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getMsg()); } DingTalkResult me = dingTalkClientUser.getUserInfo("me", userAccessToken.getData().getAccessToken()); log.info("3、resiLoginDing me:{}",JSON.toJSONString(me)); resDTO.setExtInfo(JSON.toJSONString(me.getData())); // 2、调用userfeign接口获取userId、注册网格相关信息 todo DingLoginResiFormDTO dingLoginResiFormDTO=ConvertUtils.sourceToTarget(me.getData(),DingLoginResiFormDTO.class); dingLoginResiFormDTO.setCustomerId(resDTO.getCustomerId()); Result loginResiResDTOResult = epmetUserOpenFeignClient.dingResiLogin(dingLoginResiFormDTO); if (!loginResiResDTOResult.success() || null == loginResiResDTOResult.getData()) { //临时打个日志 log.error(String.format("resilogin-ding获取epmetUserId异常,入参:%s,user服务返参:%s", JSON.toJSONString(formDTO), JSON.toJSONString(loginResiResDTOResult))); throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "获取epmetUserId异常:" + JSON.toJSONString(loginResiResDTOResult), EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getMsg()); } DingLoginResiResDTO resiResDTO=loginResiResDTOResult.getData(); resDTO.setGridId(resiResDTO.getGridId()); resDTO.setGridName(resiResDTO.getGridName()); resDTO.setAgencyId(resiResDTO.getAgencyId()); resDTO.setEpmetUserId(resiResDTO.getEpmetUserId()); resDTO.setRegFlag(resiResDTO.getRegFlag()); //3.生成token,并且存放Redis String token=this.saveTokenDtoDing(formDTO.getClientId(),AppClientConstant.APP_RESI,AppClientConstant.MINI_DING, resDTO.getEpmetUserId(), resDTO.getCustomerId()); resDTO.setAuthorization(token); } catch (ApiException e) { throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), e.getErrMsg(), EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getMsg()); } return resDTO; } private String saveTokenDtoDing(String suiteKey,String app,String client, String userId,String customerId) { //生成token串 Map map = new HashMap<>(); map.put(AppClientConstant.APP, app); map.put(AppClientConstant.CLIENT, client); map.put("userId", userId); String token = jwtTokenUtils.createToken(map); int expire = jwtTokenProperties.getExpire(); TokenDto tokenDto = new TokenDto(); tokenDto.setCustomerId(customerId); tokenDto.setApp(app); tokenDto.setClient(client); tokenDto.setUserId(userId); tokenDto.setToken(token); tokenDto.setUpdateTime(System.currentTimeMillis()); tokenDto.setExpireTime(jwtTokenUtils.getExpiration(token).getTime()); // cpUserDetailRedis.set(tokenDto, expire); cpUserDetailRedis.setForDingApp(suiteKey,tokenDto, expire); logger.info("截止时间:" + DateUtils.format(jwtTokenUtils.getExpiration(token), "yyyy-MM-dd HH:mm:ss")); return token; } @Override public ResiDingAppLoginResDTO resiLoginDingTemp(ResiDingAppLoginFormDTO formDTO) { //获取用户手机号 log.info("钉钉居民端应用登录入参:"+ JSON.toJSONString(formDTO)); ResiDingAppLoginResDTO resDTO= null; try { resDTO = new ResiDingAppLoginResDTO(); EnvEnum currentEnv = EnvEnum.getCurrentEnv(); if (EnvEnum.PROD.getCode().equals(currentEnv.getCode())) { //烟台的客户id resDTO.setCustomerId("1535072605621841922"); }else if(EnvEnum.TEST.getCode().equals(currentEnv.getCode())){ //最美琴岛 resDTO.setCustomerId("0c41b272ee9ee95ac6f184ad548a30eb"); resDTO.setGridId("f896b59f3cddf1f54280546d79803652"); resDTO.setGridName("抚顺社区-抚顺第一网格"); resDTO.setAgencyId("f6e183d8e6687020074e6d8061926bfa"); resDTO.setEpmetUserId("f838614e67cf8ae0edaefe562b6660e5"); resDTO.setRegFlag(true); }else if(EnvEnum.LOCAL.getCode().equals(currentEnv.getCode())||EnvEnum.DEV.getCode().equals(currentEnv.getCode())){ //其余统一走开发环境 resDTO.setCustomerId("45687aa479955f9d06204d415238f7cc"); resDTO.setGridId("763d6e09b9081d63195d53da84b3ae3a"); resDTO.setGridName("抚顺社区-抚顺第二网格"); resDTO.setAgencyId("f6e183d8e6687020074e6d8061926bfa"); resDTO.setEpmetUserId("f838614e67cf8ae0edaefe562b6660e5"); resDTO.setRegFlag(true); } //1、获取用户手机号 String clientId = formDTO.getClientId(); DingTalkResult userAccessToken = dingTalkClientToken.getUserAccessToken(formDTO.getAuthCode(), clientId, DingMiniAppEnum.getEnum(clientId).getSuiteSecret()); log.info("resiLoginDing userAccessToken:{}",JSON.toJSONString(userAccessToken)); if (!userAccessToken.success() || null == userAccessToken.getData()) { throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "调用微信api异常:" + JSON.toJSONString(userAccessToken), EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getMsg()); } DingTalkResult me = dingTalkClientUser.getUserInfo("me", userAccessToken.getData().getAccessToken()); log.info("resiLoginDing me:{}",JSON.toJSONString(me)); resDTO.setExtInfo(JSON.toJSONString(me.getData())); // 2、调用userfeign接口获取userId、注册网格相关信息 todo //3.生成token,并且存放Redis String token=this.saveTokenDtoDing(clientId,AppClientConstant.APP_RESI,AppClientConstant.MINI_DING, resDTO.getEpmetUserId(), resDTO.getCustomerId()); resDTO.setAuthorization(token); } catch (ApiException e) { throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), e.getErrMsg(), EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getMsg()); } return resDTO; } }