package doumeemes.service.system.impl; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import doumeemes.biz.system.SystemDictDataBiz; import doumeemes.config.shiro.ShiroToken; import doumeemes.core.constants.ResponseStatus; import doumeemes.core.exception.BusinessException; import doumeemes.core.model.LoginUserInfo; import doumeemes.core.utils.Constants; import doumeemes.core.utils.HttpsUtil; import doumeemes.core.utils.Utils; import doumeemes.core.utils.WxMiniConfig; import doumeemes.dao.business.model.Company; import doumeemes.dao.business.model.CompanyUser; import doumeemes.dao.business.model.Department; import doumeemes.dao.ext.CompanyExtMapper; import doumeemes.dao.ext.CompanyUserExtMapper; import doumeemes.dao.ext.DepartmentExtMapper; import doumeemes.dao.ext.dto.WxLoginDTO; import doumeemes.dao.ext.dto.WxLoginOutDTO; import doumeemes.dao.ext.vo.WxLoginVO; import doumeemes.dao.system.SystemUserMapper; import doumeemes.dao.system.dto.LoginDTO; import doumeemes.dao.system.model.SystemLoginLog; import doumeemes.dao.system.model.SystemUser; import doumeemes.service.system.SystemLoginLogService; import doumeemes.service.system.WxLoginService; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.Date; import java.util.Objects; /** * Created by IntelliJ IDEA. * * @Author : Rk * @create 2023/8/11 10:14 */ @Slf4j @Service public class WxLoginServiceImpl implements WxLoginService { @Autowired private SystemDictDataBiz systemDictDataBiz; @Value("${project.version}") private String systemVersion; @Autowired private CompanyUserExtMapper companyUserExtMapper; @Autowired private SystemUserMapper systemUserMapper; @Autowired private DepartmentExtMapper departmentExtMapper; @Autowired private SystemLoginLogService systemLoginLogService; @Autowired private CompanyExtMapper companyExtMapper; /** * 微信公众号获取TOKEN地址 */ public static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; /** * 微信公众号获取USERINFO信息地址 */ public static final String GET_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; public static final String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; /** * 注:公众号-设置与开发-基本设置,必须【已绑定的微信开放平台账号】 * @param code * @param request * @return */ @Override public WxLoginVO wxLogin(String code, HttpServletRequest request) { String appId = systemDictDataBiz.queryByCode(Constants.WX_CONFIG,Constants.APPID).getCode(); String appSecret = systemDictDataBiz.queryByCode(Constants.WX_CONFIG,Constants.APPSECRET).getCode(); String getTokenUrl = GET_ACCESS_TOKEN_URL.replace("CODE", code).replace("APPID", appId).replace("SECRET", appSecret); JSONObject tokenJson = JSONObject.parseObject(HttpsUtil.get(getTokenUrl,true)); String openId = tokenJson.getString("openid"); //注:公众号-设置与开发-基本设置,必须【已绑定的微信开放平台账号】 String unionId = tokenJson.getString("unionid"); return loginByUnionIdAndReturn(unionId,Constants.OPENID_WX+openId,request); } @Override public WxLoginVO wxProgramLogin(String code, HttpServletRequest request) { try { WxMaJscode2SessionResult session = WxMiniConfig.wxMaService.getUserService().getSessionInfo(code); String unionid = session.getUnionid(); String openId = session.getOpenid(); return loginByUnionIdAndReturn(unionid,Constants.OPENID_MINI+openId,request); } catch (WxErrorException e) { e.printStackTrace(); } throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"微信授权失败,请联系管理员"); } private WxLoginVO loginByUnionIdAndReturn(String unionid,String openId,HttpServletRequest request) { WxLoginVO wxLoginVO = new WxLoginVO(); wxLoginVO.setOpenid(openId); wxLoginVO.setUnionid(unionid); CompanyUser companyUser = companyUserExtMapper.selectOne(new QueryWrapper().lambda() .eq(CompanyUser::getUnionid,wxLoginVO.getUnionid()) .eq(CompanyUser::getDeleted,Constants.ZERO) .last(" limit 1 ")); // CompanyUser companyUser = companyUserExtMapper.selectOne(new QueryWrapper().eq("openid",openId).last(" limit 1 ")); if(Objects.isNull(companyUser)){ wxLoginVO.setLoginStatus(Constants.ONE); return wxLoginVO; } Department department = departmentExtMapper.selectById(companyUser.getRootDepartId()); if(Objects.isNull(department)){ throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(),"未查询到绑定部门信息"); } Company company = companyExtMapper.selectById(department.getCompanyId()); if(Objects.isNull(company)||company.getStatus().equals(Constants.ZERO)){ wxLoginVO.setLoginStatus(Constants.ONE); return wxLoginVO; } SystemUser systemUser = systemUserMapper.selectById(companyUser.getUserId()); //查询用户数据 LoginDTO dto = new LoginDTO(); dto.setCompanyId(department.getCompanyId()); dto.setUsername(systemUser.getUsername()); SystemLoginLog loginLog = new SystemLoginLog(); loginLog.setLoginUsername(dto.getUsername()); loginLog.setLoginTime(new Date()); loginLog.setSystemVersion(systemVersion); loginLog.setIp(Utils.User_Client.getIP(request)); loginLog.setLocation(Utils.Location.getLocationString(loginLog.getIp())); loginLog.setPlatform(Utils.User_Client.getPlatform(request)); loginLog.setClientInfo(Utils.User_Client.getBrowser(request)); loginLog.setOsInfo(Utils.User_Client.getOS(request)); loginLog.setServerIp(Utils.Server.getIP()); // 校验用户名和密码 Subject subject = SecurityUtils.getSubject(); ShiroToken token = new ShiroToken(dto.getCompanyId(),dto.getUsername(), null,false,true); try { subject.login(token); LoginUserInfo loginUser = ((LoginUserInfo)subject.getPrincipal()); loginLog.setUserId(loginUser.getId()); loginLog.setCompanyId(loginUser.getCompany()!=null?loginUser.getCompany().getId():null); loginLog.setCompanyUserId(loginUser.getCompanyUser()!=null?loginUser.getCompanyUser().getId():null); loginLog.setSuccess(Boolean.TRUE); loginLog.setOrgin(Constants.USER_LOGIN_ORIGIN.wx); systemLoginLogService.create(loginLog); String session = (String)subject.getSession().getId(); wxLoginVO.setLoginStatus(Constants.ZERO); wxLoginVO.setSession(session); return wxLoginVO; }catch (BusinessException e) { wxLoginVO.setLoginStatus(Constants.ONE); return wxLoginVO; }catch (AuthenticationException e) { BusinessException ee = null; loginLog.setSuccess(Boolean.FALSE); if(e.getCause()!=null && e.getCause() instanceof BusinessException){ ee = (BusinessException)e.getCause(); loginLog.setReason(ee.getMessage().length() > 200 ? (ee.getMessage().substring(0, 190) + "...") : ee.getMessage()); log.error(ee.getMessage(), e); }else{ log.error(ResponseStatus.ACCOUNT_INCORRECT.getMessage(), e); loginLog.setReason(e.getMessage().length() > 200 ? (e.getMessage().substring(0, 190) + "...") : e.getMessage()); ee = new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); } systemLoginLogService.create(loginLog); throw ee; } } @Override public String wxLoginByPassword(WxLoginDTO dto, HttpServletRequest request) { SystemLoginLog loginLog = new SystemLoginLog(); loginLog.setLoginUsername(dto.getUsername()); loginLog.setLoginTime(new Date()); loginLog.setSystemVersion(systemVersion); loginLog.setIp(Utils.User_Client.getIP(request)); loginLog.setLocation(Utils.Location.getLocationString(loginLog.getIp())); loginLog.setPlatform(Utils.User_Client.getPlatform(request)); loginLog.setClientInfo(Utils.User_Client.getBrowser(request)); loginLog.setOsInfo(Utils.User_Client.getOS(request)); loginLog.setServerIp(Utils.Server.getIP()); // 校验用户名和密码 Subject subject = SecurityUtils.getSubject(); ShiroToken token = new ShiroToken(dto.getCompanyId(),dto.getUsername(), dto.getPassword(),false,false); try { subject.login(token); LoginUserInfo loginUser = ((LoginUserInfo)subject.getPrincipal()); loginLog.setUserId(loginUser.getId()); loginLog.setCompanyId(loginUser.getCompany()!=null?loginUser.getCompany().getId():null); loginLog.setCompanyUserId(loginUser.getCompanyUser()!=null?loginUser.getCompanyUser().getId():null); loginLog.setSuccess(Boolean.TRUE); systemLoginLogService.create(loginLog); //登录携带微信openid信息 if(StringUtils.isNotBlank(dto.getOpenid())){ CompanyUser companyUser = companyUserExtMapper.selectById(loginLog.getCompanyUserId()); if(StringUtils.isBlank(companyUser.getOpenid())||!companyUser.getOpenid().equals(dto.getOpenid())){ //1、绑定微信openid到companyUser表信息 companyUser.setOpenid(dto.getOpenid()); companyUser.setUnionid(dto.getUnionid()); companyUserExtMapper.updateById(companyUser); //2、清空同用户其余companyUser表openid与 unionid companyUserExtMapper.update(null,new UpdateWrapper() .ne("ID",companyUser.getId()).set("UNIONID","").set("OPENID","") .eq("USER_ID",companyUser.getUserId()) ); } } return (String)subject.getSession().getId(); }catch (AuthenticationException e) { BusinessException ee = null; loginLog.setSuccess(Boolean.FALSE); if(e.getCause()!=null && e.getCause() instanceof BusinessException){ ee = (BusinessException)e.getCause(); loginLog.setReason(ee.getMessage().length() > 200 ? (ee.getMessage().substring(0, 190) + "...") : ee.getMessage()); log.error(ee.getMessage(), e); }else{ log.error(ResponseStatus.ACCOUNT_INCORRECT.getMessage(), e); loginLog.setReason(e.getMessage().length() > 200 ? (e.getMessage().substring(0, 190) + "...") : e.getMessage()); ee = new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); } systemLoginLogService.create(loginLog); throw ee; } } @Override public void wxLoginOut(WxLoginOutDTO wxLoginOutDTO) { if(!Objects.isNull(wxLoginOutDTO)&&!Objects.isNull(wxLoginOutDTO.getCompanyUserId())){ companyUserExtMapper.update(null,new UpdateWrapper() .set("UNIONID","").set("OPENID","") .eq("id",wxLoginOutDTO.getCompanyUserId()) ); } } }