package com.izouma.walkchina.service; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import com.izouma.walkchina.constant.AppConstants; import com.izouma.walkchina.domain.FriendInfo; import com.izouma.walkchina.domain.UserInfo; import com.izouma.walkchina.dto.RankInfo; import com.izouma.walkchina.dto.UserWalkStats; import com.izouma.walkchina.exception.ServiceException; import com.izouma.walkchina.repo.FriendInfoRepository; import com.izouma.walkchina.repo.UserInfoRepository; import com.izouma.walkchina.repo.WalkDataRepository; import com.izouma.walkchina.service.storage.StorageService; import com.izouma.walkchina.utils.ImageUtils; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import java.util.UUID; @Service @Slf4j public class UserInfoService implements UserDetailsService { @Autowired private UserInfoRepository userInfoRepository; @Autowired private WxMaService wxMaService; @Autowired private StorageService storageService; @Autowired private FriendInfoRepository friendInfoRepository; @Autowired private WalkDataRepository walkDataRepository; @Autowired private FriendInfoService friendInfoService; @Autowired private TeamService teamService; @Override public UserInfo loadUserByUsername(String username) { log.info("loadUserByUsername {}", username); return userInfoRepository.findByUsername(username); } public UserInfo registerByUserPwd(String username, String password) { UserInfo userInfo = userInfoRepository.findByUsername(username); if (userInfo != null) { throw new ServiceException("该用户已存在"); } userInfo = UserInfo.builder() .username(username) .password(new BCryptPasswordEncoder().encode(password)) .nickname("用户" + RandomStringUtils.randomAlphabetic(6)) .avatar(AppConstants.DEFAULT_AVATAR) .sex(0) .active(true) .build(); userInfo = userInfoRepository.save(userInfo); return userInfo; } public UserInfo loginMiniApp(String code) { try { WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code); String openId = result.getOpenid(); String sessionKey = result.getSessionKey(); UserInfo userInfo = userInfoRepository.findByOpenId(openId); if (userInfo != null) { userInfo.setSessionKey(sessionKey); return userInfoRepository.save(userInfo); } userInfo = UserInfo.builder() .username(UUID.randomUUID().toString()) .nickname("用户" + RandomStringUtils.randomAlphabetic(6)) .openId(openId) .avatar(AppConstants.DEFAULT_AVATAR) .sex(0) .active(true) .sessionKey(sessionKey) .build(); uploadUserMarker(userInfo); return userInfoRepository.save(userInfo); } catch (WxErrorException e) { e.printStackTrace(); } throw new ServiceException("登录失败"); } public UserInfo getMiniAppUserInfo(String sessionKey, String rawData, String signature, String encryptedData, String iv) { // 用户信息校验 if (!wxMaService.getUserService().checkUserInfo(sessionKey, rawData, signature)) { throw new ServiceException("获取用户信息失败"); } // 解密用户信息 WxMaUserInfo wxUserInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv); UserInfo userInfo = userInfoRepository.findByOpenId(wxUserInfo.getOpenId()); String avatarUrl = AppConstants.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 (userInfo == null) { userInfo = UserInfo.builder() .username(UUID.randomUUID().toString()) .nickname(wxUserInfo.getNickName()) .openId(wxUserInfo.getOpenId()) .unionId(wxUserInfo.getUnionId()) .avatar(avatarUrl) .sex(Integer.valueOf(wxUserInfo.getGender())) .country(wxUserInfo.getCountry()) .province(wxUserInfo.getProvince()) .city(wxUserInfo.getCity()) .active(true) .build(); userInfo = userInfoRepository.save(userInfo); } else { userInfo.setAvatar(avatarUrl); userInfo.setNickname(wxUserInfo.getNickName()); userInfo.setUnionId(wxUserInfo.getUnionId()); userInfo.setSex(Integer.valueOf(wxUserInfo.getGender())); userInfo.setCountry(wxUserInfo.getCountry()); userInfo.setProvince(wxUserInfo.getProvince()); userInfo.setCity(wxUserInfo.getCity()); userInfo = userInfoRepository.save(userInfo); } if (userInfo != null) { uploadUserMarker(userInfo); return userInfo; } throw new ServiceException("获取用户信息失败"); } public void saveFriend(Long userId1, Long userId2) { try { friendInfoRepository.save(FriendInfo.builder().userId(userId1).friendId(userId2).build()); } catch (Exception ignored) { } try { friendInfoRepository.save(FriendInfo.builder().userId(userId2).friendId(userId1).build()); } catch (Exception ignored) { } } public void updateLocation(Long userId, Double latitude, Double longitude) { UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在")); userInfo.setLatitude(latitude); userInfo.setLongitude(longitude); userInfoRepository.save(userInfo); } private void uploadUserMarker(UserInfo userInfo) { try { storageService.uploadFromInputStream(ImageUtils.getInputStream(ImageUtils.makeMarker("user", userInfo.getAvatar()), "png"), "marker/user/" + userInfo.getId() + ".png"); storageService.uploadFromInputStream(ImageUtils.getInputStream(ImageUtils.makeMarker("location", userInfo.getAvatar()), "png"), "marker/location/" + userInfo.getId() + ".png"); } catch (Exception e) { log.error("upload marker", e); } } public UserWalkStats getUserWalkStats(Long userId) { UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在")); Date now = new Date(); return UserWalkStats.builder() .nickname(userInfo.getNickname()) .avatar(userInfo.getAvatar()) .level(userInfo.getLevel()) .totalSteps(userInfo.getTotalSteps()) .walkCities(userInfo.getWalkCities()) .todaySteps(walkDataRepository.sumUserWalkSteps(userId, now, now).orElse(0L)) .teamSteps(walkDataRepository.sumTeamWalkSteps(userId, now, now).orElse(0L)) .build(); } public void acceptInvite(Long userId, Long inviter, boolean recruit) { friendInfoService.saveFriend(userId, inviter); if (recruit) { teamService.recruit(inviter, userId); } } public List friendRank(Long userId) { return userInfoRepository.findFriendByRank(userId); } public void update(Long userId, Map map) { UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在")); if (map.get("nickname") != null) { userInfo.setNickname(String.valueOf(map.get("nickname"))); } if (map.get("avatar") != null) { userInfo.setAvatar(String.valueOf(map.get("avatar"))); } if (map.get("sex") != null) { userInfo.setSex(Integer.parseInt(map.get("sex").toString())); } userInfoRepository.save(userInfo); } }