CZT
2023-10-23 462bfe45f2bd766330db2aa9f4a5abbaa086853b
武汉省平台接口-调整接口封装
已修改6个文件
已添加2个文件
406 ■■■■ 文件已修改
src/main/java/com/fzzy/api/entity/ApiConfs.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/utils/SM4Util.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/view/ApiConfs.view.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/conf/RestTemplateConfig.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/otherview/whhpjl/pr/WhjlApi1101PR.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/push/whhpjl/Whjl2023HttpClientUtil.java 69 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/push/whhpjl/WhjlApiRemoteService.java 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/push/whhpjl/dto/WhjlReqDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/entity/ApiConfs.java
@@ -62,6 +62,10 @@
    @Column(name = "publicKey", length = 200)
    private String publicKey;
    @PropertyDef(label = "授权码")
    @Column(name = "appCode", length = 50)
    private String appCode;
    @PropertyDef(label = "省平台接口地址")
    @Column(name = "apiUrl", length = 200)
    private String apiUrl;
src/main/java/com/fzzy/api/utils/SM4Util.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
package com.fzzy.api.utils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
/**
 * @Author: huangyucai
 * @Date: 2022/10/31
 * @Desc:
 **/
public class SM4Util {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    private static final String ENCODING = "UTF-8";
    public static final String ALGORITHM_NAME = "SM4";
    // åŠ å¯†ç®—æ³•/分组加密模式/分组填充方式
    // PKCS5Padding-以8个字节为一组进行分组加密
    // å®šä¹‰åˆ†ç»„加密模式使用:PKCS5Padding
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
    // 128-32位16进制;256-64位16进制
    public static final int DEFAULT_KEY_SIZE = 128;
    /**
     * è‡ªåŠ¨ç”Ÿæˆå¯†é’¥ï¼ˆ16进制字符串,长度32)
     *
     * @return
     * @explain
     */
    public static String generateKey() throws Exception {
        return Hex.toHexString(generateKey(DEFAULT_KEY_SIZE));
    }
    /**
     * @param keySize
     * @return
     * @throws Exception
     * @explain
     */
    public static byte[] generateKey(int keySize) throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(keySize, new SecureRandom());
        return kg.generateKey().getEncoded();
    }
    /**
     * ç”ŸæˆECB暗号
     *
     * @param algorithmName ç®—法名称
     * @param mode          æ¨¡å¼
     * @param key
     * @return
     * @throws Exception
     * @explain ECB模式(电子密码本模式:Electronic codebook)
     */
    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
        cipher.init(mode, sm4Key);
        return cipher;
    }
    /**
     * sm4加密
     *
     * @param hexKey   16进制密钥(忽略大小写)
     * @param paramStr å¾…加密字符串
     * @return è¿”回16进制的加密字符串
     * @explain åŠ å¯†æ¨¡å¼ï¼šECB
     * å¯†æ–‡é•¿åº¦ä¸å›ºå®šï¼Œä¼šéšç€è¢«åŠ å¯†å­—ç¬¦ä¸²é•¿åº¦çš„å˜åŒ–è€Œå˜åŒ–
     */
    public static String encryptEcb(String hexKey, String paramStr) {
        try {
            String cipherText = "";
            // 16进制字符串-->byte[]
            byte[] keyData = ByteUtils.fromHexString(hexKey);
            // String-->byte[]
            byte[] srcData = paramStr.getBytes(ENCODING);
            // åŠ å¯†åŽçš„æ•°ç»„
            byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
            // byte[]-->hexString
            cipherText = ByteUtils.toHexString(cipherArray);
            return cipherText;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
    /**
     * åŠ å¯†æ¨¡å¼ä¹‹Ecb
     *
     * @param key
     * @param data
     * @return
     * @throws Exception
     * @explain
     */
    public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }
    /**
     * sm4解密
     *
     * @param hexKey     16进制密钥
     * @param cipherText 16进制的加密字符串(忽略大小写)
     * @return è§£å¯†åŽçš„字符串
     * @throws Exception
     * @explain è§£å¯†æ¨¡å¼ï¼šé‡‡ç”¨ECB
     */
    public static String decryptEcb(String hexKey, String cipherText) {
        // ç”¨äºŽæŽ¥æ”¶è§£å¯†åŽçš„字符串
        String decryptStr = "";
        // hexString-->byte[]
        byte[] keyData = ByteUtils.fromHexString(hexKey);
        // hexString-->byte[]
        byte[] cipherData = ByteUtils.fromHexString(cipherText);
        // è§£å¯†
        byte[] srcData = new byte[0];
        try {
            srcData = decrypt_Ecb_Padding(keyData, cipherData);
            // byte[]-->String
            decryptStr = new String(srcData, ENCODING);
        } catch (Exception e) {
        }
        return decryptStr;
    }
    /**
     * è§£å¯†
     *
     * @param key
     * @param cipherText
     * @return
     * @throws Exception
     * @explain
     */
    public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }
    /**
     * æ ¡éªŒåŠ å¯†å‰åŽçš„å­—ç¬¦ä¸²æ˜¯å¦ä¸ºåŒä¸€æ•°æ®
     *
     * @param hexKey     16进制密钥(忽略大小写)
     * @param cipherText 16进制加密后的字符串
     * @param paramStr   åŠ å¯†å‰çš„å­—ç¬¦ä¸²
     * @return æ˜¯å¦ä¸ºåŒä¸€æ•°æ®
     * @throws Exception
     * @explain
     */
    public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception {
        // ç”¨äºŽæŽ¥æ”¶æ ¡éªŒç»“æžœ
        boolean flag = false;
        // hexString-->byte[]
        byte[] keyData = ByteUtils.fromHexString(hexKey);
        // å°†16进制字符串转换成数组
        byte[] cipherData = ByteUtils.fromHexString(cipherText);
        // è§£å¯†
        byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);
        // å°†åŽŸå­—ç¬¦ä¸²è½¬æ¢æˆbyte[]
        byte[] srcData = paramStr.getBytes(ENCODING);
        // åˆ¤æ–­2个数组是否一致
        flag = Arrays.equals(decryptData, srcData);
        return flag;
    }
 /*   public static void main(String[] args) {
        try {
            String json = "{\"name\":\"jz\"}";
            System.out.println("明文:" + json);
            // ç”Ÿæˆ32位16进制密钥
            String key = SM4Util.generateKey();
            System.out.println("密钥:" + key);
            String cipher = SM4Util.encryptEcb(key, json);
            System.out.println("密文:" + cipher);
            System.out.println("数据是否有效:" + SM4Util.verifyEcb(key, cipher, json));
            String res = SM4Util.decryptEcb(key, cipher);
            System.out.println("解密后数据:" + res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/
}
src/main/java/com/fzzy/api/view/ApiConfs.view.xml
@@ -27,6 +27,10 @@
        <Property></Property>
        <Property name="label">省平台加密公钥</Property>
      </PropertyDef>
      <PropertyDef name="appCode">
        <Property></Property>
        <Property name="label">授权码</Property>
      </PropertyDef>
      <PropertyDef name="apiUrl">
        <Property></Property>
        <Property name="label">省平台接口地址</Property>
@@ -426,13 +430,18 @@
                  <Property name="labelWidth">120</Property>
                  <Editor/>
                </AutoFormElement>
                <AutoFormElement layoutConstraint="colSpan:2">
                <AutoFormElement>
                  <Property name="name">publicKey</Property>
                  <Property name="property">publicKey</Property>
                  <Property name="labelWidth">125</Property>
                  <Editor/>
                </AutoFormElement>
                <AutoFormElement>
                  <Property name="name">appCode</Property>
                  <Property name="property">appCode</Property>
                  <Editor/>
                </AutoFormElement>
                <AutoFormElement>
                  <Property name="name">pushProtocol</Property>
                  <Property name="property">pushProtocol</Property>
                  <Property name="labelWidth">125</Property>
src/main/java/com/fzzy/conf/RestTemplateConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package com.fzzy.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
/**
 * RestTemplate的配置,SpringBoot封装的HTTP协议,GET和POST请求方法
 *
 * @author Andy
 *
 */
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        RestTemplate restTemplate = new RestTemplate(factory);
        restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);// è®¾ç½®è¿žæŽ¥è¶…时,单位毫秒
        factory.setReadTimeout(15000);//设置读取超时
        return factory;
    }
}
src/main/java/com/fzzy/otherview/whhpjl/pr/WhjlApi1101PR.java
@@ -18,6 +18,7 @@
import com.fzzy.otherview.whhpjl.dto.WhjlApi1101;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -107,30 +108,31 @@
     */
    @Expose
    public String pushData(List<WhjlApi1101> items) {
        ResponseDto responseDto;
        String result = "";
        String kqdm = items.get(0).getKqdm();
        ApiConfs apiConf = apiCommonService.getConf(kqdm);
        if (null == apiConf) return "系统没有获取到当前库区配置信息,执行失败";
        if (null == apiConf) {
            return "系统没有获取到当前库区配置信息,执行失败";
        }
        //封装参数
        ApiParam param = new ApiParam(apiConf, WhjlConstant.API_CATEGORY_11, WhjlConstant.API_CODE_1101);
        //获取实现接口
        ApiRemoteService apiService = apiPushManager.getApiRemoteService(param.getPushProtocol());
        if (null == apiService) return "系统没有当前推送协议配置,执行失败";
        if (null == apiService) {
            return "系统没有当前推送协议配置,执行失败";
        }
        //推送,数据为集合形式
        responseDto = apiService.pushData(param, apiConf, items);
        if (responseDto.getSuccess() == 0) {
            //推送成功,更新数据上传状态
        ResponseDto responseDto;
            ApiInfoData infoData;
            for (WhjlApi1101 data : items) {
            responseDto = apiService.pushData(param, apiConf, items);
            if (responseDto.getSuccess() == 0) {
                if(Constant.CZBZ_I.equals(data.getCzbz())){
                    infoData = new ApiInfoData();
                    infoData.setId(data.getBizId());
                    infoData.setKqdm(data.getKqdm());
@@ -142,7 +144,6 @@
                    data.setCzbz(Constant.CZBZ_U);
                    infoData.setCzbz(Constant.CZBZ_U);
                    infoData.setData(JSON.toJSONString(data));
                    apiInfoDataRep.save(infoData);
                }
            }
src/main/java/com/fzzy/push/whhpjl/Whjl2023HttpClientUtil.java
@@ -1,66 +1,40 @@
package com.fzzy.push.whhpjl;
import com.alibaba.fastjson.JSON;
import com.fzzy.api.entity.ApiConfs;
import com.fzzy.push.whhpjl.dto.WhjlReqDto;
import com.fzzy.push.whhpjl.dto.WhjlRespDto;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
/**
 * æ­¦æ±‰å†›ç²®çœå¹³å°-上传数据服务类
 *
 * @author czt
 * @date 2023/08/04
 * @date 2023/10/23
 */
@Slf4j
@Component
public class Whjl2023HttpClientUtil {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * post formData
     * æ•°æ®ä¸ŠæŠ¥post请求
     * @param url
     * @param reqData
     * @return
     * @throws Exception
     */
    @SuppressWarnings("resource")
    public static WhjlRespDto postPushData(String url, WhjlReqDto reqData , ApiConfs apiConfs) throws Exception {
        log.info("---------接口请求地址:" +url+ "----------参数:" + reqData.toString() +"---------");
        BufferedReader in = null;
        URL urls = new URL(url);
        HttpURLConnection connection = null;
        OutputStream outputStream = null;
    public WhjlRespDto postPushData(String url, WhjlReqDto reqData) {
        log.info("---------接口请求地址:" + url + "----------参数:" + JSON.toJSONString(reqData) + "---------");
        String rs = "";
        WhjlRespDto responseDto;
        try {
            connection = (HttpURLConnection) urls.openConnection();
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
            connection.setRequestProperty("Accept", "*/*");
            connection.setRequestProperty("Range", "bytes=" + "");
            connection.setConnectTimeout(20000);
            connection.setReadTimeout(30000);
            connection.setRequestMethod("POST");
            outputStream = connection.getOutputStream();
            outputStream.write(reqData.toString().getBytes("UTF-8"));
            try {
                connection.connect();
                if (connection.getResponseCode() == 200) {
                    in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                    String line = "";
                    while ((line = in.readLine()) != null) {
                        rs += line;
                    }
                }else{
                    log.error("http状态:" + connection.getResponseCode());
                    log.error("http消息:" + connection.getResponseMessage());
                }
            rs = restTemplate.postForObject(url, reqData, String.class);
            } catch (Exception e) {
                System.out.println("发生异常");
@@ -72,18 +46,5 @@
            responseDto = JSON.parseObject(rs,WhjlRespDto.class);
            if(responseDto == null )   return new WhjlRespDto(99,"接口请求发生未知错误");
            return responseDto;
        } finally {
            try {
                outputStream.close();
                if (in != null){
                    in.close();
                }
            } catch (Exception e) {
            }
            outputStream = null;
            if (connection != null)
                connection.disconnect();
            connection = null;
        }
    }
}
src/main/java/com/fzzy/push/whhpjl/WhjlApiRemoteService.java
@@ -39,6 +39,8 @@
    private ApiTriggerService apiTriggerService;
    @Autowired
    private ApiLogRep apiLogRep;
    @Autowired
    private Whjl2023HttpClientUtil whjl2023HttpClientUtil;
    @Override
    public String getProtocol() {
@@ -64,7 +66,7 @@
            ApiLog apiLog = new ApiLog();
            apiLog.setId(ContextUtil.getUUID());
            apiLog.setInteId(inteId);
            String jsonData = getJsonData(inteId, data);
            String jsonData = getJsonData(data);
            log.info("接口数据信息=" + jsonData);
            inteId = getInteId(inteId);
            if (StringUtils.isEmpty(inteId)) {
@@ -86,42 +88,38 @@
                return responseDto;
            }
            //封装推送数据
            WhjlReqDto reqData = new WhjlReqDto();
            //报文标识ID
            reqData.setId(ContextUtil.getUUID());
            //身份ID
            reqData.setUid(conf.getUserName());
            //获取指令id
            String key = RedisConst.buildKey(RedisConst.KYE_ORDER, conf.getKqdm());
            String orderId = (String)redisUtil.get(key);
            if(StringUtils.isEmpty(orderId)){
                ResponseDto responseDto = new ResponseDto(99, "指令id失效");
                apiLog.setStatus(99);
                apiLog.setResult("指令id失效");
                apiLogRep.save(apiLog);
                return responseDto;
                orderId = reqData.getId();
            }
            //封装推送数据
            WhjlReqDto reqData = new WhjlReqDto();
            reqData.setId(ContextUtil.getUUID());
            reqData.setUid(conf.getKqdm());
            //指令ID
            reqData.setOrderid(orderId);
            reqData.setAppcode(conf.getUserName());
            reqData.setTimestamp(ContextUtil.getCurTimeMillis());
            //应用码
            reqData.setAppcode(conf.getAppCode());
            //时间戳
            reqData.setTimestamp(Long.valueOf(ContextUtil.getCurTimeMillis()));
            //身份签名,对应用码_授权码_站点编码_报文ID_时间戳进行MD5算法签名
            String accessToken = reqData.getAppcode() +"_" + conf.getPassword() +"_" + reqData.getUid() + "_" + reqData.getId() + "_" + reqData.getTimestamp();
            log.info("身份签名:" + accessToken);
            reqData.setAccesstoken(MyMD5Util.encrypt(accessToken));
            //数据总条数
            List<Object> list  = (List<Object>)data;
            reqData.setDatalength(list.size());
            //数据进行SM4加密
            reqData.setData(AESUtils.encrypt(jsonData, conf.getPublicKey()));
            reqData.setOperator("insert");
            //数据主体,进行SM4加密
            reqData.setData(SM4Util.encryptEcb(conf.getPublicKey(), jsonData));
            //摘要,数据主体的MD5值
            reqData.setDigst(MyMD5Util.encrypt(jsonData));
            //身份签名,对应用码_授权码_站点编码_报文ID_时间戳进行MD5算法签名
            StringBuffer buffer = new StringBuffer();
            buffer.append(reqData.getAppcode()).append("_");
            buffer.append(conf.getPublicKey()).append("_");
            buffer.append(conf.getKqmc()).append("_");
            buffer.append(reqData.getId()).append("_");
            buffer.append(reqData.getTimestamp());
            reqData.setDigst(MyMD5Util.encrypt(buffer.toString()));
            reqData.setDigest(MyMD5Util.encrypt(jsonData));
            //操作类型
            reqData.setOperator("insert");
            WhjlRespDto responseDto = Whjl2023HttpClientUtil.postPushData(conf.getApiUrl() + inteId, reqData, conf);
            WhjlRespDto responseDto = whjl2023HttpClientUtil.postPushData(conf.getApiUrl() + inteId, reqData);
            apiLog.setStatus(responseDto.getCode() == 200 ? 0 : responseDto.getCode());
            apiLog.setResult(responseDto.getResult());
            apiLogRep.save(apiLog);
@@ -137,15 +135,16 @@
    }
    /**
     * è°ƒæ•´æ•°æ®å°è£…,获取json数据
     * è°ƒæ•´æ•°æ®å°è£…成list,获取json数据
     *
     * @param inteId
     * @param data
     * @return
     * @throws Exception
     */
    private String getJsonData(String inteId, Object data) {
        return JSON.toJSONString(data);
    private String getJsonData(Object data) {
        List<Object> list = new ArrayList<>();
        list.add(data);
        return JSON.toJSONString(list);
    }
    private String getInteId(String inteId) {
src/main/java/com/fzzy/push/whhpjl/dto/WhjlReqDto.java
@@ -35,7 +35,7 @@
    /**
     * æ—¶é—´æˆ³
     */
    private String timestamp;
    private Long timestamp;
    /**
     * èº«ä»½ç­¾å
@@ -55,7 +55,7 @@
    /**
     * æ•°æ®æ‘˜è¦
     */
    private String digst;
    private String digest;
    /**
     * æ“ä½œç±»åž‹