huangxiao 2 тижнів тому
батько
коміт
3b61452e68

+ 14 - 0
src/main/java/net/mingsoft/tf/wx/WxPeopleAction.java

@@ -34,6 +34,8 @@ import net.mingsoft.tf.wx.dto.ExhibitorInfoResponse;
 import net.mingsoft.tf.wx.dto.GuestRequest;
 import net.mingsoft.tf.wx.dto.WxCustomUserNamePasswordToken;
 import net.mingsoft.tf.wx.dto.WxRegisterRequest;
+import net.mingsoft.tf.wx.util.RealNameCheck;
+import net.mingsoft.tf.wx.util.RealNameResults;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.subject.Subject;
@@ -78,6 +80,10 @@ public class WxPeopleAction extends BaseAction {
     private String appid;
     @Value("${wx.secret}")
     private String secret;
+    @Value("${real.appid}")
+    private String realAppid;
+    @Value("${real.secret}")
+    private String realSecret;
     @Value("${wx.mock:false}")
     private boolean mock;
     /**
@@ -242,6 +248,14 @@ public class WxPeopleAction extends BaseAction {
     @ResponseBody
     public ResultData wxRegister(@RequestBody WxRegisterRequest people, String modelId, HttpServletRequest request, HttpServletResponse response) {
         people.setPeoplePassword(RandomUtil.randomString(8));
+        if (StrUtil.isBlank(people.getPuCard()) || StrUtil.isBlank(people.getPuRealName())) {
+            return ResultData.build().error("身份证和姓名不能为空");
+        }
+        if (RealNameCheck.check(people.getPuCard(), people.getPuRealName(), realAppid, realSecret)
+                .filter(RealNameResults::isSession)
+                .isEmpty()) {
+            return ResultData.build().error("身份证和姓名不一致");
+        }
         ResultData register = peopleAction.register(people, request, response);
         if (register.isSuccess()) {
             PeopleEntity user = this.peopleBiz.getEntityByUserName(people.getPeopleName());

+ 8 - 6
src/main/java/net/mingsoft/tf/wx/gate/GateAction.java

@@ -72,12 +72,14 @@ public class GateAction {
         log.info(message);
         TicketCheckResponse.TicketCheckResponseBuilder builder = TicketCheckResponse.builder()
                 .ticketCode(request.getTicketCode())
-                .code(0)
-                .msg("无效");
-        if (gateService.checkCode(request.getTicketCode())) {
-            browseBiz.addBrowseAdmission();
-            builder.code(1)
-                    .msg("通过");
+                .code(0).msg("无效码");
+        try {
+            if (gateService.checkCode(request.getTicketCode())) {
+                browseBiz.addBrowseAdmission();
+                builder.code(1).msg("通过");
+            }
+        } catch (Exception e) {
+            builder.code(0).msg("错误码");
         }
         return GateResults.<TicketCheckResponse>builder()
                 .Code(200)

+ 80 - 0
src/main/java/net/mingsoft/tf/wx/util/RealNameCheck.java

@@ -0,0 +1,80 @@
+package net.mingsoft.tf.wx.util;
+
+import cn.hutool.core.codec.Base64Encoder;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 实名认证
+ *
+ * @author hx
+ * @date 2026-01-21
+ */
+@Slf4j
+public class RealNameCheck {
+    public static String calcAuthorization(String secretId, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException {
+        Calendar cd = Calendar.getInstance();
+        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
+        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+        String datetime = sdf.format(cd.getTime());
+        String signStr = "x-date: " + datetime;
+        Mac mac = Mac.getInstance("HmacSHA1");
+        Key sKey = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), mac.getAlgorithm());
+        mac.init(sKey);
+        String sig = Base64Encoder.encode(mac.doFinal(signStr.getBytes(StandardCharsets.UTF_8)));
+        return "{\"id\":\"" + secretId + "\", \"x-date\":\"" + datetime + "\", \"signature\":\"" + sig + "\"}";
+    }
+
+    public static String urlencode(Map<?, ?> map) {
+        StringBuilder sb = new StringBuilder();
+        for (Map.Entry<?, ?> entry : map.entrySet()) {
+            if (sb.length() > 0) {
+                sb.append("&");
+            }
+            sb.append(String.format("%s=%s",
+                    URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8),
+                    URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)
+            ));
+        }
+        return sb.toString();
+    }
+
+    public static Optional<RealNameResults> check(String idcard, String name, String secretId, String secretKey) {
+        try (HttpResponse response = HttpUtil.createPost("https://ap-shanghai.cloudmarket-apigw.com/service-isr6xhvr/id_name/check")
+                .header("request-id", UUID.randomUUID().toString())
+                .header("Authorization", calcAuthorization(secretId, secretKey))
+                .form("idcard", idcard)
+                .form("name", name)
+                .execute()) {
+            return Optional.ofNullable(response.body())
+                    .map(JSONObject::new)
+                    .filter(json -> {
+                        if (json.getInt("code") != 200) {
+                            log.warn("身份验证失败 name:{} idcard:{} msg:{}", name, idcard, json.getStr("msg"));
+                            return false;
+                        }
+                        return true;
+                    })
+                    .map(json -> json.getJSONObject("data"))
+                    .map(json -> json.toBean(RealNameResults.class));
+        } catch (Exception e) {
+            log.warn("身份验证异常 name:{} idcard:{}", name, idcard, e);
+            return Optional.empty();
+        }
+    }
+}

+ 44 - 0
src/main/java/net/mingsoft/tf/wx/util/RealNameResults.java

@@ -0,0 +1,44 @@
+package net.mingsoft.tf.wx.util;
+
+import lombok.Data;
+
+/**
+ * 实名结果
+ *
+ * @author hx
+ * @date 2026-01-21
+ */
+@Data
+public class RealNameResults {
+    /**
+     * 1核验一致
+     * <p>
+     * 2核验不一致
+     * <p>
+     * 3库无
+     */
+    private Integer result;
+    /**
+     * 核验结果描述
+     */
+    private String message;
+    /**
+     * 解析身份证生日
+     */
+    private String birthday;
+    /**
+     * 解析身份证性别
+     */
+    private String sex;
+    /**
+     * 解析身份证地区
+     */
+    private String address;
+
+    /**
+     * 是否一致
+     */
+    public boolean isSession() {
+        return result != null && result == 1;
+    }
+}

+ 4 - 1
src/main/resources/application-dev.yml

@@ -11,4 +11,7 @@ spring:
 spring.main.allow-bean-definition-overriding: true
 
 wx.appid: wx0a115eb69d6e9359
-wx.secret: d906c8ca51acfd61e13dd61b62364050
+wx.secret: d906c8ca51acfd61e13dd61b62364050
+
+real.appid: SqPG23vZX5S0XaXW
+real.secret: b8HPby3uinUlxbu7VkR7E3E2zUxHA7sK