Procházet zdrojové kódy

fix:景区预约接口调用签名;本地MOCK模拟测试数据待删除

lileilei před 2 roky
rodič
revize
9b21f0e851

+ 1 - 1
health-code.iml

@@ -112,7 +112,7 @@
     <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
     <orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.10.0" level="project" />
     <orderEntry type="library" name="Maven: com.squareup.okio:okio:1.14.0" level="project" />
-    <orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.3.9" level="project" />
+    <orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.7.0" level="project" />
     <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.60" level="project" />
     <orderEntry type="library" name="Maven: com.github.binarywang:weixin-java-miniapp:4.0.7.B" level="project" />
     <orderEntry type="library" name="Maven: com.github.binarywang:weixin-java-common:4.0.7.B" level="project" />

+ 1 - 1
pom.xml

@@ -154,7 +154,7 @@
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
-            <version>5.3.9</version>
+            <version>5.7.0</version>
         </dependency>
 
         <dependency>

+ 53 - 0
src/main/java/com/yixin/ms/boot/config/properties/ScenicProperties.java

@@ -0,0 +1,53 @@
+package com.yixin.ms.boot.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+/**
+ * @description: WxMaProperties <br>
+ * @date: 2021/4/13 10:18 <br>
+ * @author: PWB <br>
+ */
+@Configuration
+@Data
+@ConfigurationProperties(prefix = "scenic")
+public class ScenicProperties {
+    /**
+     * 根据预约码或者身份证查询是否预约
+     */
+    private String verifyUrl;
+
+    /**
+     * 根据预约码查询姓名、证件信息
+     */
+    private String queryUrl;
+
+    /**
+     * 游客放行推送
+     */
+    private String consumeUrl;
+
+    private List<Config> configs;
+
+    @Data
+    public static class Config {
+        /**
+         * 账号id
+         */
+        private Integer adminId;
+
+        /**
+         * 三方账号id
+         */
+        private String account;
+
+        /**
+         * 三方key
+         */
+        private String key;
+    }
+
+}

+ 19 - 0
src/main/java/com/yixin/ms/model/dto/HealthMockDTO.java

@@ -0,0 +1,19 @@
+package com.yixin.ms.model.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author: lileilei
+ * @date: 2022/8/18 11:23
+ * @description:
+ */
+@Data
+@Accessors(chain = true)
+public class HealthMockDTO {
+    private Integer index;
+
+    private String mzt;
+
+    private Integer nucleicExpirationTime;
+}

+ 29 - 18
src/main/java/com/yixin/ms/server/IrsTripServer.java

@@ -15,6 +15,7 @@ import com.yixin.ms.server.dto.IrsSendMsgDTO;
 import com.yixin.ms.server.vo.IrsTripResultVO;
 import com.yixin.ms.server.vo.IrsTripTokenVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.Md5Crypt;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpEntity;
