package com.izouma.nineth.service; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.request.AlipayUserCertifyOpenCertifyRequest; import com.alipay.api.request.AlipayUserCertifyOpenInitializeRequest; import com.alipay.api.request.AlipayUserCertifyOpenQueryRequest; import com.alipay.api.response.AlipayUserCertifyOpenCertifyResponse; import com.alipay.api.response.AlipayUserCertifyOpenInitializeResponse; import com.alipay.api.response.AlipayUserCertifyOpenQueryResponse; import com.huifu.adapay.core.exception.BaseAdaPayException; import com.izouma.nineth.config.Constants; import com.izouma.nineth.config.GeneralProperties; import com.izouma.nineth.config.RedisKeys; import com.izouma.nineth.domain.Collection; import com.izouma.nineth.domain.*; import com.izouma.nineth.dto.*; import com.izouma.nineth.dto.oasis.OasisLoginDTO; import com.izouma.nineth.enums.*; import com.izouma.nineth.event.RegisterEvent; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.*; import com.izouma.nineth.security.Authority; import com.izouma.nineth.security.JwtTokenUtil; import com.izouma.nineth.security.JwtUserFactory; import com.izouma.nineth.service.sms.SmsService; import com.izouma.nineth.service.storage.StorageService; import com.izouma.nineth.utils.*; 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.ObjectUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.BeanUtils; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.persistence.criteria.Predicate; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; 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 FollowService followService; private FollowRepo followRepo; private IdentityAuthRepo identityAuthRepo; private SysConfigService sysConfigService; private UserBankCardRepo userBankCardRepo; private InviteRepo inviteRepo; private CacheService cacheService; private CollectionRepo collectionRepo; private AdapayMerchantService adapayMerchantService; private RocketMQTemplate rocketMQTemplate; private GeneralProperties generalProperties; private RedisTemplate redisTemplate; private PasswordEncoder passwordEncoder; private WeakPassRepo weakPassRepo; private UserBalanceRepo userBalanceRepo; private ContentAuditService contentAuditService; private HeatInfoRepo heatInfoRepo; private ShowroomRepo showroomRepo; private TradingAccountRepo tradingAccountRepo; private AlipayClient alipayClient; private SnowflakeIdWorker snowflakeIdWorker; private FaceAuthRepo faceAuthRepo; private AuctionPassRecordRepo auctionPassRecordRepo; private AssetRepo assetRepo; private ShowCollectionRepo showCollectionRepo; private ShowroomService showroomService; private NewsLikeRepo newsLikeRepo; private RockRecordRepo rockRecordRepo; private AirDropService airDropService; public User update(User user) { if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN) & !SecurityUtils.hasRole(AuthorityName.ROLE_SAAS)) { if (!SecurityUtils.getAuthenticatedUser().getId().equals(user.getId())) { throw new BusinessException("无权限"); } } User orig = userRepo.findById(user.getId()).orElseThrow(new BusinessException("无记录")); ObjUtils.merge(orig, user); orig = save(orig); userRepo.updateAssetMinter(orig.getId()); userRepo.updateAssetOwner(orig.getId()); userRepo.updateCollectionMinter(orig.getId()); userRepo.updateCollectionOwner(orig.getId()); userRepo.updateOrderMinter(orig.getId()); userRepo.updateHistoryFromUser(orig.getId()); userRepo.updateHistoryToUser(orig.getId()); userRepo.updateShowroomToUser(orig.getId()); cacheService.clearCollection(); return orig; } public User save(User user) { if (user.getId() != null) { cacheService.clearUserMy(user.getId()); cacheService.clearUser(user.getId()); } cacheService.clearUserList(); return userRepo.save(user); } public MetaRestResult metaUpdate(User record) { if (Objects.isNull(record)) { return MetaRestResult.returnError("Illegal parameter : params can not be null"); } if (Objects.isNull(record.getId())) { return MetaRestResult.returnError("Illegal parameter : userId can not be null"); } if (StringUtils.isBlank(record.getNickname())) { return MetaRestResult.returnError("Illegal parameter : nickname can not be null"); } String nickname = record.getNickname(); User user = userRepo.findById(record.getId()).orElse(null); if (Objects.isNull(user)) { return MetaRestResult.returnError("用户信息为空"); } if (!nickname.equals(user.getNickname())) { if (!contentAuditService.auditText(nickname)) { return MetaRestResult.returnError("昵称包含非法内容"); } } user.setNickname(nickname); return MetaRestResult.returnSuccess(save(user)); } public User update(Long userId, String nickname, String avatar, String sex, String bg, String intro, Boolean useCollectionPic, Boolean riskWarning, Integer level, Boolean isPublicShow) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (StringUtils.isNotBlank(nickname)) { if (!nickname.equals(user.getNickname())) { if (!contentAuditService.auditText(nickname)) { throw new BusinessException("昵称包含非法内容"); } } user.setNickname(nickname); } if (StringUtils.isNotBlank(avatar)) { if (!avatar.equals(user.getAvatar())) { if (!contentAuditService.auditImage(avatar)) { throw new BusinessException("头像包含敏感信息"); } } user.setAvatar(avatar); } if (StringUtils.isNotBlank(sex)) { user.setSex(sex); } if (StringUtils.isNotBlank(bg)) { if (!bg.equals(user.getBg())) { if (!contentAuditService.auditImage(bg)) { throw new BusinessException("背景包含敏感信息"); } } user.setBg(bg); } if (StringUtils.isNotBlank(intro)) { if (!intro.equals(user.getIntro())) { if (!contentAuditService.auditText(intro)) { throw new BusinessException("简介包含非法内容"); } } user.setIntro(intro); } if (useCollectionPic != null) { user.setUseCollectionPic(useCollectionPic); } if (riskWarning != null) { user.setRiskWarning(riskWarning); } if (level != null) { user.setLevel(level); } if (isPublicShow != null) { user.setIsPublicShow(isPublicShow); } user = save(user); userRepo.updateAssetMinter(userId); userRepo.updateAssetOwner(userId); userRepo.updateCollectionMinter(userId); userRepo.updateCollectionOwner(userId); userRepo.updateOrderMinter(userId); userRepo.updateHistoryFromUser(userId); userRepo.updateHistoryToUser(userId); userRepo.updateShowroomToUser(userId); return user; } @Cacheable(value = "userList", key = "#pageQuery.hashCode()") public PageWrapper all(PageQuery pageQuery) { Specification specification = JpaUtils.toSpecification(pageQuery, User.class); specification = specification.and((Specification) (root, criteriaQuery, criteriaBuilder) -> { List and = new ArrayList<>(); and.add(criteriaBuilder.equal(root.get("del"), false)); if (!pageQuery.getQuery().containsKey("admin")) { and.add(criteriaBuilder.equal(root.get("admin"), false)); } if (pageQuery.getQuery().containsKey("hasRole")) { String roleName = (String) pageQuery.getQuery().get("hasRole"); if (roleName.equals("ROLE_MINTER")) { and.add(criteriaBuilder.equal(root.get("minter"), true)); } else { and.add(criteriaBuilder .isMember(Authority.get(AuthorityName.valueOf(roleName)), root.get("authorities"))); } } if (pageQuery.getQuery().containsKey("vip")) { boolean vip = (boolean) pageQuery.getQuery().get("vip"); if (vip) { and.add(criteriaBuilder.greaterThan(root.get("vipPurchase"), 0)); } else { and.add(criteriaBuilder.lessThanOrEqualTo(root.get("vipPurchase"), 0)); } } return criteriaBuilder.and(and.toArray(new Predicate[0])); }); Page page = userRepo.findAll(specification, JpaUtils.toPageRequest(pageQuery)); return PageWrapper.of(page); } public User create(UserRegister userRegister) { User user = new User(); BeanUtils.copyProperties(userRegister, user); user.setShareRatio(sysConfigService.getBigDecimal("share_ratio")); user.setAuthStatus(AuthStatus.NOT_AUTH); if (StringUtils.isNotBlank(userRegister.getPassword())) { checkPasswordStrength(userRegister.getPassword()); user.setPassword(passwordEncoder.encode(userRegister.getPassword())); } return save(user); } public User phoneRegister(String phone, String code, String password, String inviteCode, Long invitor, Long collectionId, Long showroomId, InviteType inviteType, String name) { if (StringUtils.isBlank(name)) { name = "0x" + RandomStringUtils.randomAlphabetic(8); } Long airDropCollectionId = collectionId; Invite invite = null; if (StringUtils.isNotBlank(inviteCode)) { invite = inviteRepo.findFirstByCode(inviteCode).orElse(null); } if (inviteType != null) { if (inviteType.equals(InviteType.AUCTION)) { User inviteUser = userRepo.findById(invitor).orElseThrow(new BusinessException("暂无用户")); invite = inviteRepo.findFirstByCode(String.valueOf(invitor)).orElse(null); if (invite == null) { Invite newOne = new Invite(); newOne.setInviteNum(0); newOne.setPhone(inviteUser.getPhone()); newOne.setCode(String.valueOf(invitor)); newOne.setName(inviteUser.getNickname()); newOne.setInviteType(InviteType.AUCTION); invite = inviteRepo.save(newOne); } } } smsService.verify(phone, code); Collection collection; if (inviteType != null) { if (collectionId != null & !inviteType.equals(InviteType.AUCTION)) { collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("无藏品")); // if (!collection.isOnShelf() || !collection.isSalable()) { // collectionId = null; // } else if (collection.isScheduleSale()) { // if (collection.getStartTime().isAfter(LocalDateTime.now())) { // collectionId = null; // } // } // 只看是否开去分享 if (ObjectUtils.isEmpty(collection.getOpenQuota()) || !collection.getOpenQuota()) { collectionId = null; } } } User user = create(UserRegister.builder() .username(name) .nickname(name) .password(password) .avatar(Constants.DEFAULT_AVATAR) .phone(phone) .invitorPhone(Optional.ofNullable(invite).map(Invite::getPhone).orElse(null)) .invitorName(Optional.ofNullable(invite).map(Invite::getName).orElse(null)) .inviteCode(Optional.ofNullable(invite).map(Invite::getCode).orElse(null)) .collectionInvitor(invitor) .collectionId(collectionId) .inviteType(inviteType) .build()); if (invite != null) { inviteRepo.increaseNum(invite.getId()); } if (ObjectUtils.isNotEmpty(showroomId)) { //通过展厅的注册数量 int weight = sysConfigService.getInt("heat_register_weight"); heatInfoRepo.save(HeatInfo.builder() .showroomId(showroomId) .userId(user.getId()) .type(HeatType.REGISTER) .value(weight) .build()); showroomRepo.addHeatAndRegister(showroomId, weight, 1); } //如果collectionId是设定的且invitor为空 if (airDropCollectionId != null) { long MMC_collection_id = sysConfigService.getInt("MMC_collection_id"); if (airDropCollectionId == MMC_collection_id) { airDropService.create(AirDrop.builder() .name("MMC注册空投奖励空投") .remark(user.getId().toString()) .type(AirDropType.asset) .userIds(Collections.singletonList(user.getId())) .collectionId(airDropCollectionId) .targets(Collections .singletonList(new DropTarget(user.getId(), user .getPhone(), user.getNickname(), 1))) .auto(true) .companyId(1L) .build()); } } return user; } public String mqRegister(String phone, String code, String password, String inviteCode, Long invitor, Long collectionId, Long showroomId) { rocketMQTemplate.convertAndSend(generalProperties.getRegisterTopic(), new RegisterEvent(phone, code, password, inviteCode, invitor, collectionId, showroomId)); return phone; } public Object getRegisterResult(String phone) { return redisTemplate.opsForValue().get("register::" + phone); } public void del(Long id) { User user = userRepo.findById(id).orElseThrow(new BusinessException("用户不存在")); user.setDel(true); if (StringUtils.isNoneEmpty(user.getOpenId())) { user.setOpenId(user.getOpenId() + "###" + RandomStringUtils.randomAlphabetic(8)); } if (StringUtils.isNoneEmpty(user.getPhone())) { user.setPhone(user.getPhone() + "###" + RandomStringUtils.randomAlphabetic(8)); } save(user); //删除实名认证 identityAuthRepo.softDeleteByUserId(id); } public User loginByPhone(String phone, String code) { User user = userRepo.findByPhoneAndDelFalse(phone).orElse(null); smsService.verify(phone, code); if (user == null) { String name = "0x" + RandomStringUtils.randomAlphabetic(8); user = create(UserRegister.builder() .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER))) .username(name) .nickname(name) .avatar(Constants.DEFAULT_AVATAR) .phone(phone) .build()); } return user; } public User loginByPhonePwd(String phone, String password) { if (StringUtils.isEmpty(phone)) { throw new BusinessException("手机号错误"); } User user = userRepo.findByPhoneAndDelFalse(phone).orElseThrow(new BusinessException("账号或密码错误")); if (StringUtils.isEmpty(user.getPassword())) { throw new BusinessException("账号或密码错误"); } if (StringUtils.isNoneEmpty(user.getPassword()) && !passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("账号或密码错误"); } return user; } public User loginByUsernamePwd(String username, String password) { if (StringUtils.isEmpty(username)) { throw new BusinessException("用户名错误"); } User user = userRepo.findByUsernameAndDelFalse(username).orElseThrow(new BusinessException("账号或密码错误")); if (StringUtils.isEmpty(user.getPassword()) || !passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("账号或密码错误"); } return user; } public User loginMp(String code) throws WxErrorException { WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, null); User user = userRepo.findByOpenIdAndDelFalse(wxMpUser.getOpenId()).orElse(null); if (user == null) { String name = "0x" + RandomStringUtils.randomAlphabetic(8); user = User.builder() .username(name) .nickname(name) .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.get(AuthorityName.ROLE_USER))) .authStatus(AuthStatus.NOT_AUTH) .build(); save(user); } return user; } public String code2openId(String code) throws WxErrorException { WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); return wxMpService.oauth2getUserInfo(accessToken, null).getOpenId(); } public User loginMa(String code) { try { WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code); String openId = result.getOpenid(); String sessionKey = result.getSessionKey(); User userInfo = userRepo.findByOpenIdAndDelFalse(openId).orElse(null); ; if (userInfo != null) { return userInfo; } String name = "0x" + RandomStringUtils.randomAlphabetic(8); userInfo = User.builder() .username(name) .nickname(name) .openId(openId) .avatar(Constants.DEFAULT_AVATAR) .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER))) .authStatus(AuthStatus.NOT_AUTH) .build(); userInfo = 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.findByOpenIdAndDelFalse(wxUserInfo.getOpenId()).orElse(null); 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())) .build(); user = 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 = save(user); } return user; } public String setPassword(Long userId, String password) { checkPasswordStrength(password); User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); user.setPassword(passwordEncoder.encode(password)); user = save(user); return jwtTokenUtil.generateToken(JwtUserFactory.create(user)); } public String setPassword(Long userId, String code, String password) { checkPasswordStrength(password); User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); smsService.verify(user.getPhone(), code); return setPassword(userId, password); } public String forgotPassword(String phone, String password, String code) { checkPasswordStrength(password); User user = userRepo.findByPhoneAndDelFalse(phone).orElseThrow(new BusinessException("手机号未注册")); smsService.verify(user.getPhone(), code); return setPassword(user.getId(), password); } public static void checkPasswordStrength(String password) { if (StringUtils.isBlank(password)) throw new BusinessException("密码不能为空"); if (!Pattern.matches("^[a-zA-Z0-9!@#$%^&*]+$", password)) throw new BusinessException("密码含非法字符"); int upper = 0; int lower = 0; int digit = 0; int special = 0; char ch; for (int i = 0; i < password.length(); i++) { ch = password.charAt(i); if (Character.isUpperCase(ch)) upper++; else if (Character.isLowerCase(ch)) lower++; else if (Character.isDigit(ch)) digit++; else { if (ch == '<' || ch == '>') { throw new BusinessException("密码包含非法字符"); } else special++; } } if (upper > 0 && lower > 0 && digit > 0 && password.length() >= 8) { return; } throw new BusinessException("密码长度至少为8位,且必须包含大小写字母和数字"); } public void bindPhone(Long userId, String phone) { User user = userRepo.findByIdAndDelFalse(userId).orElseThrow(new BusinessException("用户不存在")); if (StringUtils.isNoneEmpty(user.getPhone())) { throw new BusinessException("该账号已绑定手机"); } userRepo.findByPhoneAndDelFalse(phone).ifPresent(user1 -> { if (!user1.getId().equals(userId)) { throw new BusinessException("该手机号已绑定其他账号"); } }); user.setPhone(phone); save(user); } public UserDTO toDTO(User user) { return toDTO(user, true); } public UserDTO toDTO(User user, boolean join) { UserDTO userDTO = new UserDTO(); BeanUtils.copyProperties(user, userDTO); if (user.getAuthorities() != null) { userDTO.setAuthorities(new HashSet<>(user.getAuthorities())); } if (join) { if (SecurityUtils.getAuthenticatedUser() != null) { userDTO.setFollow(followService.isFollow(SecurityUtils.getAuthenticatedUser().getId(), user.getId())); } } return userDTO; } public List toDTO(List users) { List follows = new ArrayList<>(); if (SecurityUtils.getAuthenticatedUser() != null) { follows.addAll(followRepo.findByUserId(SecurityUtils.getAuthenticatedUser().getId())); } return users.stream().parallel().map(user -> { UserDTO dto = toDTO(user, false); if (!follows.isEmpty()) { dto.setFollow(follows.stream().anyMatch(f -> f.getFollowUserId().equals(user.getId()))); } return dto; }).collect(Collectors.toList()); } public Page toDTO(Page users) { List userDTOS = toDTO(users.getContent()); return new PageImpl<>(userDTOS, users.getPageable(), users.getTotalElements()); } @CacheEvict(value = "user", allEntries = true) public void setTradeCode(Long userId, String token, String tradeCode) { String phone = smsService.verifyToken(token); User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (!StringUtils.equals(phone, user.getPhone())) { throw new BusinessException("验证码无效"); } user.setTradeCode(passwordEncoder.encode(tradeCode)); save(user); } public void verifyTradeCode(Long userId, String tradeCode) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (!passwordEncoder.matches(tradeCode, user.getTradeCode())) { throw new BusinessException("交易密码错误"); } } public Map searchByPhone(String phone) { if (AuthStatus.SUCCESS != SecurityUtils.getAuthenticatedUser().getAuthStatus()) { throw new BusinessException("实名认证后才能赠送"); } User user = userRepo.findByPhoneAndDelFalse(phone).orElseThrow(new BusinessException("用户不存在或未认证")); if (AuthStatus.SUCCESS != user.getAuthStatus()) { throw new BusinessException("用户不存在或未认证"); } String realName = identityAuthRepo.findFirstByUserIdAndStatusAndDelFalseOrderByCreatedAtDesc( user.getId(), AuthStatus.SUCCESS) .map(IdentityAuth::getRealName).orElse("").replaceAll(".*(?=.)", "**"); Map map = new HashMap<>(); map.put("id", user.getId()); map.put("avatar", user.getAvatar()); map.put("phone", user.getPhone().replaceAll("(?<=.{3}).*(?=.{4})", "**")); map.put("realName", realName); return map; } public Map searchByPhoneAdmin(String phoneStr) { List phone = Arrays.stream(phoneStr.replaceAll("\n", " ") .replaceAll("\r\n", " ") .split(" ")) .map(String::trim) .filter(s -> !StringUtils.isEmpty(s)) .collect(Collectors.toList()); List users = userRepo.findByPhoneInAndDelFalse(phone); Map map = new HashMap<>(); map.put("users", users); List notFound = phone.stream().filter(p -> users.stream().noneMatch(u -> p.equals(u.getPhone()))) .collect(Collectors.toList()); map.put("notFound", notFound); return map; } public void addBankCard(Long userId, String bankNo, String phone, String code) throws BaseAdaPayException { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); IdentityAuth identityAuth = identityAuthRepo .findFirstByUserIdAndStatusAndDelFalseOrderByCreatedAtDesc(userId, AuthStatus.SUCCESS) .orElseThrow(new BusinessException("用户未认证")); if (identityAuth.isOrg()) { //throw new BusinessException("企业认证用户请绑定对公账户"); } if (!StringUtils.isBlank(user.getSettleAccountId())) { throw new BusinessException("此账号已绑定"); } BankValidate bankValidate = BankUtils.validate(bankNo); if (!bankValidate.isValidated()) { throw new BusinessException("暂不支持此卡"); } smsService.verify(phone, code); // adapayMerchantService.createMemberForAll(userId.toString(), user.getPhone(), identityAuth.getRealName(), identityAuth.getIdNo()); // user.setMemberId(user.getId().toString()); // save(user); // // String accountId = adapayMerchantService.createSettleAccountForAll // (user.getMemberId(), identityAuth.getRealName(), // identityAuth.getIdNo(), phone, bankNo); // user.setSettleAccountId(Optional.ofNullable(accountId).orElse("1")); // save(user); user.setMemberId(user.getId().toString()); user.setSettleAccountId("1"); save(user); userBankCardRepo.save(UserBankCard.builder() .bank(bankValidate.getBank()) .bankName(bankValidate.getBankName()) .bankNo(bankNo) .cardType(bankValidate.getCardType()) .cardTypeDesc(bankValidate.getCardTypeDesc()) .userId(userId) .phone(phone) .realName(identityAuth.getRealName()) .idNo(identityAuth.getIdNo()) .build()); userBalanceRepo.unlock(userId); } public void removeBankCard(Long userId) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); // if (StringUtils.isNotBlank(user.getSettleAccountId()) && StringUtils.isNotBlank(user.getMemberId())) { // adapayMerchantService.delSettleAccountForAll(user.getMemberId()); // user.setSettleAccountId(null); // save(user); // userBankCardRepo.deleteByUserId(userId); // cacheService.clearUserMy(userId); // } else { // throw new BusinessException("未绑定"); // } user.setSettleAccountId(null); save(user); userBankCardRepo.deleteByUserId(userId); cacheService.clearUserMy(userId); } public void removeAuth(Long userId) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (user.getAuthStatus() == AuthStatus.SUCCESS) { user.setAuthStatus(AuthStatus.NOT_AUTH); save(user); identityAuthRepo.deleteAll(identityAuthRepo.findByUserIdAndDelFalse(userId)); cacheService.clearUserMy(userId); } } public Map batchRegister(String phones, String defaultPassword) { List exist = new ArrayList<>(); List err = new ArrayList<>(); List success = new ArrayList<>(); Arrays.stream(phones.replaceAll(",", " ") .replaceAll(",", " ") .replaceAll("\n", " ") .replaceAll("\r\n", " ") .split(" ")).forEach(phone -> { if (userRepo.findByPhoneAndDelFalse(phone).isPresent()) { exist.add(phone); } else { if (!Pattern.matches("^1[3-9]\\d{9}$", phone)) { err.add(phone); } else { try { String name = "0x" + RandomStringUtils.randomAlphabetic(8); User user = create(UserRegister.builder() .authorities(Collections .singleton(Authority.get(AuthorityName.ROLE_USER))) .username(name) .nickname(name) .password(defaultPassword) .avatar(Constants.DEFAULT_AVATAR) .phone(phone) .build()); success.add(phone); } catch (Exception e) { log.error("注册失败", e); err.add(phone); } } } }); Map map = new HashMap<>(); map.put("exist", exist); map.put("error", err); map.put("success", success); return map; } public Map invite(PageQuery pageQuery) { Page all = this.all(pageQuery).toPage(); List userIds = all.map(User::getId).getContent(); // List page = tokenHistoryRepo.userBuy(userIds); // Map buy = page.stream() // .collect(Collectors.groupingBy(TokenHistory::getToUserId, // Collectors.mapping(TokenHistory::getPrice, // Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)))); Page users = all.map(user -> { InvitePhoneDTO dto = new InvitePhoneDTO(user); BigDecimal buy = rockRecordRepo.findRecordByUserIdOrderByCreatedAtDesc(user.getId()); dto.setTotal(buy); return dto; }); BigDecimal total = rockRecordRepo.findRecordByUserIdOrderByIdInDesc(userIds); Map map = new HashMap<>(); map.put("user", users); map.put("total", total); return map; } @Async public void checkSettleAccountAsync() { checkSettleAccount(); } public void checkSettleAccount() { List list = userRepo.findBySettleAccountIdIsNotNull(); AtomicInteger count = new AtomicInteger(); list.forEach(user -> { try { Thread.sleep(500); IdentityAuth identityAuth = identityAuthRepo .findFirstByUserIdAndStatusAndDelFalseOrderByCreatedAtDesc(user.getId(), AuthStatus.SUCCESS) .orElseThrow(new BusinessException("用户未认证")); UserBankCard userBankCard = userBankCardRepo.findByUserId(user.getId()).stream().findAny() .orElseThrow(new BusinessException("未绑卡")); adapayMerchantService.createMemberForAll( user.getId().toString(), Optional.ofNullable(userBankCard.getPhone()).orElse(user.getPhone()), identityAuth.getRealName(), identityAuth.getIdNo()); adapayMerchantService.createSettleAccountForAll( user.getId().toString(), identityAuth.getRealName(), identityAuth.getIdNo(), Optional.ofNullable(userBankCard.getPhone()).orElse(user.getPhone()), userBankCard.getBankNo()); userBankCard.setPhone(Optional.ofNullable(userBankCard.getPhone()).orElse(user.getPhone())); userBankCardRepo.save(userBankCard); } catch (Exception e) { user.setSettleAccountId(null); save(user); userBankCardRepo.deleteByUserId(user.getId()); } count.getAndIncrement(); log.info("checkSettleAccount {}/{}", count.get(), list.size()); }); } @Cacheable(value = "myUserInfo", key = "#id") public User my(Long id) { User user = userRepo.findById(id).orElseThrow(new BusinessException("用户不存在")); user.setPassword(null); user.setTradeCode(null); return user; } public Page toMinterDTO(Page users) { List origins = users.getContent(); List minters = new ArrayList<>(); origins.forEach(user -> { Minter minter = Minter.builder() .id(user.getId()) .name(user.getNickname()) .avatar(user.getAvatar()) .build(); minters.add(minter); }); return new PageImpl<>(minters, users.getPageable(), users.getTotalElements()); } @Async public List scanWeakPassword() { String[] weakPass = new String[]{ "000000", "111111", "11111111", "112233", "123123", "123321", "123456", "12345678", "654321", "666666", "888888", "abcdef", "abcabc", "abc123", "a1b2c3", "aaa111", "123qwe", "qwerty", "qweasd", "admin", "password", "p@ssword", "passwd", "iloveyou", "5201314", "asdfghjkl", "66666666", "88888888"}; boolean hasNext = true; int pageNum = 0; List list = new ArrayList<>(); while (hasNext) { Page page = userRepo.findAll((Specification) (root, query, criteriaBuilder) -> criteriaBuilder.isNotNull(root.get("password")), PageRequest.of(pageNum++, 200, Sort.by("id"))); page.getContent().parallelStream().forEach(user -> { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); boolean match = false; for (String pass : weakPass) { if (encoder.matches(pass, user.getPassword())) { match = true; log.info("检测到弱密码userId={}, pass={}", user.getId(), pass); weakPassRepo.save(new WeakPass(user.getId(), pass)); user.setPassword(null); save(user); redisTemplate.opsForValue().set(RedisKeys.JWT_TOKEN + user.getId(), "1"); break; } } if (match) { list.add(user); } }); hasNext = page.hasNext(); } return list; } public List findInviteOrderByCount(Long collectionId) { redisTemplate.opsForValue().get(RedisKeys.INVITOR_LIST + collectionId); List dtos; dtos = JSONObject.parseArray((String) redisTemplate.opsForValue() .get(RedisKeys.INVITOR_LIST + collectionId), InvitorDTO.class); if (dtos == null) { dtos = new ArrayList<>(); List objects = userRepo.customSearch(collectionId); for (Object[] object : objects) { InvitorDTO invitorDTO = new InvitorDTO((BigInteger) object[0], (String) object[1], (BigInteger) object[2]); dtos.add(invitorDTO); } redisTemplate.opsForValue() .set(RedisKeys.INVITOR_LIST + collectionId, JSONObject.toJSONString(dtos), Duration .ofSeconds(60 * 10)); } return dtos; } public InvitorDetailDTO findMyInviteRecord(Long userId, Long collectionId) { InvitorDetailDTO result = new InvitorDetailDTO(); // if (!SecurityUtils.getAuthenticatedUser().getId().equals(userId)) { // throw new BusinessException("无法查询他人邀请记录"); // } List invitorDTOS = findInviteOrderByCount(collectionId); InvitorDTO dto = invitorDTOS.stream() .filter(invitorDTO -> invitorDTO.getUserId().equals(BigInteger.valueOf(userId))) .findFirst().orElse(null); if (dto != null) { result.setIndex(invitorDTOS.indexOf(dto) + 1); result.setUserId(BigInteger.valueOf(userId)); result.setNickName(dto.getNickName()); if (result.getIndex() != 1) { result.setLastCount(invitorDTOS.get(invitorDTOS.indexOf(dto) - 1).getCount()); } } else { result.setUserId(BigInteger.valueOf(userId)); result.setNickName(SecurityUtils.getAuthenticatedUser().getNickname()); } List invitedUserDTOS = userRepo.findInvitedDTO(collectionId, userId); result.setInvitedUserDTOS(invitedUserDTOS); result.setCount(BigInteger.valueOf(invitedUserDTOS.size())); return result; } public void enableWallet(Long userId) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (user.isWalletEnabled()) { return; } if (!sysConfigService.getBoolean("enable_wallet")) { throw new BusinessException("绿魔卡功能暂未开启"); } IdentityAuth identityAuth = identityAuthRepo.findByUserId(userId).stream().findFirst().orElse(null); if (identityAuth == null) { throw new BusinessException("请先完成实名认证"); } // long age = ChronoUnit.YEARS.between(LocalDate.parse(identityAuth.getIdNo().substring(6, 14), // DateTimeFormatter.ofPattern("yyyyMMdd")), LocalDate.now()); // if (!((age >= 22 && age <= 55))) { // throw new BusinessException("仅22至55周岁藏家可申请绿魔卡"); // } // BigDecimal amount = sysConfigService.getBigDecimal("wallet_enable_amount"); // if (Optional.ofNullable(orderRepo.sumUserPrice(userId)).orElse(BigDecimal.ZERO).compareTo(amount) < 0) { // throw new BusinessException("申请绿魔卡需满" + amount + "绿洲石"); // } user.setWalletEnabled(true); save(user); } public Page companyList(PageQuery pageQuery) { Page users = this.all(pageQuery).toPage(); List> companyNums = showroomRepo.countNum("COMPANY"); Map showroomNum = new HashMap<>(); companyNums.forEach(value -> showroomNum.put(Convert.convert(Long.class, value.get("user_id")), Convert.convert(Integer.class, value.get("num")))); List> companyBoxNums = showroomRepo.countNum("COMPANY_BOX"); Map boxNum = new HashMap<>(); companyBoxNums.forEach(value -> boxNum.put(Convert.convert(Long.class, value.get("user_id")), Convert.convert(Integer.class, value.get("num")))); return users.map(user -> { CompanyDTO dto = new CompanyDTO(user); dto.setShowroomNum(showroomNum.get(user.getId()) == null ? 0 : showroomNum.get(user.getId())); dto.setBoxShowroomNum(boxNum.get(user.getId()) == null ? 0 : boxNum.get(user.getId())); return dto; }); } public Object loginTrading(String phone, String password, String tradeCode) { if (StringUtils.isEmpty(phone)) { throw new BusinessException("手机号错误"); } User user = userRepo.findByPhoneAndDelFalse(phone).orElseThrow(new BusinessException("账号或密码错误")); TradingAccount tradingAccount = tradingAccountRepo.findById(user.getId()) .orElseThrow(new BusinessException("账号或密码错误")); if (StringUtils.isEmpty(user.getPassword())) { throw new BusinessException("账号或密码错误"); } if (StringUtils.isNoneEmpty(user.getPassword()) && !passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("账号或密码错误"); } if (StringUtils.isNoneEmpty(user.getPassword()) && !passwordEncoder.matches(tradeCode, user.getTradeCode())) { throw new BusinessException("支付密码错误"); } Map map = new HashMap<>(); map.put("user", user); map.put("token", jwtTokenUtil.generateToken(JwtUserFactory.create(user))); map.put("account", tradingAccount); return map; } public Object myTrading(Long id) { User user = userRepo.findById(id).orElseThrow(new BusinessException("账号或密码错误")); TradingAccount tradingAccount = tradingAccountRepo.findById(user.getId()) .orElseThrow(new BusinessException("账号或密码错误")); Map map = new HashMap<>(); map.put("user", user); map.put("account", tradingAccount); return map; } public String prepareAliAuth(String type, Long userId, String name, String no) throws AlipayApiException { Long id = snowflakeIdWorker.nextId(); AlipayUserCertifyOpenInitializeRequest request = new AlipayUserCertifyOpenInitializeRequest(); JSONObject biz = new JSONObject(); biz.put("outer_order_no", id + ""); biz.put("biz_code", "FACE"); JSONObject identity_param = new JSONObject(); identity_param.put("identity_type", "CERT_INFO"); identity_param.put("cert_type", type); identity_param.put("cert_name", name); identity_param.put("cert_no", no); biz.put("identity_param", identity_param); JSONObject merchant_config = new JSONObject(); merchant_config.put("return_url", "alipays://platformapi/startapp?appId=20000067&url=" + URLEncoder.encode(generalProperties.getHost() + "/user/faceAuthNotify/" + id, StandardCharsets.UTF_8)); biz.put("merchant_config", merchant_config); log.info(JSON.toJSONString(biz, true)); request.setBizContent(biz.toJSONString()); AlipayUserCertifyOpenInitializeResponse response = alipayClient.execute(request); if (response.isSuccess()) { String certifyId = response.getCertifyId(); faceAuthRepo.save(FaceAuth.builder() .id(id) .userId(userId) .name(name) .idNo(no) .certifyId(certifyId) .build()); return certifyId; } throw new BusinessException(response.getMsg()); } public String getAliAuthUrl(String certify_id) throws AlipayApiException { AlipayUserCertifyOpenCertifyRequest request = new AlipayUserCertifyOpenCertifyRequest(); JSONObject bizContentObj = new JSONObject(); bizContentObj.put("certify_id", certify_id); request.setBizContent(bizContentObj.toString()); AlipayUserCertifyOpenCertifyResponse response = alipayClient.pageExecute(request, "GET"); if (response.isSuccess()) { return response.getBody(); } throw new BusinessException(response.getMsg()); } public User oneKeyLogin(String umengKey, String token) { String phone = UmengUtils.getMobile(umengKey, token); if (StringUtils.isBlank(phone)) { throw new BusinessException("登录失败,请尝试其他方式"); } User user = userRepo.findByPhoneAndDelFalse(phone).orElse(null); if (user == null) { String name = "0x" + RandomStringUtils.randomAlphabetic(8); user = create(UserRegister.builder() .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER))) .username(name) .nickname(name) .avatar(Constants.DEFAULT_AVATAR) .phone(phone) .build()); } return user; } public Map checkFaceAuth(String certifyId) throws AlipayApiException { AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest(); JSONObject biz = new JSONObject(); biz.put("certify_id", certifyId); request.setBizContent(biz.toJSONString()); AlipayUserCertifyOpenQueryResponse response = alipayClient.execute(request); Map map = new HashMap<>(); if (response.isSuccess()) { System.out.println("调用成功"); } else { System.out.println("调用失败"); } return map; } public void faceAuthNotify(Long id) { faceAuthRepo.findById(id).ifPresent(faceAuth -> { try { AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest(); JSONObject biz = new JSONObject(); biz.put("certify_id", faceAuth.getCertifyId()); request.setBizContent(biz.toJSONString()); AlipayUserCertifyOpenQueryResponse response = alipayClient.execute(request); if (response.isSuccess()) { JSONObject res = JSONObject.parseObject(response.getBody()); JSONObject data = res.getJSONObject("alipay_user_certify_open_query_response"); if (StringUtils.equals(data.getString("passed"), "T")) { User user = userRepo.findById(faceAuth.getUserId()).orElse(null); if (user != null) { IdentityAuth identityAuth = identityAuthRepo.save(IdentityAuth.builder() .userId(user.getId()) .idNo(faceAuth.getIdNo()) .realName(faceAuth.getName()) .status(AuthStatus.SUCCESS) .build()); identityAuthRepo.deleteDuplicated(user.getId(), identityAuth.getId()); user.setAuthStatus(AuthStatus.SUCCESS); user.setAuthId(identityAuth.getId()); save(user); } } } } catch (AlipayApiException e) { throw new RuntimeException(e); } }); } public Map oasisInfo(Long userId) { Map map = new HashMap<>(); User user = userRepo.findById(userId).orElseThrow(new BusinessException("未找到用户信息")); map.put("nickName", user.getNickname()); List assets = assetRepo.findAllByOwnerIdAndStatusAndOasisIdNotNull(userId, AssetStatus.NORMAL); List oasisLoginDTOS = new ArrayList<>(); assets.forEach(asset -> { OasisLoginDTO oasisLoginDTO = new OasisLoginDTO(); oasisLoginDTO.setOasisId(asset.getOasisId()); oasisLoginDTO.setAssetId(asset.getId()); oasisLoginDTO.setSource(asset.getStatus().getDescription()); Collection collection = collectionRepo.findFirstByOnShelfAndAssetId(true, asset.getId()); if (collection != null) { oasisLoginDTO.setUrl(generalProperties.getHost() + "/9th/productDetail/" + collection .getId() + "?id=" + collection.getId()); } else { oasisLoginDTO.setUrl("未公开展示"); } Showroom showroom = showroomRepo.findByOasisId(oasisLoginDTO.getOasisId()) .orElseThrow(new BusinessException("无记录 ")); List origin = showCollectionRepo.findAllByShowroomIdOrderBySort(showroom.getId()); List neo = new ArrayList<>(); if (origin != null) { origin.forEach(orig -> collectionRepo.findById(orig.getCollectionId()) .ifPresent(collection1 -> { orig.setStatus(showroomService.getStatus(collection1)); orig.setPrice(collection1.getPrice()); neo.add(orig); })); } showroom.setCollections(neo); User showRoomUser = SecurityUtils.getAuthenticatedUser(); if (showRoomUser != null && !showRoomUser.isAdmin()) { List likes = newsLikeRepo.findByUserIdAndShowroomId(showRoomUser .getId(), showroom.getId()); showroom.setLiked(CollUtil.isNotEmpty(likes)); } oasisLoginDTO.setShowroom(showroom); oasisLoginDTOS.add(oasisLoginDTO); }); map.put("oasisInfo", oasisLoginDTOS); map.put("avatar", SecurityUtils.getAuthenticatedUser().getAvatar()); return map; } /** * 流拍5次直接删号处罚 */ @Scheduled(cron = "0 0/10 * * * ?") public void delUser() { List userIds = auctionPassRecordRepo.checkUserId(); if (CollUtil.isNotEmpty(userIds)) { log.info("流拍处罚:{}", userIds); userRepo.softDeleteIn(userIds); //清缓存 userIds.forEach(id -> { cacheService.clearUserMy(id); cacheService.clearUser(id); }); } } public void noCollectionId(User user) { if (user.getCreatedAt().isBefore(LocalDateTime.of(2022, 7, 5, 0, 0, 0))) { return; } if (user.getVipPoint() < 1) { //有效新用户1个限购 user.setVipPoint(100); userRepo.save(user); cacheService.clearUserMy(user.getId()); cacheService.clearUser(user.getId()); } } public void bindAuctionInvitor(Long userId, Long invitor) { Invite invite = null; InviteType type = InviteType.AUCTION; User inviteUser = userRepo.findById(invitor).orElseThrow(new BusinessException("暂无用户")); invite = inviteRepo.findFirstByCode(String.valueOf(invitor)).orElse(null); if (invite == null) { Invite newOne = new Invite(); newOne.setInviteNum(0); newOne.setPhone(inviteUser.getPhone()); newOne.setCode(String.valueOf(invitor)); newOne.setName(inviteUser.getNickname()); newOne.setInviteType(InviteType.AUCTION); invite = inviteRepo.save(newOne); } User user = userRepo.findById(userId).orElseThrow(new BusinessException("无此用户")); user.setInvitorPhone(Optional.of(invite).map(Invite::getPhone).orElse(null)); user.setInvitorName(Optional.of(invite).map(Invite::getName).orElse(null)); user.setInviteCode(Optional.of(invite).map(Invite::getCode).orElse(null)); user.setCollectionInvitor(invitor); // user.setCollectionId(collectionId) user.setInviteType(type); User orig = userRepo.findById(user.getId()).orElseThrow(new BusinessException("无记录")); ObjUtils.merge(orig, user); orig = save(orig); userRepo.updateAssetMinter(orig.getId()); userRepo.updateAssetOwner(orig.getId()); userRepo.updateCollectionMinter(orig.getId()); userRepo.updateCollectionOwner(orig.getId()); userRepo.updateOrderMinter(orig.getId()); userRepo.updateHistoryFromUser(orig.getId()); userRepo.updateHistoryToUser(orig.getId()); userRepo.updateShowroomToUser(orig.getId()); cacheService.clearCollection(); } }