Browse Source

完善 wxbase E证通对接开发

frankeleyn 2 years ago
parent
commit
90ac206199

+ 2 - 1
src/main/java/com/ematou/wxbase/aop/LogAspect.java

@@ -39,11 +39,12 @@ public class LogAspect {
             logger.info("----------------方法: " + targetMethodName + "的参数为: " + objectMapper.writeValueAsString(joinPoint.getArgs()) + "----------------");
             proceed = joinPoint.proceed();
             logger.info("----------------方法: " + targetMethodName + "执行的返回值为: " + proceed + "----------------");
-        }catch (ServiceException se){
+        } catch (ServiceException se){
             // 如果时业务异常记录结果,抛出交给统一异常处理
             throw se;
         } catch (Throwable throwable) {
             logger.error("----------------方法: " + targetMethodName + "执行出现异常,错误信息为:" + throwable.getMessage() + "----------------", throwable);
+            throw new ServiceException("系统异常,请稍后再试!");
         }
         return proceed;
     }

+ 16 - 0
src/main/java/com/ematou/wxbase/common/constant/RedisKey.java

@@ -0,0 +1,16 @@
+package com.ematou.wxbase.common.constant;
+
+/**
+ * Redis 缓存键前缀
+ *
+ * @author frankeleyn
+ * @email lvjian@qhdswl.com
+ * @date 2023/2/20 16:38
+ */
+public class RedisKey {
+
+    /**
+     * 获取E证通 token 缓存键前缀
+     */
+    public static final String GET_EID_TOKEN = "get_eid_token:";
+}

+ 1 - 1
src/main/java/com/ematou/wxbase/common/web/R.java