@@ -176,24 +177,34 @@ public class IrsTripServer {
     }
 
     public static void main(String[] args) {
-        String appKey = "A330104242107202107000001", appSecret = "9a92d8b9d41f41729ab8ccbfaa547f12";
-        String requestTime = String.valueOf(System.currentTimeMillis());
-        System.out.println(requestTime);
-        String dateTime = DateUtil.formatDateTime(DateUtil.date(Long.valueOf(requestTime)));
-        System.out.println(dateTime);
-        String sign = SecureUtil.md5(appKey + appSecret + requestTime).toLowerCase();
-        System.out.println("获取token: " + sign);
-        sign = SecureUtil.md5(appKey + "bea7eb8906e14ea7a620f9ab7846db8f" + requestTime).toLowerCase();
-        System.out.println("刷新token: "+ sign);
-        //bbf754f8d3134d7292b7f363f20f533a
-        sign = SecureUtil.md5(appKey + "048755972cd24e1a9dca21dc6aac70cc" + requestTime).toLowerCase();
-        System.out.println(sign);
-        String secret = SecureUtil.md5("9@nr!#G8*Kuw" + dateTime);
-        System.out.println(secret);
-        System.out.println(RandomUtil.randomString(32));
-        System.out.println("#############################");
-        String pwd = SecureUtil.md5("admin@123" + "hh_f03920fbc2512e12" + "1659354702").toLowerCase();
-        System.out.println(pwd);
+//        String appKey = "A330104242107202107000001", appSecret = "9a92d8b9d41f41729ab8ccbfaa547f12";
+//        String requestTime = String.valueOf(System.currentTimeMillis());
+//        System.out.println(requestTime);
+//        String dateTime = DateUtil.formatDateTime(DateUtil.date(Long.valueOf(requestTime)));
+//        System.out.println(dateTime);
+//        String sign = SecureUtil.md5(appKey + appSecret + requestTime).toLowerCase();
+//        System.out.println("获取token: " + sign);
+//        sign = SecureUtil.md5(appKey + "bea7eb8906e14ea7a620f9ab7846db8f" + requestTime).toLowerCase();
+//        System.out.println("刷新token: "+ sign);
+//        //bbf754f8d3134d7292b7f363f20f533a
+//        sign = SecureUtil.md5(appKey + "048755972cd24e1a9dca21dc6aac70cc" + requestTime).toLowerCase();
+//        System.out.println(sign);
+//        String secret = SecureUtil.md5("9@nr!#G8*Kuw" + dateTime);
+//        System.out.println(secret);
+//        System.out.println(RandomUtil.randomString(32));
+//        System.out.println("#############################");
+//        String pwd = SecureUtil.md5("admin@123" + "hh_f03920fbc2512e12" + "1659354702").toLowerCase();
+//        System.out.println(pwd);
+        String str = "{\"account\":\"1510813918447009792\",\"idNumber\":\"456\",\"reservationCode\":\"123\",\"timestamp\":\"1660717723806\"}74d9aed80d7a4c7181ba9615fae0fc11";
+        String signStr = SecureUtil.md5(str);
+        System.out.println(signStr);
+
+        String rt = String.valueOf(System.currentTimeMillis());
+
+        String ak = "83d9174a3e614cf4bb95767551dd7ec6", sk = "fca0ee49199347f793e54175090193e6";
+        String sn = SecureUtil.md5(ak+sk+rt);
+        System.out.println(rt);
+        System.out.println(sn);
     }
 
 }

+ 38 - 13
src/main/java/com/yixin/ms/server/ScenicServer.java

@@ -1,15 +1,24 @@
 package com.yixin.ms.server;
 
+import cn.hutool.crypto.SecureUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
+import com.yixin.ms.boot.config.properties.ScenicProperties;
+import com.yixin.ms.boot.restful.ServiceException;
 import com.yixin.ms.server.dto.ScenicConsumeDTO;
 import com.yixin.ms.server.dto.ScenicVerifyDTO;
 import com.yixin.ms.server.vo.ScenicConsumeVO;
 import com.yixin.ms.server.vo.ScenicVerifyVO;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
+import java.security.Security;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 /**
  * @author: lileilei
  * @date: 2022/8/3 17:37
@@ -18,22 +27,28 @@ import org.springframework.stereotype.Component;
 @Slf4j
 @Component
 public class ScenicServer {
-    @Value("${scenic.verifyUrl}")
-    private String verifyUrl;
-
-    @Value("${scenic.queryUrl}")
-    private String queryUrl;
-
-    @Value("${scenic.consumeUrl}")
-    private String consumeUrl;
+    @Autowired
+    private ScenicProperties scenicProperties;
 
     /**
      * 根据预约码或者身份证查询是否预约
      * @param dto
      * @return
      */
