package com.izouma.nineth.service; import com.alibaba.fastjson.JSONObject; import com.github.kevinsawicki.http.HttpRequest; import com.izouma.nineth.annotations.RedisLock; import com.izouma.nineth.domain.IdentityAuth; import com.izouma.nineth.domain.User; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.enums.AuthStatus; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.IdentityAuthRepo; import com.izouma.nineth.repo.UserRepo; import com.izouma.nineth.utils.DateTimeUtils; import com.izouma.nineth.utils.JpaUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.env.Environment; import org.springframework.data.domain.Page; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import java.util.stream.Collectors; @Service @AllArgsConstructor @Slf4j public class IdentityAuthService { private IdentityAuthRepo identityAuthRepo; private UserRepo userRepo; private AdapayService adapayService; private RedisTemplate redisTemplate; private Environment env; private SysConfigService sysConfigService; public Page all(PageQuery pageQuery) { return identityAuthRepo.findAll(JpaUtils.toSpecification(pageQuery, IdentityAuth.class), JpaUtils.toPageRequest(pageQuery)); } public void apply(IdentityAuth identityAuth) { if (identityAuth.getUserId() == null) { throw new BusinessException("用户不存在"); } User user = userRepo.findByIdAndDelFalse(identityAuth.getUserId()).orElseThrow(new BusinessException("用户不存在")); List auths = identityAuthRepo.findByUserIdAndDelFalse(identityAuth.getUserId()); auths.stream().filter(auth -> auth.getStatus() == AuthStatus.PENDING).findAny().ifPresent(a -> { throw new BusinessException("正在审核中,请勿重复提交"); }); auths.stream().filter(auth -> auth.getStatus() == AuthStatus.SUCCESS).findAny().ifPresent(a -> { throw new BusinessException("已认证,请勿重复提交"); }); identityAuth.setStatus(AuthStatus.PENDING); identityAuthRepo.save(identityAuth); user.setAuthStatus(AuthStatus.PENDING); userRepo.save(user); } public void audit(Long id, AuthStatus status, String reason) { IdentityAuth auth = identityAuthRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("申请不存在")); if (auth.getStatus() != AuthStatus.PENDING) { throw new BusinessException("已经审核过"); } User user = userRepo.findByIdAndDelFalse(auth.getUserId()).orElseThrow(new BusinessException("用户不存在")); if (status == AuthStatus.SUCCESS) { user.setAuthId(auth.getId()); } auth.setStatus(status); auth.setReason(reason); auth.setAutoValidated(true); identityAuthRepo.save(auth); user.setAuthStatus(status); userRepo.save(user); } public List repeat(String idNo, Long userId) { List auths = identityAuthRepo.findAllByIdNoAndUserIdIsNotAndDelFalse(idNo, userId); if (auths.isEmpty()) { return null; } List userIds = auths.stream().map(IdentityAuth::getUserId).distinct().collect(Collectors.toList()); return userRepo.findByIdInAndDelFalse(userIds); } public void validate(String name, String phone, String idno) { String body = HttpRequest.post("https://jubrige.market.alicloudapi.com/mobile/3-validate-transfer") .header("Authorization", "APPCODE b48bc8f6759345a79ae20a951f03dabe") .contentType(HttpRequest.CONTENT_TYPE_FORM) .form("idCardNo", idno) .form("mobile", phone) .form("name", name) .body(); JSONObject jsonObject = JSONObject.parseObject(body); if (jsonObject.getInteger("code") != 200) { String msg = jsonObject.getString("msg"); throw new BusinessException(msg); } else { JSONObject data = jsonObject.getJSONObject("data"); int result = data.getIntValue("result"); String desc = data.getString("desc"); if (result != 0) { throw new BusinessException(desc); } else { log.info("{} {} {} 实名认证通过", name, phone, idno); } } } @Scheduled(fixedRate = 60000) @RedisLock(value = "autoValidate", expire = 30, unit = TimeUnit.MINUTES) public void autoValidate() { if (!sysConfigService.getBoolean("auto_validate")) return; log.info("autoValidate"); if (Arrays.asList(env.getActiveProfiles()).contains("dev")) { return; } try { List list = identityAuthRepo.findByStatusAndAutoValidated(AuthStatus.PENDING, false); list.parallelStream().forEach(identityAuth -> { boolean success = false; String reason = null; if (!Pattern.matches("[1-9]{1}[0-9]{5}(19|20)[0-9]{2}((0[1-9]{1})|(1[0-2]{1}))((0[1-9]{1})|([1-2]{1}[0-9]{1}|(3[0-1]{1})))[0-9]{3}[0-9x]{1}", identityAuth.getIdNo().toLowerCase())) { audit(identityAuth.getId(), AuthStatus.FAIL, "身份证格式错误"); return; } else { LocalDate birth = DateTimeUtils.toLocalDate(identityAuth.getIdNo().substring(6, 14), "yyyyMMdd"); long age = ChronoUnit.YEARS.between(birth, LocalDate.now()); if (age < 18) { audit(identityAuth.getId(), AuthStatus.FAIL, "未满18岁"); return; } else if (age > 60) { audit(identityAuth.getId(), AuthStatus.FAIL, "超过60岁"); return; } } int count = identityAuthRepo.countByIdNoAndStatus(identityAuth.getIdNo(), AuthStatus.SUCCESS); if (count >= 3) { success = false; reason = "同一身份证注册超过3个"; } else { try { User user = userRepo.findById(identityAuth.getUserId()) .orElseThrow(new BusinessException("用户不存在")); validate(identityAuth.getRealName(), user.getPhone(), identityAuth.getIdNo()); success = true; } catch (Exception e) { reason = e.getMessage(); } } audit(identityAuth.getId(), success ? AuthStatus.SUCCESS : AuthStatus.PENDING, reason); }); } catch (Exception ignored) { } } }