@@ -28,7 +28,7 @@ public class R<T> implements Serializable {
     }
 
     public static <T> R<T> success(T data) {
-        return restResult(data, ResponseCodeConstant.code_200, null);
+        return restResult(data, ResponseCodeConstant.code_200, "成功");
     }
 
     public static <T> R<T> error(String message) {

+ 3 - 12
src/main/java/com/ematou/wxbase/controller/EidController.java

@@ -4,9 +4,7 @@ import com.ematou.wxbase.common.web.R;
 import com.ematou.wxbase.entity.dto.EidTokenRequestDTO;
 import com.ematou.wxbase.service.EidService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * E证通业务 Controller
@@ -22,15 +20,8 @@ public class EidController {
     @Autowired
     private EidService eidService;
 
-    @GetMapping ("/getEidToken")
-    public R getEidToken() {
-        EidTokenRequestDTO requestDTO =
-                EidTokenRequestDTO.builder()
-                        .merchSn("mhbs990053989883052032")
-                        .appCode("Kmall-cw")
-                        .userName("张三")
-                        .idCard("430411196705226476")
-                        .build();
+    @PostMapping("/getEidToken")
+    public R getEidToken(@RequestBody EidTokenRequestDTO requestDTO) {
         return eidService.getEidToken(requestDTO);
     }
 

+ 9 - 0
src/main/java/com/ematou/wxbase/entity/EidTokenRecord.java

@@ -1,6 +1,9 @@
 package com.ematou.wxbase.entity;
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.sql.Timestamp;
 import java.time.LocalDateTime;
@@ -13,13 +16,19 @@ import java.time.LocalDateTime;
  * @date 2023/2/16 16:20
  */
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
 public class EidTokenRecord {
 
     private String id;// 主键
     private String merchSn;// 商户编号
+    private String appCode;// 应用编码
     private String token;// token
     private LocalDateTime generationTime;// 生成时间
     private LocalDateTime expireTime;// 过期时间
+    private String idCard;// 身份证
+    private String userName;// 用户姓名
     private Timestamp tstm;// 时间戳
 
 }

+ 3 - 1
src/main/java/com/ematou/wxbase/entity/dto/EidTokenRequestDTO.java

@@ -5,6 +5,8 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.io.Serializable;
+
 /**
  * E证通请求 DTO
  *
@@ -16,7 +18,7 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 @NoArgsConstructor
 @Builder
-public class EidTokenRequestDTO {
+public class EidTokenRequestDTO implements Serializable {
 
     /**
      * 商户号

+ 38 - 0
src/main/java/com/ematou/wxbase/entity/vo/EidTokenResponseVO.java

@@ -0,0 +1,38 @@
+package com.ematou.wxbase.entity.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * E证通响应 VO
+ *
+ * @author frankeleyn
+ * @email lvjian@qhdswl.com
+ * @date 2023/2/20 14:11
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class EidTokenResponseVO implements Serializable {
+
+    /**
+     * 核验人姓名
+     */
+    private String userName;
+
+    /**
+     * 核验人身份证
+     */
+    private String idCard;
+
+    /**
+     * 核验人E证通 token
+     */
+    private String eidToken;
+
+}

+ 1 - 1
src/main/java/com/ematou/wxbase/handler/GlobalExceptionHandler.java

@@ -26,7 +26,7 @@ public class GlobalExceptionHandler {
     public R handleServiceException(ServiceException e, HttpServletRequest request)
     {
         String requestURI = request.getRequestURI();
-        log.error("请求地址'{}',发生业务异常{}", requestURI, e.getMessage());
+        log.error("请求地址【{}】,发生业务异常【{}】", requestURI, e.getMessage());
         return R.error(e.getMessage());
     }
 

+ 3 - 1
src/main/java/com/ematou/wxbase/service/EidService.java

@@ -2,6 +2,7 @@ package com.ematou.wxbase.service;
 
 import com.ematou.wxbase.common.web.R;
 import com.ematou.wxbase.entity.dto.EidTokenRequestDTO;
+import com.ematou.wxbase.entity.vo.EidTokenResponseVO;
 
 /**
  * E证通业务接口
@@ -16,10 +17,11 @@ public interface EidService {
      * 获取E证通 Token
      * @return
      */
-    R<String> getEidToken(EidTokenRequestDTO requestDTO);
+    R<EidTokenResponseVO> getEidToken(EidTokenRequestDTO requestDTO);
 
     /**
      * 获取E证通结果
      */
     R getEidResult();
+
 }

+ 88 - 19
src/main/java/com/ematou/wxbase/service/impl/EidServiceImpl.java

@@ -1,15 +1,16 @@
 package com.ematou.wxbase.service.impl;
 
+import cn.hutool.core.util.StrUtil;
+import com.ematou.wxbase.common.constant.RedisKey;
 import com.ematou.wxbase.common.constant.TokenType;
 import com.ematou.wxbase.common.web.R;
-import com.ematou.wxbase.entity.EidMerch;
-import com.ematou.wxbase.entity.MerchApp;
-import com.ematou.wxbase.entity.MerchInfo;
-import com.ematou.wxbase.entity.OperationRecord;
+import com.ematou.wxbase.entity.*;
 import com.ematou.wxbase.entity.dto.EidTokenRequestDTO;
+import com.ematou.wxbase.entity.vo.EidTokenResponseVO;
 import com.ematou.wxbase.exception.Assert;
 import com.ematou.wxbase.exception.ServiceException;
 import com.ematou.wxbase.mapper.EidMerchMapper;
+import com.ematou.wxbase.mapper.EidTokenRecordMapper;
 import com.ematou.wxbase.mapper.MerchAppMapper;
 import com.ematou.wxbase.mapper.MerchInfoMapper;
 import com.ematou.wxbase.service.EidService;
@@ -22,11 +23,14 @@ import com.tencentcloudapi.faceid.v20180301.FaceidClient;
 import com.tencentcloudapi.faceid.v20180301.models.GetEidTokenRequest;
 import com.tencentcloudapi.faceid.v20180301.models.GetEidTokenResponse;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.List;
-import java.util.UUID;
 
 /**
  * E证通业务实现类
@@ -51,6 +55,11 @@ public class EidServiceImpl implements EidService {
     @Resource
     private OperationRecordService recordService;
 
+    @Resource
+    private EidTokenRecordMapper eidTokenRecordMapper;
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
 
     /**
      * 获取E证通 Token
@@ -58,7 +67,7 @@ public class EidServiceImpl implements EidService {
      * @return
      */
     @Override
-    public R<String> getEidToken(EidTokenRequestDTO requestDTO) {
+    public R<EidTokenResponseVO> getEidToken(EidTokenRequestDTO requestDTO) {
         // 校验参数
         validateParam(requestDTO);
         // 校验商户
@@ -68,14 +77,43 @@ public class EidServiceImpl implements EidService {
         // 查询E证通商户配置
         EidMerch eidMerch = eidMerchMapper.selectByMerchSn(requestDTO.getMerchSn());
         Assert.notNull(eidMerch, "商户E证通配置不存在!");
-        // 请求E证通 token
-        String eidToken = reqEidToken(eidMerch);
-        // 插入操作记录
-        insertOptRecord(requestDTO);
-        // TODO: 插入E证通 token 记录
 
+        // 响应数据
+        EidTokenResponseVO responseVO =
+                EidTokenResponseVO.builder()
+                        .idCard(requestDTO.getIdCard())
+                        .userName(requestDTO.getUserName())
+                        .build();
 
-        return R.success(null);
+        // 获取E证通缓存键(功能名称:商户号:应用编码:核验人身份证号),例如: get_eid_token:merch123:kmall-pt:431422196503217896
+        String cacheKey =
+                RedisKey.GET_EID_TOKEN +
+                        requestDTO.getMerchSn() + ":" +
+                        requestDTO.getAppCode() + ":" +
+                        requestDTO.getIdCard();
+        // 获取缓存中的 token
+        String cacheEidToken = (String) redisTemplate.opsForValue().get(cacheKey);
+        if (StrUtil.isNotBlank(cacheEidToken)) {
+            // 如果不为空,缓存存在
+            // 将 token 组装到响应数据中
+            responseVO.setEidToken(cacheEidToken);
+        }else {
+            // 如果为空,缓存不存在
+            // 请求E证通 token
+            //String eidToken = reqEidToken(eidMerch, requestDTO.getUserName(), requestDTO.getIdCard());
+            String eidToken = "1a2b3c4d5e6f";
+            // 将E证通 token 设置进 Redis,并设置过期时间
+            redisTemplate.opsForValue().set(cacheKey, eidToken, Duration.ofSeconds(eidMerch.getTokenExpired()));
+            // 插入操作记录
+            insertOptRecord(requestDTO);
+            // 插入E证通操作记录
+            insertEidTokenRecord(requestDTO, eidToken);
+            // 返回结果组装
+            responseVO.setEidToken(eidToken);
+        }
+
+        // 返回结果
+        return R.success(responseVO);
     }
 
 
@@ -127,10 +165,13 @@ public class EidServiceImpl implements EidService {
 
     /**
      * 获取E证通 token
-     * @param eidMerch
+     *
+     * @param eidMerch E证通商户配置
+     * @param userName 核验人姓名
+     * @param idCard 核验人身份证
      * @return
      */
-    private String reqEidToken(EidMerch eidMerch) {
+    private String reqEidToken(EidMerch eidMerch, String userName, String idCard) {
         try {
             // 创建访问凭据
             Credential cred = new Credential(eidMerch.getSecretId(), eidMerch.getSecretKey());
@@ -144,19 +185,23 @@ public class EidServiceImpl implements EidService {
             FaceidClient client = new FaceidClient(cred, "", clientProfile);
             // 实例化一个请求对象,每个接口都会对应一个request对象
             GetEidTokenRequest req = new GetEidTokenRequest();
-
+            // 设置商户 id
+            req.setMerchantId(eidMerch.getMerchId());
+            // 设置核验人姓名
+            req.setName(userName);
+            // 设置核验人身份证
+            req.setIdCard(idCard);
             // 返回的resp是一个GetEidTokenResponse的实例,与请求对象对应
             GetEidTokenResponse resp = client.GetEidToken(req);
             // 输出json格式的字符串回包
-            System.out.println(GetEidTokenResponse.toJsonString(resp));
+            log.info("E证通返回结果: " + GetEidTokenResponse.toJsonString(resp));
             // 获取 EidToken
             String eidToken = resp.getEidToken();
-            eidToken = UUID.randomUUID().toString().replace("-", "");
             // 返回 token
             return eidToken;
         } catch (TencentCloudSDKException e) {
-            log.error("腾讯云 SDK 人脸核验异常.", e);
-            throw new ServiceException("人脸核验异常!");
+            log.error("腾讯云 SDK 请求E证通 token 异常.", e);
+            throw new ServiceException("请求E证通异常!");
         }
 
     }
@@ -177,4 +222,28 @@ public class EidServiceImpl implements EidService {
         recordService.insertRecord(operationRecord);
     }
 
+    /**
+     * 插入E证通 token 记录
+     *
+     * @param requestDTO
+     * @param eidToken
+     */
+    private void insertEidTokenRecord(EidTokenRequestDTO requestDTO, String eidToken) {
+        // token 生成时间
+        LocalDateTime generationTime = LocalDateTime.now();
+        // 过期时间, 生成时间 + 60s
+        LocalDateTime expireTime = generationTime.plusMinutes(8L);
+        EidTokenRecord eidTokenRecord = EidTokenRecord.builder()
+                .merchSn(requestDTO.getMerchSn())
+                .appCode(requestDTO.getAppCode())
+                .token(eidToken)
+                .generationTime(generationTime)
+                .expireTime(expireTime)
+                .idCard(requestDTO.getIdCard())
+                .userName(requestDTO.getUserName())
+                .build();
+        int insert = eidTokenRecordMapper.insert(eidTokenRecord);
+        Assert.notTrue(insert < 1, "插入E证通 token 记录失败!");
+    }
+
 }

+ 25 - 0
src/main/resources/mybatis/EidMerchMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ematou.wxbase.mapper.EidMerchMapper">
+
+    <sql id="eidMerchColumns">
+        t.id,
+        t.merch_sn,
+        t.secret_id,
+        t.secret_key,
+        t.merch_id,
+        t.token_expired
+    </sql>
+
+    <!-- 根据商户号查询商户E证通配置信息 -->
+    <select id="selectByMerchSn" resultType="com.ematou.wxbase.entity.EidMerch">
+        SELECT
+            <include refid="eidMerchColumns" />
+        FROM
+            `eid_merch` t
+        WHERE t.merch_sn = #{merchSn};
+    </select>
+
+</mapper>

+ 10 - 1
src/test/java/com/ematou/wxbase/RedisTest.java

@@ -1,10 +1,13 @@
 package com.ematou.wxbase;
 
+import cn.hutool.core.util.StrUtil;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.redis.core.RedisTemplate;
 
+import java.time.Duration;
+
 /**
  * Redis 测试类
  *
@@ -20,7 +23,7 @@ public class RedisTest {
 
     @Test
     public void testSet() {
-        redisTemplate.opsForValue().set("wcq", "1234556");
+        redisTemplate.opsForValue().set("get_eid_token:merch123:kmall-pt:431422196503217896", "1234556", Duration.ofSeconds(60L));
     }
 
     @Test
@@ -28,4 +31,10 @@ public class RedisTest {
         redisTemplate.delete("lj_hh");
     }
 
+    @Test
+    public void testGet() {
+        String o = (String) redisTemplate.opsForValue().get("get_eid_token:merch123:kmall-pt:431422196503217896");
+        System.out.println("Redis 取值 => " + o + " 是否为空 =》 " + StrUtil.isNotBlank(o));
+    }
+
 }