-    public ScenicVerifyVO verify(ScenicVerifyDTO dto) {
-        ScenicVerifyVO verifyVO = JSON.parseObject(HttpUtil.post(verifyUrl, JSON.toJSONString(dto)), ScenicVerifyVO.class);
+    public ScenicVerifyVO verify(ScenicVerifyDTO dto, Integer adminId) {
+        List<ScenicProperties.Config> configs = scenicProperties.getConfigs();
+        Map<Integer, ScenicProperties.Config> configMap = configs.stream().collect(Collectors.toMap(ScenicProperties.Config::getAdminId, v -> v, (v1, v2) -> v1));
+        ScenicProperties.Config config = configMap.get(adminId);
+        if(!config.getAdminId().equals(adminId)){
+            throw new ServiceException("景区预约账号未配置,请检查");
+        }
+
+        dto.setTimestamp(String.valueOf(System.currentTimeMillis())).setAccount(config.getAccount());
+        //签名
+        dto.setSign(SecureUtil.md5(new StringBuilder().append(JSON.toJSONString(dto)).append(config.getKey()).toString()));
+        String body = HttpUtil.post(scenicProperties.getVerifyUrl(), JSON.toJSONString(dto));
+        log.info("根据预约码或者身份证查询是否预约,入参信息:{}, 响应信息:{}", JSON.toJSONString(dto),  body);
+        ScenicVerifyVO verifyVO = JSON.parseObject(body, ScenicVerifyVO.class);
         return verifyVO;
     }
 
@@ -42,9 +57,19 @@ public class ScenicServer {
      * @param dto
      * @return
      */
-    public ScenicConsumeVO consume(ScenicConsumeDTO dto){
-        String body = HttpUtil.post(consumeUrl, JSON.toJSONString(dto));
+    public ScenicConsumeVO consume(ScenicConsumeDTO dto, Integer adminId){
+        List<ScenicProperties.Config> configs = scenicProperties.getConfigs();
+        Map<Integer, ScenicProperties.Config> configMap = configs.stream().collect(Collectors.toMap(ScenicProperties.Config::getAdminId, v -> v, (v1, v2) -> v1));
+        ScenicProperties.Config config = configMap.get(adminId);
+        if(!config.getAdminId().equals(adminId)){
+            throw new ServiceException("景区预约账号未配置,请检查");
+        }
+
+        dto.setTimestamp(String.valueOf(System.currentTimeMillis())).setAccount(config.getAccount());
+        //签名
+        dto.setSign(SecureUtil.md5(new StringBuilder().append(JSON.toJSONString(dto)).append(config.getKey()).toString()));
+        String body = HttpUtil.post(scenicProperties.getConsumeUrl(), JSON.toJSONString(dto));
         log.info("游客放行入参信息:{}, 推送响应内容:{}", JSON.toJSONString(dto), body);
-        return JSON.parseObject(HttpUtil.post(consumeUrl, JSON.toJSONString(dto)), ScenicConsumeVO.class);
+        return JSON.parseObject(body, ScenicConsumeVO.class);
     }
 }

+ 8 - 0
src/main/java/com/yixin/ms/server/dto/ScenicConsumeDTO.java

@@ -1,5 +1,6 @@
 package com.yixin.ms.server.dto;
 
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import lombok.Data;
 import lombok.experimental.Accessors;
 
@@ -10,6 +11,7 @@ import lombok.experimental.Accessors;
  */
 @Data
 @Accessors(chain = true)
+@JsonPropertyOrder(value = "a,i,r,s,t")
 public class ScenicConsumeDTO {
     /**
      * 身份证
@@ -20,4 +22,10 @@ public class ScenicConsumeDTO {
      * 预约码
      */
     private String reservationCode;
+
+    private String account;
+
+    private String timestamp;
+
+    private String sign;
 }

+ 8 - 5
src/main/java/com/yixin/ms/server/dto/ScenicVerifyDTO.java

@@ -1,5 +1,7 @@
 package com.yixin.ms.server.dto;
 
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import lombok.Data;
 import lombok.experimental.Accessors;
 
@@ -10,19 +12,20 @@ import lombok.experimental.Accessors;
  */
 @Data
 @Accessors(chain = true)
+@JsonPropertyOrder(value = "a,i,r,s,t")
 public class ScenicVerifyDTO {
     /**
      * 身份证
      */
     private String idNumber;
-
     /**
      * 预约码
      */
     private String reservationCode;
 
-    /**
-     * 行为参数 1-入园
-     */
-    private String actionType;
+    private String account;
+
+    private String timestamp;
+
+    private String sign;
 }

+ 45 - 5
src/main/java/com/yixin/ms/service/impl/HealthCodeServiceImpl.java

@@ -4,7 +4,9 @@ import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.DesensitizedUtil;
 import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.excel.util.CollectionUtils;
@@ -20,6 +22,7 @@ import com.yixin.ms.boot.uitls.OkHttpUtils;
 import com.yixin.ms.boot.uitls.RedisUtil;
 import com.yixin.ms.boot.uitls.SMSOrIdCardUtils;
 import com.yixin.ms.model.dto.HealthCodeDTO;
+import com.yixin.ms.model.dto.HealthMockDTO;
 import com.yixin.ms.model.dto.ShortTermDTO;
 import com.yixin.ms.model.enums.*;
 import com.yixin.ms.model.vo.HealtCodeNucleinVO;
@@ -58,6 +61,29 @@ public class HealthCodeServiceImpl implements HealthCodeService {
     private ScenicServer scenicServer;
     @Autowired
     private Executor executor;
+    //顺序
+    private static Integer index = 0;
+    private static List<HealthMockDTO> mockDTOList = Lists.newArrayList();
+
+    static {
+        if (CollectionUtil.isEmpty(mockDTOList)) {
+            mockDTOList.add(new HealthMockDTO().setIndex(0).setMzt("绿码").setNucleicExpirationTime(0));
+            mockDTOList.add(new HealthMockDTO().setIndex(1).setMzt("绿码").setNucleicExpirationTime(24));
+            mockDTOList.add(new HealthMockDTO().setIndex(2).setMzt("绿码").setNucleicExpirationTime(48));
+            mockDTOList.add(new HealthMockDTO().setIndex(3).setMzt("绿码").setNucleicExpirationTime(72));
+            mockDTOList.add(new HealthMockDTO().setIndex(4).setMzt("绿码").setNucleicExpirationTime(168));
+            mockDTOList.add(new HealthMockDTO().setIndex(5).setMzt("黄码").setNucleicExpirationTime(0));
+            mockDTOList.add(new HealthMockDTO().setIndex(6).setMzt("黄码").setNucleicExpirationTime(24));
+            mockDTOList.add(new HealthMockDTO().setIndex(7).setMzt("黄码").setNucleicExpirationTime(48));
+            mockDTOList.add(new HealthMockDTO().setIndex(8).setMzt("黄码").setNucleicExpirationTime(72));
+            mockDTOList.add(new HealthMockDTO().setIndex(9).setMzt("黄码").setNucleicExpirationTime(168));
+            mockDTOList.add(new HealthMockDTO().setIndex(10).setMzt("红码").setNucleicExpirationTime(0));
+            mockDTOList.add(new HealthMockDTO().setIndex(11).setMzt("红码").setNucleicExpirationTime(24));
+            mockDTOList.add(new HealthMockDTO().setIndex(12).setMzt("红码").setNucleicExpirationTime(48));
+            mockDTOList.add(new HealthMockDTO().setIndex(13).setMzt("红码").setNucleicExpirationTime(72));
+            mockDTOList.add(new HealthMockDTO().setIndex(14).setMzt("红码").setNucleicExpirationTime(168));
+        }
+    }
 
     @Override
     public HealtCodeUserVO getShortTermCertificate(ShortTermDTO shortTermDTO) {
@@ -151,7 +177,7 @@ public class HealthCodeServiceImpl implements HealthCodeService {
                 HealthResultVO<DeviceScanIdCardVO> scanIdCardResult = null;
                 if (StrUtil.isNotEmpty(shortTermDTO.getHealthCode())) {
                     if (placeInfoVO.getScenicFlag() && NumberUtil.isNumber(shortTermDTO.getHealthCode())) {
-                        ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setReservationCode(shortTermDTO.getHealthCode()));
+                        ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setReservationCode(shortTermDTO.getHealthCode()), placeInfoVO.getAdminId());
                         if (!verifyVO.getReleaseStatus()) {
                             throw new ServiceException(verifyVO.getMessage());
                         } else {
@@ -166,8 +192,8 @@ public class HealthCodeServiceImpl implements HealthCodeService {
                             healthCodeVO = restResult.getData();
                         }
 
-                        if(healthCodeVO != null){
-                            ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setIdNumber(healthCodeVO.getIdNum()));
+                        if (healthCodeVO != null) {
+                            ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setIdNumber(healthCodeVO.getIdNum()), placeInfoVO.getAdminId());
                             if (!verifyVO.getReleaseStatus()) {
                                 throw new ServiceException(verifyVO.getMessage());
                             }
@@ -179,7 +205,7 @@ public class HealthCodeServiceImpl implements HealthCodeService {
                     }
                 } else {
                     if (placeInfoVO.getScenicFlag()) {
-                        ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setIdNumber(shortTermDTO.getIdNumber()));
+                        ScenicVerifyVO verifyVO = scenicServer.verify(new ScenicVerifyDTO().setIdNumber(shortTermDTO.getIdNumber()), placeInfoVO.getAdminId());
                         if (!verifyVO.getReleaseStatus()) {
                             throw new ServiceException(verifyVO.getMessage());
                         }
@@ -237,6 +263,10 @@ public class HealthCodeServiceImpl implements HealthCodeService {
             userVO.setUsername(StrUtil.isEmpty(userVO.getUsername()) ? shortTermDTO.getName() : userVO.getUsername());
             //身份证号
             userVO.setIdNumber(StrUtil.isEmpty(userVO.getIdNumber()) ? shortTermDTO.getIdNumber() : userVO.getIdNumber());
+
+            //姓名和身份证号脱敏处理
+            userVO.setUsername(StrUtil.isEmpty(userVO.getUsername()) ? StrUtil.EMPTY : DesensitizedUtil.chineseName(userVO.getUsername()));
+            userVO.setIdNumber(StrUtil.isEmpty(userVO.getIdNumber()) ? StrUtil.EMPTY : DesensitizedUtil.idCardNum(userVO.getIdNumber(), 4, 4));
             /**
              * 0 未接种 对应0针
              *
@@ -256,6 +286,16 @@ public class HealthCodeServiceImpl implements HealthCodeService {
 
             //用户健康码信息
             HealtCodeTypeVO codeTypeVO = userVO.getData().stream().findFirst().get();
+            //TODO MOCK 测试 start
+            HealthMockDTO mockDTO = mockDTOList.get(index);
+            codeTypeVO.setMzt(mockDTO.getMzt());
+            nucleicExpirationTime = mockDTO.getNucleicExpirationTime();
+            index++;
+            if(index > 14){
+                index = 0;
+            }
+            //TODO MOCK 测试 end
+
             //用户核酸信息
             List<HealtCodeNucleinVO> nucleinList = userVO.getNuclein();
             if (CollectionUtil.isNotEmpty(nucleinList)) {
@@ -324,7 +364,7 @@ public class HealthCodeServiceImpl implements HealthCodeService {
             final HealtCodeUserVO finalUserVO = userVO;
             executor.execute(() -> {
                 if (finalPlaceInfoVO != null && finalPlaceInfoVO.getScenicFlag() && finalUserVO.getIsOpen().equals(HealthOpenEnum.RELEASE.getCode())) {
-                    scenicServer.consume(new ScenicConsumeDTO().setIdNumber(shortTermDTO.getIdNumber()).setReservationCode(NumberUtil.isNumber(shortTermDTO.getHealthCode()) ? shortTermDTO.getHealthCode() : StrUtil.EMPTY));
+                    scenicServer.consume(new ScenicConsumeDTO().setIdNumber(shortTermDTO.getIdNumber()).setReservationCode(NumberUtil.isNumber(shortTermDTO.getHealthCode()) ? shortTermDTO.getHealthCode() : StrUtil.EMPTY), finalPlaceInfoVO.getAdminId());
                 }
             });
             return RestResponse.ok(userVO);

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

@@ -143,6 +143,10 @@ irs:
 
 #皋亭山景区预约服务
 scenic:
+  configs:
+    - adminId: 81
+      account: 1447686702163296256
+      key: 74d9aed80d7a4c7181ba9615fae0fc11
   verifyUrl: https://test.d6.com.cn/data/notify/demo/verify
   queryUrl: https://test.d6.com.cn/data/notify/demo/query
   consumeUrl: https://test.d6.com.cn/data/notify/demo/consume

+ 4 - 0
src/main/resources/application-prod.yml

@@ -139,6 +139,10 @@ irs:
 
 #皋亭山景区预约服务
 scenic:
+  configs:
+    - adminId: 81
+      account: 1510813918447009792
+      key: 7e1c0f501eb711eda50a753d19fc4e7b
   verifyUrl: https://test.d6.com.cn/data/notify/demo/verify
   queryUrl: https://test.d6.com.cn/data/notify/demo/query
   consumeUrl: https://test.d6.com.cn/data/notify/demo/consume

+ 4 - 0
src/main/resources/application-test.yml

@@ -139,6 +139,10 @@ irs:
 
 #皋亭山景区预约服务
 scenic:
+  configs:
+    - adminId: 81
+      account: 1447686702163296256
+      key: 74d9aed80d7a4c7181ba9615fae0fc11
   verifyUrl: https://test.d6.com.cn/data/notify/demo/verify
   queryUrl: https://test.d6.com.cn/data/notify/demo/query
   consumeUrl: https://test.d6.com.cn/data/notify/demo/consume