IdentityAuthService.java 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package com.izouma.nineth.service;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.github.kevinsawicki.http.HttpRequest;
  4. import com.izouma.nineth.annotations.RedisLock;
  5. import com.izouma.nineth.domain.IdentityAuth;
  6. import com.izouma.nineth.domain.User;
  7. import com.izouma.nineth.dto.PageQuery;
  8. import com.izouma.nineth.enums.AuthStatus;
  9. import com.izouma.nineth.exception.BusinessException;
  10. import com.izouma.nineth.repo.IdentityAuthRepo;
  11. import com.izouma.nineth.repo.UserRepo;
  12. import com.izouma.nineth.utils.DateTimeUtils;
  13. import com.izouma.nineth.utils.JpaUtils;
  14. import lombok.AllArgsConstructor;
  15. import lombok.extern.slf4j.Slf4j;
  16. import org.springframework.core.env.Environment;
  17. import org.springframework.data.domain.Page;
  18. import org.springframework.data.redis.core.RedisTemplate;
  19. import org.springframework.scheduling.annotation.Scheduled;
  20. import org.springframework.stereotype.Service;
  21. import java.time.LocalDate;
  22. import java.time.temporal.ChronoUnit;
  23. import java.util.Arrays;
  24. import java.util.List;
  25. import java.util.concurrent.TimeUnit;
  26. import java.util.regex.Pattern;
  27. import java.util.stream.Collectors;
  28. @Service
  29. @AllArgsConstructor
  30. @Slf4j
  31. public class IdentityAuthService {
  32. private IdentityAuthRepo identityAuthRepo;
  33. private UserRepo userRepo;
  34. private AdapayService adapayService;
  35. private RedisTemplate<String, Object> redisTemplate;
  36. private Environment env;
  37. private SysConfigService sysConfigService;
  38. public Page<IdentityAuth> all(PageQuery pageQuery) {
  39. return identityAuthRepo.findAll(JpaUtils.toSpecification(pageQuery, IdentityAuth.class), JpaUtils.toPageRequest(pageQuery));
  40. }
  41. public void apply(IdentityAuth identityAuth) {
  42. if (identityAuth.getUserId() == null) {
  43. throw new BusinessException("用户不存在");
  44. }
  45. User user = userRepo.findByIdAndDelFalse(identityAuth.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  46. List<IdentityAuth> auths = identityAuthRepo.findByUserIdAndDelFalse(identityAuth.getUserId());
  47. auths.stream().filter(auth -> auth.getStatus() == AuthStatus.PENDING).findAny().ifPresent(a -> {
  48. throw new BusinessException("正在审核中,请勿重复提交");
  49. });
  50. auths.stream().filter(auth -> auth.getStatus() == AuthStatus.SUCCESS).findAny().ifPresent(a -> {
  51. throw new BusinessException("已认证,请勿重复提交");
  52. });
  53. identityAuth.setStatus(AuthStatus.PENDING);
  54. identityAuthRepo.save(identityAuth);
  55. user.setAuthStatus(AuthStatus.PENDING);
  56. userRepo.save(user);
  57. }
  58. public void audit(Long id, AuthStatus status, String reason) {
  59. IdentityAuth auth = identityAuthRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("申请不存在"));
  60. if (auth.getStatus() != AuthStatus.PENDING) {
  61. throw new BusinessException("已经审核过");
  62. }
  63. User user = userRepo.findByIdAndDelFalse(auth.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  64. if (user.getAuthStatus() != AuthStatus.SUCCESS) {
  65. if (status == AuthStatus.SUCCESS) {
  66. user.setAuthId(auth.getId());
  67. }
  68. user.setAuthStatus(status);
  69. userRepo.save(user);
  70. }
  71. auth.setStatus(status);
  72. auth.setReason(reason);
  73. auth.setAutoValidated(true);
  74. identityAuthRepo.save(auth);
  75. }
  76. public List<User> repeat(String idNo, Long userId) {
  77. List<IdentityAuth> auths = identityAuthRepo.findAllByIdNoAndUserIdIsNotAndDelFalse(idNo, userId);
  78. if (auths.isEmpty()) {
  79. return null;
  80. }
  81. List<Long> userIds = auths.stream().map(IdentityAuth::getUserId).distinct().collect(Collectors.toList());
  82. return userRepo.findByIdInAndDelFalse(userIds);
  83. }
  84. public void validate(String name, String phone, String idno) {
  85. String body = HttpRequest.post("https://jubrige.market.alicloudapi.com/mobile/3-validate-transfer")
  86. .header("Authorization", "APPCODE b48bc8f6759345a79ae20a951f03dabe")
  87. .contentType(HttpRequest.CONTENT_TYPE_FORM)
  88. .form("idCardNo", idno)
  89. .form("mobile", phone)
  90. .form("name", name)
  91. .body();
  92. JSONObject jsonObject = JSONObject.parseObject(body);
  93. if (jsonObject.getInteger("code") != 200) {
  94. String msg = jsonObject.getString("msg");
  95. throw new BusinessException(msg);
  96. } else {
  97. JSONObject data = jsonObject.getJSONObject("data");
  98. int result = data.getIntValue("result");
  99. String desc = data.getString("desc");
  100. if (result != 0) {
  101. throw new BusinessException(desc);
  102. } else {
  103. log.info("{} {} {} 实名认证通过", name, phone, idno);
  104. }
  105. }
  106. }
  107. @Scheduled(fixedRate = 60000)
  108. @RedisLock(value = "autoValidate", expire = 30, unit = TimeUnit.MINUTES)
  109. public void autoValidate() {
  110. if (!sysConfigService.getBoolean("auto_validate")) return;
  111. log.info("autoValidate");
  112. if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
  113. return;
  114. }
  115. try {
  116. List<IdentityAuth> list = identityAuthRepo.findByStatusAndAutoValidated(AuthStatus.PENDING, false);
  117. list.parallelStream().forEach(identityAuth -> {
  118. boolean success = false;
  119. String reason = null;
  120. User user = userRepo.findById(identityAuth.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  121. if (user.getAuthStatus() == AuthStatus.SUCCESS) {
  122. audit(identityAuth.getId(), AuthStatus.SUCCESS, null);
  123. return;
  124. }
  125. 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()
  126. .toLowerCase())) {
  127. audit(identityAuth.getId(), AuthStatus.FAIL, "身份证格式错误");
  128. return;
  129. } else {
  130. LocalDate birth = DateTimeUtils.toLocalDate(identityAuth.getIdNo().substring(6, 14), "yyyyMMdd");
  131. long age = ChronoUnit.YEARS.between(birth, LocalDate.now());
  132. if (age < 18) {
  133. audit(identityAuth.getId(), AuthStatus.FAIL, "未满18岁");
  134. return;
  135. } else if (age > 60) {
  136. audit(identityAuth.getId(), AuthStatus.FAIL, "超过60岁");
  137. return;
  138. }
  139. }
  140. int count = identityAuthRepo.countByIdNoAndStatus(identityAuth.getIdNo(), AuthStatus.SUCCESS);
  141. if (count >= 3) {
  142. success = false;
  143. reason = "同一身份证注册超过3个";
  144. } else {
  145. try {
  146. validate(identityAuth.getRealName(), user.getPhone(), identityAuth.getIdNo());
  147. success = true;
  148. } catch (Exception e) {
  149. reason = e.getMessage();
  150. }
  151. }
  152. audit(identityAuth.getId(), success ? AuthStatus.SUCCESS : AuthStatus.PENDING, reason);
  153. });
  154. } catch (Exception ignored) {
  155. }
  156. }
  157. }