package com.izouma.jiashanxia.service; 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 cn.hutool.core.util.ObjectUtil; import com.izouma.jiashanxia.config.Constants; import com.izouma.jiashanxia.domain.User; import com.izouma.jiashanxia.dto.EmployeeDTO; import com.izouma.jiashanxia.dto.PageQuery; import com.izouma.jiashanxia.dto.UserRegister; import com.izouma.jiashanxia.enums.AuthorityName; import com.izouma.jiashanxia.exception.BusinessException; import com.izouma.jiashanxia.repo.UserRepo; import com.izouma.jiashanxia.security.Authority; import com.izouma.jiashanxia.security.JwtTokenUtil; import com.izouma.jiashanxia.security.JwtUserFactory; import com.izouma.jiashanxia.service.sms.SmsService; import com.izouma.jiashanxia.service.storage.StorageService; import com.izouma.jiashanxia.utils.JpaUtils; import com.izouma.jiashanxia.utils.SecurityUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Page; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.persistence.criteria.Predicate; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @Service @Slf4j @AllArgsConstructor public class UserService { private UserRepo userRepo; private WxMaService wxMaService; private WxMpService wxMpService; private SmsService smsService; private StorageService storageService; private JwtTokenUtil jwtTokenUtil; private CaptchaService captchaService; public Page all(PageQuery pageQuery) { return userRepo.findAll(JpaUtils.toSpecification(pageQuery, User.class), JpaUtils.toPageRequest(pageQuery)); } public User create(UserRegister userRegister) { User user = new User(); BeanUtils.copyProperties(userRegister, user); if (StringUtils.isNotBlank(userRegister.getPassword())) { user.setPassword(new BCryptPasswordEncoder().encode(userRegister.getPassword())); } return userRepo.save(user); } public User loginByPhone(String phone) { return userRepo.findByPhone(phone); } public User loginMp(String code) throws WxErrorException { WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, null); User user = userRepo.findByOpenId(wxMpUser.getOpenId()); if (user == null) { user = User.builder() .username(UUID.randomUUID().toString()) .nickname(wxMpUser.getNickname()) .avatar(wxMpUser.getHeadImgUrl()) .sex(wxMpUser.getSexDesc()) .country(wxMpUser.getCountry()) .province(wxMpUser.getProvince()) .city(wxMpUser.getCity()) .openId(wxMpUser.getOpenId()) .language(wxMpUser.getLanguage()) .authorities(Collections.singleton(Authority.builder().name("ROLE_USER").build())) .build(); userRepo.save(user); } return user; } public User loginMa(String code, Long parent) { try { WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code); String openId = result.getOpenid(); String sessionKey = result.getSessionKey(); User userInfo = userRepo.findByOpenId(openId); if (userInfo != null) { // 上级不为空 && 用户上级为空 if (ObjectUtil.isNotEmpty(parent) && ObjectUtil.isNull(userInfo.getParent())) { userInfo.setParent(parent); userRepo.save(userInfo); } userInfo.setSessionKey(sessionKey); return userInfo; } userInfo = User.builder() .username(UUID.randomUUID().toString()) .nickname("用户" + RandomStringUtils.randomAlphabetic(6)) .openId(openId) .avatar(Constants.DEFAULT_AVATAR) .authorities(Collections.singleton(Authority.builder().name("ROLE_USER").build())) .parent(parent) .amount(BigDecimal.ZERO) .teamFounder(false) .sessionKey(sessionKey) .build(); userInfo = userRepo.save(userInfo); return userInfo; } catch (WxErrorException e) { e.printStackTrace(); } throw new BusinessException("登录失败"); } public User getMaUserInfo(String sessionKey, String rawData, String signature, String encryptedData, String iv) { // 用户信息校验 if (!wxMaService.getUserService().checkUserInfo(sessionKey, rawData, signature)) { throw new BusinessException("获取用户信息失败"); } // 解密用户信息 WxMaUserInfo wxUserInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv); User user = userRepo.findByOpenId(wxUserInfo.getOpenId()); String avatarUrl = Constants.DEFAULT_AVATAR; try { String path = "image/avatar/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + ".jpg"; avatarUrl = storageService.uploadFromUrl(wxUserInfo.getAvatarUrl(), path); } catch (Exception e) { log.error("获取头像失败", e); } if (user == null) { user = User.builder() .username(UUID.randomUUID().toString()) .nickname(wxUserInfo.getNickName()) .openId(wxUserInfo.getOpenId()) .avatar(avatarUrl) .sex(wxUserInfo.getGender()) .country(wxUserInfo.getCountry()) .province(wxUserInfo.getProvince()) .city(wxUserInfo.getCity()) .authorities(Collections.singleton(Authority.builder().name("ROLE_USER").build())) .amount(BigDecimal.ZERO) .teamFounder(false) .wxAuthorized(true) .build(); user = userRepo.save(user); } else { user.setAvatar(avatarUrl); user.setNickname(wxUserInfo.getNickName()); user.setSex(wxUserInfo.getGender()); user.setCountry(wxUserInfo.getCountry()); user.setProvince(wxUserInfo.getProvince()); user.setCity(wxUserInfo.getCity()); user.setWxAuthorized(true); user = userRepo.save(user); } return user; } public User getMaPhone(String sessionKey, String encryptedData, String iv) { // 解密用户信息 WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv); User user = userRepo.findById(SecurityUtils.getAuthenticatedUser().getId()) .orElseThrow(new BusinessException("用户不存在")); user.setPhone(phoneNoInfo.getPhoneNumber()); return userRepo.save(user); } public String setPassword(Long userId, String password) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); user.setPassword(new BCryptPasswordEncoder().encode(password)); user = userRepo.save(user); return jwtTokenUtil.generateToken(JwtUserFactory.create(user)); } public String setPassword(Long userId, String key, String code, String password) { if (!captchaService.verify(key, code)) { throw new BusinessException("验证码错误"); } return setPassword(userId, password); } public void updateUserInfo(Map data) { User user = userRepo.findById(SecurityUtils.getAuthenticatedUser().getId()) .orElseThrow(new BusinessException("用户不存在")); try { org.apache.commons.beanutils.BeanUtils.populate(user, data); } catch (IllegalAccessException | InvocationTargetException e) { log.error("updateUserInfo", e); } userRepo.save(user); } /* 我的推广 */ public List myPromotion(Long userId) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户")); List users = new ArrayList<>(); // 如果是企业创始人,查出下级所有推广 if (user.getTeamFounder()) { List employees = userRepo.findAllByCompanyId(user.getCompanyId()); List collect = employees.stream().map(User::getId).collect(Collectors.toList()); users.addAll(userRepo.findAllByParentIn(collect)); } users.addAll(userRepo.findAllByParent(userId)); return users; } /* 我的推广 */ public Page myPromotion(PageQuery pageQuery, Long userId) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户")); return userRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> { List and = JpaUtils.toPredicates(pageQuery, User.class, root, criteriaQuery, criteriaBuilder); if (user.getTeamFounder()) { List employees = userRepo.findAllByCompanyId(user.getCompanyId()); List collect = employees.stream().map(User::getId).collect(Collectors.toList()); and.add(root.get("parent").in(collect)); } else { and.add(criteriaBuilder.equal(root.get("parent"), userId)); } return criteriaBuilder.and(and.toArray(new Predicate[0])); }), JpaUtils.toPageRequest(pageQuery)); } /* 我的员工 */ public Page myEmployee(PageQuery pageQuery, User user) { // User user = userRepo.findById(id).orElseThrow(new BusinessException("无用户")); Set authorities = user.getAuthorities(); // 管理员返回所有 if (authorities.contains(Authority.get(AuthorityName.ROLE_ADMIN))) { return userRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> { List and = JpaUtils.toPredicates(pageQuery, User.class, root, criteriaQuery, criteriaBuilder); and.add(root.get("companyId").isNotNull()); return criteriaBuilder.and(and.toArray(new Predicate[0])); }), JpaUtils.toPageRequest(pageQuery)); } if (ObjectUtil.isNull(user.getCompanyId())) { throw new BusinessException("无企业"); } // 返回企业员工 return userRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> { List and = JpaUtils.toPredicates(pageQuery, User.class, root, criteriaQuery, criteriaBuilder); and.add(criteriaBuilder.equal(root.get("companyId"), user.getCompanyId())); return criteriaBuilder.and(and.toArray(new Predicate[0])); }), JpaUtils.toPageRequest(pageQuery)); } }