hejinbo 2 лет назад
Родитель
Сommit
4d4ab28c40

+ 3
- 8
ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/AdjudicationController.java Просмотреть файл

@@ -27,17 +27,12 @@ public class AdjudicationController extends BaseController {
27 27
 
28 28
     /**
29 29
      * 裁决书送达(电子邮件)
30
-     * @param id 案件id
31
-     * @param appEmail 申请人邮箱
32
-     * @param resEmail 被申请人邮箱
33
-     * @param apptrackingNum 申请人快递单号
34
-     * @param restrackingNum 被申请人快递单号
30
+     * @param bookSendVO
35 31
      * @return
36 32
      */
37 33
     @PostMapping("/delivery")
38
-    public AjaxResult sendDocumentByEmail(Long id,String appEmail,String resEmail
39
-            ,String apptrackingNum,String restrackingNum){
40
-        return adjudicationService.sendDocumentByEmail(id,appEmail,resEmail,apptrackingNum,restrackingNum);
34
+    public AjaxResult sendDocumentByEmail(@RequestBody BookSendVO bookSendVO){
35
+        return adjudicationService.sendDocumentByEmail(bookSendVO.getId(),bookSendVO.getAppEmail(),bookSendVO.getResEmail(),bookSendVO.getApptrackingNum(),bookSendVO.getRestrackingNum());
41 36
     }
42 37
 
43 38
     /**

+ 4
- 1
ruoyi-common/pom.xml Просмотреть файл

@@ -183,7 +183,10 @@
183 183
             <artifactId>mail</artifactId>
184 184
             <version>1.4.7</version>
185 185
         </dependency>
186
-
186
+        <dependency>
187
+            <groupId>org.apache.httpcomponents</groupId>
188
+            <artifactId>httpclient</artifactId>
189
+        </dependency>
187 190
 
188 191
 
189 192
     </dependencies>

+ 13
- 0
ruoyi-common/src/main/java/com/ruoyi/common/config/EsignDemoConfig.java Просмотреть файл

@@ -0,0 +1,13 @@
1
+package com.ruoyi.common.config;
2
+
3
+public class EsignDemoConfig {
4
+
5
+    // 应用ID
6
+    public static final String EsignAppId = "7438987614";
7
+    // 应用密钥
8
+    public static final String EsignAppSecret = "9d7844f13830931037772b9d20cf1529";
9
+    // e签宝接口调用域名(模拟环境)
10
+    public static final String EsignHost = "https://smlopenapi.esign.cn";
11
+    // e签宝接口调用域名(正式环境)
12
+    // public static final String EsignHost = "https://openapi.esign.cn";
13
+}

+ 371
- 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignEncryption.java Просмотреть файл

@@ -0,0 +1,371 @@
1
+/*
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4
+ * the License. You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ * specific language governing permissions and limitations under the License.
11
+ */
12
+package com.ruoyi.common.constant;
13
+import com.ruoyi.common.exception.EsignDemoException;
14
+import org.apache.commons.codec.binary.Base64;
15
+import org.apache.http.message.BasicNameValuePair;
16
+
17
+import javax.crypto.Mac;
18
+import javax.crypto.spec.SecretKeySpec;
19
+import java.io.UnsupportedEncodingException;
20
+import java.security.InvalidKeyException;
21
+import java.security.MessageDigest;
22
+import java.security.NoSuchAlgorithmException;
23
+import java.text.Collator;
24
+import java.text.MessageFormat;
25
+import java.util.*;
26
+
27
+/**
28
+ * @description 请求数据通用处理类
29
+ * @author 澄泓
30
+ * @date 2020年10月22日 下午14:25:31
31
+ * @since JDK1.7
32
+ */
33
+public class EsignEncryption {
34
+
35
+    /**
36
+     * 不允许外部创建实例
37
+     */
38
+    private EsignEncryption(){}
39
+
40
+    /**
41
+     * 拼接待签名字符串
42
+     * @param httpMethod
43
+     * @param url
44
+     * @return
45
+     */
46
+    public static String appendSignDataString(String httpMethod, String contentMd5,String accept,String contentType,String headers,String date, String url) throws EsignDemoException {
47
+        StringBuffer sb = new StringBuffer();
48
+        sb.append(httpMethod).append("\n").append(accept).append("\n").append(contentMd5).append("\n")
49
+                .append(contentType).append("\n");
50
+
51
+        if ("".equals(date) || date == null) {
52
+            sb.append("\n");
53
+        } else {
54
+            sb.append(date).append("\n");
55
+        }
56
+        if ("".equals(headers) || headers == null) {
57
+            sb.append(url);
58
+        } else {
59
+            sb.append(headers).append("\n").append(url);
60
+        }
61
+        return new String(sb);
62
+    }
63
+
64
+    /***
65
+     *  Content-MD5的计算方法
66
+     * @param str 待计算的消息
67
+     * @return MD5计算后摘要值的Base64编码(ContentMD5)
68
+     * @throws EsignDemoException 加密过程中的异常信息
69
+     */
70
+    public static String doContentMD5(String str) throws EsignDemoException {
71
+        byte[] md5Bytes = null;
72
+        MessageDigest md5 = null;
73
+        String contentMD5 = null;
74
+        try {
75
+            md5 = MessageDigest.getInstance("MD5");
76
+            // 计算md5函数
77
+            md5.update(str.getBytes("UTF-8"));
78
+            // 获取文件MD5的二进制数组(128位)
79
+            md5Bytes = md5.digest();
80
+            // 把MD5摘要后的二进制数组md5Bytes使用Base64进行编码(而不是对32位的16进制字符串进行编码)
81
+            contentMD5 = Base64.encodeBase64String(md5Bytes);
82
+
83
+        } catch (NoSuchAlgorithmException e) {
84
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
85
+            ex.initCause(e);
86
+            throw ex;
87
+        } catch (UnsupportedEncodingException e) {
88
+            e.printStackTrace();
89
+        }
90
+        return contentMD5;
91
+    }
92
+
93
+    /***
94
+     * 计算请求签名值-HmacSHA256摘要
95
+     * @param message 待签名字符串
96
+     * @param secret  密钥APP KEY
97
+     * @return reqSignature HmacSHA256计算后摘要值的Base64编码
98
+     * @throws EsignDemoException 加密过程中的异常信息
99
+     */
100
+    public static String doSignatureBase64(String message, String secret) throws EsignDemoException {
101
+        String algorithm = "HmacSHA256";
102
+        Mac hmacSha256;
103
+        String digestBase64 = null;
104
+        try {
105
+            hmacSha256 = Mac.getInstance(algorithm);
106
+            byte[] keyBytes = secret.getBytes("UTF-8");
107
+            byte[] messageBytes = message.getBytes("UTF-8");
108
+            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
109
+            // 使用HmacSHA256对二进制数据消息Bytes计算摘要
110
+            byte[] digestBytes = hmacSha256.doFinal(messageBytes);
111
+            // 把摘要后的结果digestBytes使用Base64进行编码
112
+            digestBase64 = Base64.encodeBase64String(digestBytes);
113
+        } catch (NoSuchAlgorithmException e) {
114
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
115
+            ex.initCause(e);
116
+            throw ex;
117
+        } catch (InvalidKeyException e) {
118
+            EsignDemoException ex = new EsignDemoException("无效的密钥规范",e);
119
+            ex.initCause(e);
120
+            throw ex;
121
+        } catch (UnsupportedEncodingException e) {
122
+            e.printStackTrace();
123
+        }
124
+        return digestBase64;
125
+    }
126
+
127
+    /**
128
+     * 获取时间戳
129
+     * @return
130
+     */
131
+    public static String timeStamp() {
132
+        long timeStamp = System.currentTimeMillis();
133
+        return String.valueOf(timeStamp);
134
+    }
135
+
136
+    /**
137
+     * byte字节数组转换成字符串
138
+     * @param b
139
+     * @return
140
+     */
141
+    public static String byteArrayToHexString(byte[] b) {
142
+        StringBuilder hs = new StringBuilder();
143
+        String stmp;
144
+        for (int n = 0; b != null && n < b.length; n++) {
145
+            stmp = Integer.toHexString(b[n] & 0XFF);
146
+            if (stmp.length() == 1)
147
+                hs.append('0');
148
+            hs.append(stmp);
149
+        }
150
+        return hs.toString().toLowerCase();
151
+    }
152
+
153
+    /**
154
+     * hash散列加密算法
155
+     * @return
156
+     */
157
+    public static String Hmac_SHA256(String message,String key) throws EsignDemoException {
158
+        byte[] rawHmac=null;
159
+        try {
160
+            SecretKeySpec sk = new SecretKeySpec(key.getBytes(), "HmacSHA256");
161
+            Mac mac = Mac.getInstance("HmacSHA256");
162
+            mac.init(sk);
163
+            rawHmac = mac.doFinal(message.getBytes());
164
+        }catch (InvalidKeyException e){
165
+            EsignDemoException ex = new EsignDemoException("无效的密钥规范",e);
166
+            ex.initCause(e);
167
+            throw ex;
168
+        } catch (NoSuchAlgorithmException e) {
169
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
170
+            ex.initCause(e);
171
+            throw ex;
172
+        }catch (Exception e){
173
+            EsignDemoException ex = new EsignDemoException("hash散列加密算法报错",e);
174
+            ex.initCause(e);
175
+            throw ex;
176
+        }finally {
177
+            return byteArrayToHexString(rawHmac);
178
+        }
179
+
180
+    }
181
+
182
+    /**
183
+     * MD5加密32位
184
+     */
185
+    public static String MD5Digest(String text) throws EsignDemoException {
186
+        byte[] digest=null;
187
+        try {
188
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
189
+            md5.update(text.getBytes());
190
+            digest = md5.digest();
191
+        }catch (NoSuchAlgorithmException e){
192
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
193
+            ex.initCause(e);
194
+            throw ex;
195
+        }finally {
196
+            return byteArrayToHexString(digest);
197
+        }
198
+
199
+    }
200
+
201
+    public static void formDataSort(List<BasicNameValuePair> param) {
202
+        Collections.sort(param, new Comparator<BasicNameValuePair>() {
203
+            @Override
204
+            public int compare(BasicNameValuePair o1, BasicNameValuePair o2) {
205
+                Comparator<Object> com = Collator.getInstance(Locale.CHINA);
206
+                return com.compare(o1.getName(), o2.getName());
207
+            }
208
+        });
209
+    }
210
+
211
+    /***
212
+     * 字符串是否为空(含空格校验)
213
+     * @param str
214
+     * @return
215
+     */
216
+    public static boolean isBlank(String str) {
217
+        if (null == str || 0 == str.length()) {
218
+            return true;
219
+        }
220
+
221
+        int strLen = str.length();
222
+
223
+        for (int i = 0; i < strLen; i++) {
224
+            if (!Character.isWhitespace(str.charAt(i))) {
225
+                return false;
226
+            }
227
+        }
228
+        return true;
229
+    }
230
+
231
+
232
+    /***
233
+     * 对请求URL中的Query参数按照字段名的 ASCII 码从小到大排序(字典排序)
234
+     *
235
+     * @param apiUrl
236
+     * @return 排序后的API接口地址
237
+     * @throws Exception
238
+     */
239
+    public static String sortApiUrl(String apiUrl) throws EsignDemoException {
240
+
241
+        if (!apiUrl.contains("?")) {
242
+            return apiUrl;
243
+        }
244
+
245
+        int queryIndex = apiUrl.indexOf("?");
246
+        String apiUrlPath =apiUrl.substring(0,queryIndex+1);
247
+        String apiUrlQuery = apiUrl.substring(queryIndex+1);
248
+        //apiUrlQuery为空时返回
249
+        if(isBlank(apiUrlQuery)){
250
+            return apiUrl.substring(0,apiUrl.length()-1);
251
+             }
252
+        // 请求URL中Query参数转成Map
253
+        Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
254
+        String[] params = apiUrlQuery.split("&");
255
+        for (String str : params) {
256
+            int index = str.indexOf("=");
257
+            String key = str.substring(0, index);
258
+            String value = str.substring(index + 1);
259
+            if (queryParamsMap.containsKey(key)) {
260
+                String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
261
+                throw new EsignDemoException(msg);
262
+            }
263
+            queryParamsMap.put(key, value);
264
+        }
265
+
266
+        ArrayList<String> queryMapKeys = new ArrayList<String>();
267
+        for (Map.Entry<Object, Object> entry : queryParamsMap.entrySet()) {
268
+            queryMapKeys.add((String) entry.getKey());
269
+        }
270
+        // 按照字段名的 ASCII 码从小到大排序(字典排序)
271
+        Collections.sort(queryMapKeys, new Comparator<String>() {
272
+            @Override
273
+            public int compare(String o1, String o2) {
274
+                return (o1.compareToIgnoreCase(o2) == 0 ? -o1.compareTo(o2) : o1.compareToIgnoreCase(o2));
275
+            }
276
+        });
277
+
278
+        StringBuffer queryString = new StringBuffer();
279
+        // 构造Query参数键值对值对的格式
280
+        for (int i = 0; i < queryMapKeys.size(); i++) {
281
+            String key = queryMapKeys.get(i);
282
+            String value = (String) queryParamsMap.get(key);
283
+            queryString.append(key);
284
+            queryString.append("=");
285
+            queryString.append(value);
286
+            queryString.append("&");
287
+        }
288
+        if (queryString.length() > 0) {
289
+            queryString = queryString.deleteCharAt(queryString.length() - 1);
290
+        }
291
+
292
+        // Query参数排序后的接口请求地址
293
+        StringBuffer sortApiUrl = new StringBuffer();
294
+        sortApiUrl.append(apiUrlPath);
295
+        sortApiUrl.append(queryString.toString());
296
+        return sortApiUrl.toString();
297
+    }
298
+
299
+    /**
300
+     *获取query
301
+     * @param apiUrl
302
+     * @return
303
+     * @throws EsignDemoException
304
+     */
305
+    public static ArrayList<BasicNameValuePair> getQuery(String apiUrl) throws EsignDemoException {
306
+        ArrayList<BasicNameValuePair> BasicNameValuePairList = new ArrayList<>();
307
+
308
+        if (!apiUrl.contains("?")) {
309
+            return BasicNameValuePairList;
310
+        }
311
+
312
+        int queryIndex = apiUrl.indexOf("\\?");
313
+        String apiUrlQuery = apiUrl.substring(queryIndex,apiUrl.length());
314
+
315
+        // 请求URL中Query参数转成Map
316
+        Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
317
+        String[] params = apiUrlQuery.split("&");
318
+        for (String str : params) {
319
+            int index = str.indexOf("=");
320
+            String key = str.substring(0, index);
321
+            String value = str.substring(index + 1);
322
+            if (queryParamsMap.containsKey(key)) {
323
+                String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
324
+                throw new EsignDemoException(msg);
325
+            }
326
+            BasicNameValuePairList.add(new BasicNameValuePair(key,value));
327
+            queryParamsMap.put(key, value);
328
+        }
329
+        return BasicNameValuePairList;
330
+    }
331
+    /**
332
+     *
333
+     */
334
+    public static boolean callBackCheck(String timestamp,String requestQuery,String body,String key,String signature){
335
+        String algorithm="HmacSHA256";
336
+        String encoding="UTF-8";
337
+        Mac mac = null;
338
+        try {
339
+            String data = timestamp + requestQuery + body;
340
+            mac = Mac.getInstance(algorithm);
341
+            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(encoding), algorithm);
342
+            mac.init(secretKey);
343
+            mac.update(data.getBytes(encoding));
344
+        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
345
+            e.printStackTrace();
346
+            System.out.println("获取Signature签名信息异常:" + e.getMessage());
347
+            return false;
348
+        }
349
+        return byte2hex(mac.doFinal()).equalsIgnoreCase(signature);
350
+    }
351
+
352
+    /***
353
+     * 将byte[]转成16进制字符串
354
+     *
355
+     * @param data
356
+     *
357
+     * @return 16进制字符串
358
+     */
359
+    public static String byte2hex(byte[] data) {
360
+        StringBuilder hash = new StringBuilder();
361
+        String stmp;
362
+        for (int n = 0; data != null && n < data.length; n++) {
363
+            stmp = Integer.toHexString(data[n] & 0XFF);
364
+            if (stmp.length() == 1)
365
+                hash.append('0');
366
+            hash.append(stmp);
367
+        }
368
+        return hash.toString();
369
+    }
370
+
371
+}

+ 26
- 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHeaderConstant.java Просмотреть файл

@@ -0,0 +1,26 @@
1
+package com.ruoyi.common.constant;
2
+/**
3
+ * @description  头部信息常量
4
+ * @author  澄泓
5
+ * @date  2020/10/22 15:05
6
+ * @version JDK1.7
7
+ */
8
+public enum EsignHeaderConstant {
9
+    ACCEPT("*/*"),
10
+    DATE(""),
11
+    HEADERS( ""),
12
+    CONTENTTYPE_FORMDATA("application/x-www-form-urlencoded"),
13
+    CONTENTTYPE_JSON("application/json; charset=UTF-8"),
14
+    CONTENTTYPE_PDF("application/pdf"),
15
+    CONTENTTYPE_STREAM("application/octet-stream"),
16
+    AUTHMODE("Signature");
17
+
18
+    private String value;
19
+    private EsignHeaderConstant(String value) {
20
+        this.value=value;
21
+    }
22
+
23
+    public String VALUE(){
24
+        return this.value;
25
+    }
26
+}

+ 486
- 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/EsignHttpCfgHelper.java Просмотреть файл

@@ -0,0 +1,486 @@
1
+/*
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4
+ * the License. You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ * specific language governing permissions and limitations under the License.
11
+ */
12
+package com.ruoyi.common.constant;
13
+import com.ruoyi.common.core.domain.entity.EsignHttpResponse;
14
+import com.ruoyi.common.enums.EsignRequestType;
15
+import com.ruoyi.common.exception.EsignDemoException;
16
+import org.apache.http.*;
17
+import org.apache.http.auth.AuthScope;
18
+import org.apache.http.auth.UsernamePasswordCredentials;
19
+import org.apache.http.client.ClientProtocolException;
20
+import org.apache.http.client.CredentialsProvider;
21
+import org.apache.http.client.HttpRequestRetryHandler;
22
+import org.apache.http.client.config.RequestConfig;
23
+import org.apache.http.client.entity.UrlEncodedFormEntity;
24
+import org.apache.http.client.methods.CloseableHttpResponse;
25
+import org.apache.http.client.methods.HttpRequestBase;
26
+import org.apache.http.client.protocol.HttpClientContext;
27
+import org.apache.http.client.utils.URIBuilder;
28
+import org.apache.http.config.Registry;
29
+import org.apache.http.config.RegistryBuilder;
30
+import org.apache.http.conn.ConnectTimeoutException;
31
+import org.apache.http.conn.socket.ConnectionSocketFactory;
32
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
33
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
34
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
35
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
36
+import org.apache.http.entity.ByteArrayEntity;
37
+import org.apache.http.entity.ContentType;
38
+import org.apache.http.entity.StringEntity;
39
+import org.apache.http.impl.client.BasicCredentialsProvider;
40
+import org.apache.http.impl.client.CloseableHttpClient;
41
+import org.apache.http.impl.client.HttpClientBuilder;
42
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
43
+import org.apache.http.message.BasicNameValuePair;
44
+import org.apache.http.protocol.HttpContext;
45
+import org.apache.http.util.EntityUtils;
46
+import org.slf4j.Logger;
47
+import org.slf4j.LoggerFactory;
48
+
49
+import javax.net.ssl.*;
50
+import java.io.IOException;
51
+import java.io.InterruptedIOException;
52
+import java.net.UnknownHostException;
53
+import java.security.cert.CertificateException;
54
+import java.security.cert.X509Certificate;
55
+import java.text.MessageFormat;
56
+import java.util.ArrayList;
57
+import java.util.Arrays;
58
+import java.util.List;
59
+import java.util.Map;
60
+
61
+/**
62
+ * @description Http请求 辅助类
63
+ * @author 澄泓
64
+ * @since JDK1.7
65
+ */
66
+public class EsignHttpCfgHelper {
67
+
68
+	private static Logger LOGGER = LoggerFactory.getLogger(EsignHttpCfgHelper.class);
69
+	/**
70
+	 * 超时时间,默认15000毫秒
71
+	 */
72
+	private static int MAX_TIMEOUT = 15000;
73
+	/**
74
+	 * 请求池最大连接数,默认100个
75
+	 */
76
+	private static  int MAX_TOTAL=100;
77
+	/**
78
+	 * 单域名最大的连接数,默认50个
79
+	 */
80
+	private static  int ROUTE_MAX_TOTAL=50;
81
+	/**
82
+	 * 请求失败重试次数,默认3次
83
+	 */
84
+	private static   int MAX_RETRY = 3;
85
+	/**
86
+	 * 是否需要域名校验,默认不需要校验
87
+	 */
88
+	private static boolean SSL_VERIFY=false;
89
+
90
+	/**
91
+	 * 正向代理IP
92
+	 */
93
+	private static String PROXY_IP;
94
+	/**
95
+	 * 正向代理端口,默认8888
96
+	 */
97
+	private static int PROXY_PORT=8888;
98
+	/**
99
+	 * 代理协议,默认http
100
+	 */
101
+	private static String PROXY_AGREEMENT="http";
102
+
103
+	/**
104
+	 * 是否开启代理,默认false
105
+	 */
106
+	private static boolean OPEN_PROXY=false;
107
+
108
+	/**
109
+	 * 代理服务器用户名
110
+	 */
111
+	private static String PROXY_USERNAME="";
112
+
113
+	/**
114
+	 * 代理服务器密码
115
+	 */
116
+	private static String PROXY_PASSWORD="";
117
+
118
+
119
+	private static PoolingHttpClientConnectionManager connMgr; //连接池
120
+	private static HttpRequestRetryHandler retryHandler; //重试机制
121
+
122
+	private static CloseableHttpClient httpClient=null;
123
+
124
+	public static int getMaxTimeout() {
125
+		return MAX_TIMEOUT;
126
+	}
127
+
128
+	public static void setMaxTimeout(int maxTimeout) {
129
+		MAX_TIMEOUT = maxTimeout;
130
+	}
131
+
132
+	public static int getMaxTotal() {
133
+		return MAX_TOTAL;
134
+	}
135
+
136
+	public static void setMaxTotal(int maxTotal) {
137
+		MAX_TOTAL = maxTotal;
138
+	}
139
+
140
+	public static int getRouteMaxTotal() {
141
+		return ROUTE_MAX_TOTAL;
142
+	}
143
+
144
+	public static void setRouteMaxTotal(int routeMaxTotal) {
145
+		ROUTE_MAX_TOTAL = routeMaxTotal;
146
+	}
147
+
148
+	public static int getMaxRetry() {
149
+		return MAX_RETRY;
150
+	}
151
+
152
+	public static void setMaxRetry(int maxRetry) {
153
+		MAX_RETRY = maxRetry;
154
+	}
155
+
156
+	public static boolean isSslVerify() {
157
+		return SSL_VERIFY;
158
+	}
159
+
160
+	public static void setSslVerify(boolean sslVerify) {
161
+		SSL_VERIFY = sslVerify;
162
+	}
163
+
164
+	public static String getProxyIp() {
165
+		return PROXY_IP;
166
+	}
167
+
168
+	public static void setProxyIp(String proxyIp) {
169
+		PROXY_IP = proxyIp;
170
+	}
171
+
172
+	public static int getProxyPort() {
173
+		return PROXY_PORT;
174
+	}
175
+
176
+	public static void setProxyPort(int proxyPort) {
177
+		PROXY_PORT = proxyPort;
178
+	}
179
+
180
+	public static String getProxyAgreement() {
181
+		return PROXY_AGREEMENT;
182
+	}
183
+
184
+	public static void setProxyAgreement(String proxyAgreement) {
185
+		PROXY_AGREEMENT = proxyAgreement;
186
+	}
187
+
188
+	public static boolean getOpenProxy() {
189
+		return OPEN_PROXY;
190
+	}
191
+
192
+	public static void setOpenProxy(boolean openProxy) {
193
+		OPEN_PROXY = openProxy;
194
+	}
195
+
196
+	public static String getProxyUsername() {
197
+		return PROXY_USERNAME;
198
+	}
199
+
200
+	public static void setProxyUserame(String proxyUsername) {
201
+		PROXY_USERNAME = proxyUsername;
202
+	}
203
+
204
+	public static String getProxyPassword() {
205
+		return PROXY_PASSWORD;
206
+	}
207
+
208
+	public static void setProxyPassword(String proxyPassword) {
209
+		PROXY_PASSWORD = proxyPassword;
210
+	}
211
+
212
+
213
+
214
+
215
+	/**
216
+	 * 不允许外部创建实例
217
+	 */
218
+	private EsignHttpCfgHelper() {
219
+	}
220
+
221
+	//------------------------------公有方法start--------------------------------------------
222
+
223
+
224
+	/**
225
+	 * @description 发起HTTP / HTTPS 请求
226
+	 *
227
+	 * @param reqType
228
+	 * 			{@link EsignRequestType} 请求类型  GET、 POST 、 DELETE 、 PUT
229
+	 * @param httpUrl
230
+	 * 			{@link String} 请求目标地址
231
+	 * @param headers
232
+	 * 			{@link Map} 请求头
233
+	 * @param param
234
+	 * 			{@link Object} 参数
235
+	 * @return
236
+	 * @throws EsignDemoException
237
+	 * @author 澄泓
238
+	 */
239
+	public static EsignHttpResponse sendHttp(EsignRequestType reqType, String httpUrl, Map<String, String> headers, Object param, boolean debug)
240
+			throws EsignDemoException {
241
+		HttpRequestBase reqBase=null;
242
+		if(httpUrl.startsWith("http")){
243
+			reqBase=reqType.getHttpType(httpUrl);
244
+		}else{
245
+			throw new EsignDemoException("请求url地址格式错误");
246
+		}
247
+		if(debug){
248
+			LOGGER.info("请求头:{}",headers+"\n");
249
+			LOGGER.info("请求参数\n{}", param+"\n");
250
+			LOGGER.info("请求地址\n:{}\n请求方式\n:{}",reqBase.getURI(),reqType+"\n");
251
+		}
252
+		//请求方法不是GET或者DELETE时传入body体,否则不传入。
253
+		String[] methods = {"DELETE", "GET"};
254
+		if(param instanceof String&&Arrays.binarySearch(methods, reqType.name())<0){//POST或者PUT请求
255
+			((HttpEntityEnclosingRequest) reqBase).setEntity(
256
+					new StringEntity(String.valueOf(param), ContentType.create("application/json", "UTF-8")));
257
+		}
258
+		//参数时字节流数组
259
+		else if(param instanceof byte[]) {
260
+			reqBase=reqType.getHttpType(httpUrl);
261
+			byte[] paramBytes = (byte[])param;
262
+			((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes));
263
+		}
264
+		//参数是form表单时
265
+		else if(param instanceof List){
266
+			((HttpEntityEnclosingRequest) reqBase).setEntity(new UrlEncodedFormEntity((Iterable<? extends NameValuePair>) param));
267
+		}
268
+		httpClient = getHttpClient();
269
+		config(reqBase);
270
+
271
+		//设置请求头
272
+		if(headers != null &&headers.size()>0) {
273
+			for(Map.Entry<String, String> entry :headers.entrySet()) {
274
+				reqBase.setHeader(entry.getKey(), entry.getValue());
275
+			}
276
+		}
277
+		//响应对象
278
+		CloseableHttpResponse res = null;
279
+		//响应内容
280
+		String resCtx = null;
281
+		int status;
282
+		EsignHttpResponse esignHttpResponse = new EsignHttpResponse();
283
+		try {
284
+			//执行请求
285
+			res = httpClient.execute(reqBase);
286
+			status=res.getStatusLine().getStatusCode();
287
+
288
+			//获取请求响应对象和响应entity
289
+			HttpEntity httpEntity = res.getEntity();
290
+			if(httpEntity != null) {
291
+				resCtx = EntityUtils.toString(httpEntity,"utf-8");
292
+			}
293
+			if(debug) {
294
+				LOGGER.info("响应\n{}", resCtx + "\n");
295
+				LOGGER.info("----------------------------end------------------------");
296
+			}
297
+		} catch (NoHttpResponseException e) {
298
+			throw new EsignDemoException("服务器丢失了",e);
299
+		} catch (SSLHandshakeException e){
300
+			String msg = MessageFormat.format("SSL握手异常", e);
301
+			EsignDemoException ex = new EsignDemoException(msg, e);
302
+			throw ex;
303
+		} catch (UnknownHostException e){
304
+			EsignDemoException ex = new EsignDemoException("服务器找不到", e);
305
+			ex.initCause(e);
306
+			throw ex;
307
+		} catch(ConnectTimeoutException e){
308
+			EsignDemoException ex = new EsignDemoException("连接超时", e);
309
+			ex.initCause(e);
310
+			throw ex;
311
+		} catch(SSLException e){
312
+			EsignDemoException ex = new EsignDemoException("SSL异常",e);
313
+			ex.initCause(e);
314
+			throw ex;
315
+		} catch (ClientProtocolException e) {
316
+			EsignDemoException ex = new EsignDemoException("请求头异常",e);
317
+			ex.initCause(e);
318
+			throw ex;
319
+		} catch (IOException e) {
320
+			EsignDemoException ex = new EsignDemoException("网络请求失败",e);
321
+			ex.initCause(e);
322
+			throw ex;
323
+		} finally {
324
+			if(res != null) {
325
+				try {
326
+					res.close();
327
+				} catch (IOException e) {
328
+					EsignDemoException ex = new EsignDemoException("--->>关闭请求响应失败",e);
329
+					ex.initCause(e);
330
+					throw ex;
331
+				}
332
+			}
333
+		}
334
+		esignHttpResponse.setStatus(status);
335
+		esignHttpResponse.setBody(resCtx);
336
+		return esignHttpResponse;
337
+	}
338
+	//------------------------------公有方法end----------------------------------------------
339
+
340
+	//------------------------------私有方法start--------------------------------------------
341
+
342
+	/**
343
+	 * @description 请求头和超时时间配置
344
+	 *
345
+	 * @param httpReqBase
346
+	 * @author 澄泓
347
+	 */
348
+	private static void config(HttpRequestBase httpReqBase) {
349
+		// 配置请求的超时设置
350
+		RequestConfig.Builder builder = RequestConfig.custom()
351
+				.setConnectionRequestTimeout(MAX_TIMEOUT)
352
+				.setConnectTimeout(MAX_TIMEOUT)
353
+				.setSocketTimeout(MAX_TIMEOUT);
354
+		if(OPEN_PROXY){
355
+			HttpHost proxy=new HttpHost(PROXY_IP,PROXY_PORT,PROXY_AGREEMENT);
356
+			builder.setProxy(proxy);
357
+		}
358
+		RequestConfig requestConfig = builder.build();
359
+		httpReqBase.setConfig(requestConfig);
360
+	}
361
+
362
+	/**
363
+	 * @description 连接池配置
364
+	 *
365
+	 * @return
366
+	 * @author 澄泓
367
+	 */
368
+	private static void cfgPoolMgr() throws EsignDemoException {
369
+		ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
370
+		LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
371
+		if(!SSL_VERIFY){
372
+            sslsf=sslConnectionSocketFactory();
373
+        }
374
+
375
+		Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
376
+				.register("http", plainsf)
377
+				.register("https", sslsf)
378
+				.build();
379
+
380
+		//连接池管理器
381
+		connMgr = new PoolingHttpClientConnectionManager(registry);
382
+		//请求池最大连接数
383
+		connMgr.setMaxTotal(MAX_TOTAL);
384
+		//但域名最大的连接数
385
+		connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL);
386
+	}
387
+
388
+
389
+
390
+
391
+	/**
392
+	 * @description 设置重试机制
393
+	 *
394
+	 * @author 澄泓
395
+	 */
396
+	private static void cfgRetryHandler() {
397
+		retryHandler = new HttpRequestRetryHandler() {
398
+
399
+			@Override
400
+			public boolean retryRequest(IOException e, int excCount, HttpContext ctx) {
401
+				//超过最大重试次数,就放弃
402
+				if(excCount > MAX_RETRY) {
403
+					return false;
404
+				}
405
+				//服务器丢掉了链接,就重试
406
+				if(e instanceof NoHttpResponseException) {
407
+					return true;
408
+				}
409
+				//不重试SSL握手异常
410
+				if(e instanceof SSLHandshakeException) {
411
+					return false;
412
+				}
413
+				//中断
414
+				if(e instanceof InterruptedIOException) {
415
+					return false;
416
+				}
417
+				//目标服务器不可达
418
+				if(e instanceof UnknownHostException) {
419
+					return false;
420
+				}
421
+				//连接超时
422
+				//SSL异常
423
+				if(e instanceof SSLException) {
424
+					return false;
425
+				}
426
+
427
+				HttpClientContext clientCtx = HttpClientContext.adapt(ctx);
428
+				HttpRequest req = clientCtx.getRequest();
429
+				//如果是幂等请求,就再次尝试
430
+				if(!(req instanceof HttpEntityEnclosingRequest)) {
431
+					return true;
432
+				}
433
+				return false;
434
+			}
435
+		};
436
+	}
437
+
438
+    /**
439
+     * 忽略域名校验
440
+     */
441
+    private static SSLConnectionSocketFactory sslConnectionSocketFactory() throws EsignDemoException {
442
+        try {
443
+            SSLContext ctx = SSLContext.getInstance("TLS");    // 创建一个上下文(此处指定的协议类型似乎不是重点)
444
+            X509TrustManager tm = new X509TrustManager() {     // 创建一个跳过SSL证书的策略
445
+                public X509Certificate[] getAcceptedIssuers() {
446
+                    return null;
447
+                }
448
+
449
+                public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
450
+                }
451
+
452
+                public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
453
+                }
454
+            };
455
+            ctx.init(null, new TrustManager[] { tm }, null);    // 使用上面的策略初始化上下文
456
+            return new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
457
+        }catch (Exception e){
458
+            EsignDemoException ex = new EsignDemoException("忽略域名校验失败",e);
459
+            ex.initCause(e);
460
+            throw ex;
461
+        }
462
+
463
+    }
464
+
465
+	/**
466
+	 * @description 获取单例HttpClient
467
+	 *
468
+	 * @return
469
+	 * @author 澄泓
470
+	 */
471
+	private static synchronized CloseableHttpClient getHttpClient() throws EsignDemoException {
472
+		if(httpClient==null) {
473
+			CredentialsProvider credsProvider = new BasicCredentialsProvider();
474
+			credsProvider.setCredentials(new AuthScope(PROXY_IP,PROXY_PORT),new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD));
475
+			cfgPoolMgr();
476
+			cfgRetryHandler();
477
+            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
478
+            httpClient =  httpClientBuilder.setDefaultCredentialsProvider(credsProvider).setConnectionManager(connMgr).setRetryHandler(retryHandler).build();
479
+		}
480
+		return httpClient;
481
+
482
+	}
483
+	//------------------------------私有方法end----------------------------------------------
484
+
485
+
486
+}

+ 284
- 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/FileTransformation.java Просмотреть файл

@@ -0,0 +1,284 @@
1
+/*
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4
+ * the License. You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ * specific language governing permissions and limitations under the License.
11
+ */
12
+package com.ruoyi.common.constant;
13
+
14
+import com.ruoyi.common.exception.EsignDemoException;
15
+import org.apache.commons.codec.binary.Base64;
16
+
17
+import java.io.*;
18
+import java.net.HttpURLConnection;
19
+import java.net.URL;
20
+import java.security.MessageDigest;
21
+import java.security.NoSuchAlgorithmException;
22
+import java.util.HashMap;
23
+import java.util.Map;
24
+
25
+/**
26
+ * @author 澄泓
27
+ * @version JDK1.7
28
+ * @description 文件转换类
29
+ * @date 2020/10/26 10:47
30
+ */
31
+public class FileTransformation {
32
+
33
+    /**
34
+     * 传入本地文件路径转二进制byte
35
+     *
36
+     * @param srcFilePath 本地文件路径
37
+     * @return
38
+     * @throws EsignDemoException
39
+     */
40
+    public static byte[] fileToBytes(String srcFilePath) throws EsignDemoException {
41
+        return getBytes(srcFilePath);
42
+    }
43
+
44
+    /**
45
+     * 图片转base64
46
+     *
47
+     * @param filePath 本地文件路径
48
+     * @return
49
+     * @throws EsignDemoException
50
+     */
51
+    public static String fileToBase64(String filePath) throws EsignDemoException {
52
+        byte[] bytes;
53
+        String base64 = null;
54
+        bytes = fileToBytes(filePath);
55
+        base64 = Base64.encodeBase64String(bytes);
56
+        base64 = base64.replaceAll("\r\n", "");
57
+        return base64;
58
+    }
59
+
60
+    public static void main(String[] args) throws EsignDemoException {
61
+        System.out.println(getFileContentMD5("D:\\文档\\PLT2022-02124CT.pdf"));
62
+    }
63
+
64
+    /***
65
+     * 计算文件内容的Content-MD5
66
+     * @param filePath 文件路径
67
+     * @return
68
+     */
69
+    public static String getFileContentMD5(String filePath) throws EsignDemoException {
70
+        // 获取文件MD5的二进制数组(128位)
71
+        byte[] bytes = getFileMD5Bytes128(filePath);
72
+        // 对文件MD5的二进制数组进行base64编码
73
+        return new String(Base64.encodeBase64String(bytes));
74
+    }
75
+
76
+    /**
77
+     * 下载文件
78
+     *
79
+     * @param httpUrl 网络文件地址url
80
+     * @return
81
+     */
82
+    public static boolean downLoadFileByUrl(String httpUrl, String dir) throws EsignDemoException {
83
+        InputStream fis = null;
84
+        FileOutputStream fileOutputStream = null;
85
+        try {
86
+            URL url = new URL(httpUrl);
87
+            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
88
+            httpConn.connect();
89
+            fis = httpConn.getInputStream();
90
+            fileOutputStream = new FileOutputStream(new File(dir));
91
+            byte[] md5Bytes = null;
92
+
93
+            byte[] buffer = new byte[1024];
94
+            int length = -1;
95
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
96
+                fileOutputStream.write(buffer, 0, length);
97
+            }
98
+        } catch (IOException e) {
99
+            EsignDemoException ex = new EsignDemoException("获取文件流异常", e);
100
+            ex.initCause(e);
101
+            throw ex;
102
+        } finally {
103
+            try {
104
+                if (fis != null) {
105
+                    fis.close();
106
+                }
107
+                if (fileOutputStream != null) {
108
+                    fileOutputStream.close();
109
+                }
110
+            } catch (IOException e) {
111
+                EsignDemoException ex = new EsignDemoException("关闭文件流异常", e);
112
+                ex.initCause(e);
113
+                throw ex;
114
+            }
115
+        }
116
+        return true;
117
+    }
118
+
119
+
120
+    /**
121
+     * 网络文件转二进制MD5数组并获取文件大小
122
+     *
123
+     * @param fileUrl 网络文件地址url
124
+     * @return
125
+     */
126
+    public static Map fileUrlToBytes(String fileUrl) throws EsignDemoException {
127
+        HashMap<String, Object> map = new HashMap<String, Object>();
128
+        try {
129
+            URL url = new URL(fileUrl);
130
+            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
131
+            httpConn.connect();
132
+            InputStream fis = httpConn.getInputStream();
133
+            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
134
+            outStream.close();
135
+            map.put("fileSize", fis.available());
136
+            byte[] md5Bytes = null;
137
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
138
+            byte[] buffer = new byte[1024];
139
+            int length = -1;
140
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
141
+                md5.update(buffer, 0, length);
142
+                outStream.write(buffer, 0, length);
143
+            }
144
+            md5Bytes = md5.digest();
145
+            byte[] fileData = outStream.toByteArray();
146
+            map.put("fileData", fileData);
147
+            outStream.close();
148
+            fis.close();
149
+            map.put("md5Bytes", md5Bytes);
150
+        } catch (IOException e) {
151
+            EsignDemoException ex = new EsignDemoException("获取文件流异常", e);
152
+            ex.initCause(e);
153
+            throw ex;
154
+        } catch (NoSuchAlgorithmException e) {
155
+            EsignDemoException ex = new EsignDemoException("文件计算异常", e);
156
+            ex.initCause(e);
157
+            throw ex;
158
+        }
159
+        return map;
160
+    }
161
+
162
+    /***
163
+     * 获取文件MD5的二进制数组(128位)
164
+     * @param filePath
165
+     * @return
166
+     * @throws EsignDemoException
167
+     */
168
+    public static byte[] getFileMD5Bytes128(String filePath) throws EsignDemoException {
169
+        FileInputStream fis = null;
170
+        byte[] md5Bytes = null;
171
+        try {
172
+            File file = new File(filePath);
173
+            fis = new FileInputStream(file);
174
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
175
+            byte[] buffer = new byte[1024];
176
+            int length = -1;
177
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
178
+                md5.update(buffer, 0, length);
179
+            }
180
+            md5Bytes = md5.digest();
181
+            fis.close();
182
+        } catch (FileNotFoundException e) {
183
+            EsignDemoException ex = new EsignDemoException("文件找不到", e);
184
+            ex.initCause(e);
185
+            throw ex;
186
+        } catch (NoSuchAlgorithmException e) {
187
+            EsignDemoException ex = new EsignDemoException("不支持此算法", e);
188
+            ex.initCause(e);
189
+            throw ex;
190
+        } catch (IOException e) {
191
+            EsignDemoException ex = new EsignDemoException("输入流或输出流异常", e);
192
+            ex.initCause(e);
193
+            throw ex;
194
+        } finally {
195
+            if (fis != null) {
196
+                try {
197
+                    fis.close();
198
+                } catch (IOException e) {
199
+                    EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e);
200
+                    ex.initCause(e);
201
+                    throw ex;
202
+                }
203
+            }
204
+        }
205
+        return md5Bytes;
206
+    }
207
+
208
+    /**
209
+     * @param path
210
+     * @return
211
+     * @throws EsignDemoException
212
+     * @description 根据文件路径,获取文件base64
213
+     * @author 宫清
214
+     * @date 2019年7月21日 下午4:22:08
215
+     */
216
+    public static String getBase64Str(String path) throws EsignDemoException {
217
+        InputStream is = null;
218
+        try {
219
+            is = new FileInputStream(new File(path));
220
+            byte[] bytes = new byte[is.available()];
221
+            is.read(bytes);
222
+            return Base64.encodeBase64String(bytes);
223
+        } catch (Exception e) {
224
+            EsignDemoException ex = new EsignDemoException("获取文件输入流失败", e);
225
+            ex.initCause(e);
226
+            throw ex;
227
+        } finally {
228
+            if (is != null) {
229
+                try {
230
+                    is.close();
231
+                } catch (IOException e) {
232
+                    EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e);
233
+                    ex.initCause(e);
234
+                    throw ex;
235
+                }
236
+            }
237
+        }
238
+    }
239
+
240
+    /**
241
+     * @param path 文件路径
242
+     * @return
243
+     * @description 获取文件名称
244
+     * @author 宫清
245
+     * @date 2019年7月21日 下午8:21:16
246
+     */
247
+    public static String getFileName(String path) {
248
+        return new File(path).getName();
249
+    }
250
+
251
+    /**
252
+     * @param filePath {@link String} 文件地址
253
+     * @return
254
+     * @throws EsignDemoException
255
+     * @description 获取文件字节流
256
+     * @date 2019年7月10日 上午9:17:00
257
+     * @author 宫清
258
+     */
259
+    public static byte[] getBytes(String filePath) throws EsignDemoException {
260
+        File file = new File(filePath);
261
+        FileInputStream fis = null;
262
+        byte[] buffer = null;
263
+        try {
264
+            fis = new FileInputStream(file);
265
+            buffer = new byte[(int) file.length()];
266
+            fis.read(buffer);
267
+        } catch (Exception e) {
268
+            EsignDemoException ex = new EsignDemoException("获取文件字节流失败", e);
269
+            ex.initCause(e);
270
+            throw ex;
271
+        } finally {
272
+            if (fis != null) {
273
+                try {
274
+                    fis.close();
275
+                } catch (IOException e) {
276
+                    EsignDemoException ex = new EsignDemoException("关闭文件字节流失败", e);
277
+                    ex.initCause(e);
278
+                    throw ex;
279
+                }
280
+            }
281
+        }
282
+        return buffer;
283
+    }
284
+}

+ 24
- 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignCoreSdkInfo.java Просмотреть файл

@@ -0,0 +1,24 @@
1
+package com.ruoyi.common.core.domain.entity;
2
+/**
3
+ * esignSDK-core信息类
4
+ * @author  澄泓
5
+ * @date  2022/2/22 13:59
6
+ * @version
7
+ */
8
+public class EsignCoreSdkInfo {
9
+    private static final String SdkVersion="Esign-Sdk-Core1.0";
10
+    private static final String SupportedVersion="JDK1.7 MORE THAN";
11
+
12
+    private static final String Info="sdk-esign-api核心工具包,主要处理e签宝公有云产品接口调用时的签名计算以及网络请求,通过EsignHttpHelper.signAndBuildSignAndJsonHeader构造签名鉴权+json数据格式的请求头,通过HttpHelper.doCommHttp方法入参发起网络请求。让开发者无需关注具体的请求签名算法,专注于接口业务的json参数构造";
13
+    public static String getSdkVersion() {
14
+        return SdkVersion;
15
+    }
16
+
17
+    public static String getInfo() {
18
+        return Info;
19
+    }
20
+
21
+    public static String getSupportedVersion() {
22
+        return SupportedVersion;
23
+    }
24
+}

+ 24
- 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/EsignHttpResponse.java Просмотреть файл

@@ -0,0 +1,24 @@
1
+package com.ruoyi.common.core.domain.entity;
2
+/**
3
+ * 网络请求的response类
4
+ */
5
+public class EsignHttpResponse {
6
+    private int status;
7
+    private String body;
8
+
9
+    public int getStatus() {
10
+        return status;
11
+    }
12
+
13
+    public void setStatus(int status) {
14
+        this.status = status;
15
+    }
16
+
17
+    public String getBody() {
18
+        return body;
19
+    }
20
+
21
+    public void setBody(String body) {
22
+        this.body = body;
23
+    }
24
+}

+ 39
- 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/EsignRequestType.java Просмотреть файл

@@ -0,0 +1,39 @@
1
+package com.ruoyi.common.enums;
2
+
3
+import org.apache.http.client.methods.*;
4
+
5
+/**
6
+ * @description 请求类型
7
+ * @author 澄泓
8
+ * @since JDK1.7
9
+ */
10
+public enum EsignRequestType {
11
+
12
+	POST{
13
+		@Override
14
+		public HttpRequestBase getHttpType(String url) {
15
+			return new HttpPost(url);
16
+		}
17
+	},
18
+	GET{
19
+		@Override
20
+		public HttpRequestBase getHttpType(String url) {
21
+			return new HttpGet(url);
22
+		}
23
+	},
24
+	DELETE{
25
+		@Override
26
+		public HttpRequestBase getHttpType(String url) {
27
+			return new HttpDelete(url);
28
+		}
29
+	},
30
+	PUT{
31
+		@Override
32
+		public HttpRequestBase getHttpType(String url) {
33
+			return new HttpPut(url);
34
+		}
35
+	},
36
+	;
37
+
38
+   public abstract HttpRequestBase getHttpType(String url);
39
+}

+ 36
- 0
ruoyi-common/src/main/java/com/ruoyi/common/exception/EsignDemoException.java Просмотреть файл

@@ -0,0 +1,36 @@
1
+package com.ruoyi.common.exception;
2
+
3
+/**
4
+ * description 自定义全局异常
5
+ * @author 澄泓
6
+ * datetime 2019年7月1日上午10:43:24
7
+ */
8
+public class EsignDemoException extends Exception {
9
+
10
+	private static final long serialVersionUID = 4359180081622082792L;
11
+	private Exception e;
12
+
13
+	public EsignDemoException(String msg) {
14
+		super(msg);
15
+	}
16
+
17
+	public EsignDemoException(String msg, Throwable cause) {
18
+		super(msg,cause);
19
+	}
20
+
21
+	public EsignDemoException(){
22
+
23
+	}
24
+
25
+	public Exception getE() {
26
+		return e;
27
+	}
28
+
29
+	public void setE(Exception e) {
30
+		this.e = e;
31
+	}
32
+
33
+
34
+
35
+
36
+}

+ 178
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/EsignHttpHelper.java Просмотреть файл

@@ -0,0 +1,178 @@
1
+package com.ruoyi.common.utils;
2
+
3
+
4
+import com.ruoyi.common.constant.EsignEncryption;
5
+import com.ruoyi.common.constant.EsignHeaderConstant;
6
+import com.ruoyi.common.constant.EsignHttpCfgHelper;
7
+import com.ruoyi.common.core.domain.entity.EsignCoreSdkInfo;
8
+import com.ruoyi.common.core.domain.entity.EsignHttpResponse;
9
+import com.ruoyi.common.enums.EsignRequestType;
10
+import com.ruoyi.common.exception.EsignDemoException;
11
+import org.slf4j.Logger;
12
+import org.slf4j.LoggerFactory;
13
+
14
+import java.util.HashMap;
15
+import java.util.Map;
16
+
17
+/**
18
+ * @description Http 请求 辅助类
19
+ * @author 澄泓
20
+ * @since JDK1.7
21
+ */
22
+public class EsignHttpHelper {
23
+	private static final Logger LOGGER = LoggerFactory.getLogger(EsignHttpHelper.class);
24
+
25
+	/**
26
+	 * 不允许外部创建实例
27
+	 */
28
+	private EsignHttpHelper() {
29
+
30
+	}
31
+
32
+	/**
33
+	 * @description 发送常规HTTP 请求
34
+	 *
35
+	 * @param reqType 请求方式
36
+	 * @param url 请求路径
37
+	 * @param paramStr 请求参数
38
+	 * @return
39
+	 * @throws EsignDemoException
40
+	 * @author 澄泓
41
+	 */
42
+	public static EsignHttpResponse doCommHttp(String host, String url, EsignRequestType reqType, Object paramStr , Map<String,String> httpHeader, boolean debug) throws EsignDemoException {
43
+
44
+		return EsignHttpCfgHelper.sendHttp(reqType, host+url,httpHeader, paramStr, debug);
45
+
46
+	}
47
+
48
+
49
+	/**
50
+	 * @description 发送文件流上传 HTTP 请求
51
+	 *
52
+	 * @param reqType 请求方式
53
+	 * @param uploadUrl 请求路径
54
+	 * @param param 请求参数
55
+	 * @param fileContentMd5 文件fileContentMd5
56
+	 * @param contentType 文件MIME类型
57
+	 * @return
58
+	 * @throws EsignDemoException
59
+	 * @author 澄泓
60
+	 */
61
+	public static EsignHttpResponse doUploadHttp( String uploadUrl,EsignRequestType reqType,byte[] param, String fileContentMd5,
62
+												 String contentType, boolean debug) throws EsignDemoException {
63
+		Map<String, String> uploadHeader = buildUploadHeader(fileContentMd5, contentType);
64
+		if(debug){
65
+			LOGGER.info("----------------------------start------------------------");
66
+			LOGGER.info("fileContentMd5:{}",fileContentMd5);
67
+			LOGGER.info("contentType:{}",contentType);
68
+		}
69
+		return EsignHttpCfgHelper.sendHttp(reqType,uploadUrl, uploadHeader, param,debug);
70
+	}
71
+
72
+
73
+
74
+	/**
75
+	 * @description 构建一个签名鉴权+json数据的esign请求头
76
+	 * @return
77
+	 * @author 澄泓
78
+	 */
79
+	public static Map<String, String> buildSignAndJsonHeader(String projectId,String contentMD5,String accept,String contentType,String authMode) {
80
+
81
+		Map<String, String> header = new HashMap<>();
82
+		header.put("X-Tsign-Open-App-Id", projectId);
83
+		header.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
84
+		header.put("X-Tsign-Open-Ca-Timestamp", EsignEncryption.timeStamp());
85
+		header.put("Accept",accept);
86
+		header.put("Content-MD5",contentMD5);
87
+		header.put("Content-Type", contentType);
88
+		header.put("X-Tsign-Open-Auth-Mode", authMode);
89
+		return header;
90
+	}
91
+
92
+	/**
93
+	 * 签名计算并且构建一个签名鉴权+json数据的esign请求头
94
+	 * @param  httpMethod
95
+	 *      *         The name of a supported {@linkplain java.nio.charset.Charset
96
+	 *      *         charset}
97
+	 * @return
98
+	 */
99
+	public static Map<String,String> signAndBuildSignAndJsonHeader(String projectId, String secret,String paramStr,String httpMethod,String url,boolean debug) throws EsignDemoException {
100
+		String contentMD5="";
101
+		//统一转大写处理
102
+		httpMethod = httpMethod.toUpperCase();
103
+		if("GET".equals(httpMethod)||"DELETE".equals(httpMethod)){
104
+			paramStr=null;
105
+			contentMD5="";
106
+		} else if("PUT".equals(httpMethod)||"POST".equals(httpMethod)){
107
+			//对body体做md5摘要
108
+			contentMD5= EsignEncryption.doContentMD5(paramStr);
109
+		}else{
110
+			throw new EsignDemoException(String.format("不支持的请求方法%s",httpMethod));
111
+		}
112
+		//构造一个初步的请求头
113
+		Map<String, String> esignHeaderMap = buildSignAndJsonHeader(projectId, contentMD5, EsignHeaderConstant.ACCEPT.VALUE(), EsignHeaderConstant.CONTENTTYPE_JSON.VALUE(), EsignHeaderConstant.AUTHMODE.VALUE());
114
+		//排序
115
+		url=EsignEncryption.sortApiUrl(url);
116
+		//传入生成的bodyMd5,加上其他请求头部信息拼接成字符串
117
+		String message = EsignEncryption.appendSignDataString(httpMethod, esignHeaderMap.get("Content-MD5"),esignHeaderMap.get("Accept"),esignHeaderMap.get("Content-Type"),esignHeaderMap.get("Headers"),esignHeaderMap.get("Date"), url);
118
+		//整体做sha256签名
119
+		String reqSignature = EsignEncryption.doSignatureBase64(message, secret);
120
+		//请求头添加签名值
121
+		esignHeaderMap.put("X-Tsign-Open-Ca-Signature",reqSignature);
122
+		if(debug){
123
+			LOGGER.info("----------------------------start------------------------");
124
+			LOGGER.info("待计算body值:{}", paramStr+"\n");
125
+			LOGGER.info("MD5值:{}",contentMD5+"\n");
126
+			LOGGER.info("待签名字符串:{}",message+"\n");
127
+			LOGGER.info("签名值:{}",reqSignature+"\n");
128
+		}
129
+		return esignHeaderMap;
130
+	}
131
+
132
+
133
+	/**
134
+	 * @description 构建一个Token鉴权+jsons数据的esign请求头
135
+	 * @return
136
+	 * @author 澄泓
137
+	 */
138
+	public static Map<String, String> buildTokenAndJsonHeader(String appid,String token) {
139
+		Map<String, String> esignHeader = new HashMap<>();
140
+		esignHeader.put("X-Tsign-Open-Version-Sdk", EsignCoreSdkInfo.getSdkVersion());
141
+		esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_JSON.VALUE());
142
+		esignHeader.put("X-Tsign-Open-App-Id", appid);
143
+		esignHeader.put("X-Tsign-Open-Token", token);
144
+		return esignHeader;
145
+	}
146
+
147
+	/**
148
+	 * @description 构建一个form表单数据的esign请求头
149
+	 * @return
150
+	 * @author 澄泓
151
+	 */
152
+	public static Map<String, String> buildFormDataHeader(String appid) {
153
+		Map<String, String> esignHeader = new HashMap<>();
154
+		esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
155
+		esignHeader.put("X-Tsign-Open-Authorization-Version","v2");
156
+		esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_FORMDATA.VALUE());
157
+		esignHeader.put("X-Tsign-Open-App-Id", appid);
158
+		return esignHeader;
159
+	}
160
+
161
+	/**
162
+	 * @description 创建文件流上传 请求头
163
+	 *
164
+	 * @param fileContentMd5
165
+	 * @param contentType
166
+	 * @return
167
+	 * @author 澄泓
168
+	 */
169
+	public static Map<String, String> buildUploadHeader(String fileContentMd5, String contentType) {
170
+		Map<String, String> header = new HashMap<>();
171
+		header.put("Content-MD5", fileContentMd5);
172
+		header.put("Content-Type", contentType);
173
+
174
+		return header;
175
+	}
176
+
177
+	// ------------------------------私有方法end----------------------------------------------
178
+}

+ 57
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/EsignFileBean.java Просмотреть файл

@@ -0,0 +1,57 @@
1
+package com.ruoyi.common.utils.bean;
2
+
3
+
4
+import com.ruoyi.common.constant.FileTransformation;
5
+import com.ruoyi.common.exception.EsignDemoException;
6
+
7
+import java.io.File;
8
+
9
+/**
10
+ * @description  文件基础信息封装类
11
+ * @author  澄泓
12
+ * @date  2020/10/26 14:54
13
+ * @version JDK1.7
14
+ */
15
+public class EsignFileBean {
16
+    //文件名称
17
+    private String fileName;
18
+    //文件大小
19
+    private int fileSize;
20
+    //文件内容MD5
21
+    private String fileContentMD5;
22
+    //文件地址
23
+    private String filePath;
24
+
25
+
26
+    public EsignFileBean(String filePath) throws EsignDemoException {
27
+            this.filePath=filePath;
28
+            this.fileContentMD5 = FileTransformation.getFileContentMD5(filePath);
29
+            File file = new File(filePath);
30
+            if (!file.exists()) {
31
+                throw new EsignDemoException("文件不存在");
32
+            }
33
+            this.fileName = file.getName();
34
+            this.fileSize = (int) file.length();
35
+    }
36
+
37
+    public String getFileName() {
38
+        return fileName;
39
+    }
40
+
41
+    public int getFileSize() {
42
+        return fileSize;
43
+    }
44
+
45
+    public String getFileContentMD5() {
46
+        return fileContentMD5;
47
+    }
48
+
49
+    /**
50
+     * 传入本地文件地址获取二进制数据
51
+     * @return
52
+     * @throws EsignDemoException
53
+     */
54
+    public byte[] getFileBytes() throws EsignDemoException {
55
+        return FileTransformation.fileToBytes(filePath);
56
+    }
57
+}

+ 43
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/SaaSAPIFileUtils.java Просмотреть файл

@@ -0,0 +1,43 @@
1
+package com.ruoyi.common.utils.file;
2
+
3
+import com.ruoyi.common.config.EsignDemoConfig;
4
+import com.ruoyi.common.constant.EsignHeaderConstant;
5
+import com.ruoyi.common.core.domain.entity.EsignHttpResponse;
6
+import com.ruoyi.common.enums.EsignRequestType;
7
+import com.ruoyi.common.exception.EsignDemoException;
8
+import com.ruoyi.common.utils.EsignHttpHelper;
9
+import com.ruoyi.common.utils.bean.EsignFileBean;
10
+
11
+import java.util.Map;
12
+
13
+public class SaaSAPIFileUtils {
14
+    private static String eSignHost= EsignDemoConfig.EsignHost;
15
+    private static String eSignAppId= EsignDemoConfig.EsignAppId;
16
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
17
+    /**
18
+     * 获取文件上传地址
19
+     *
20
+     * @return
21
+     */
22
+    public static EsignHttpResponse getUploadUrl(String filePath) throws EsignDemoException {
23
+        //自定义的文件封装类,传入文件地址可以获取文件的名称大小,文件流等数据
24
+        EsignFileBean esignFileBean = new EsignFileBean(filePath);
25
+        String apiaddr = "/v3/files/file-upload-url";
26
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
27
+        String jsonParm = "{\n" +
28
+                "    \"contentMd5\": \"" + esignFileBean.getFileContentMD5() + "\",\n" +
29
+                "    \"fileName\":\"" + esignFileBean.getFileName() + "\"," +
30
+                "    \"fileSize\": " + esignFileBean.getFileSize() + ",\n" +
31
+                "    \"convertToPDF\":" +true+ ",\n" +
32
+                "    \"contentType\": \"" + EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE() + "\"\n" +
33
+                "}";
34
+        //请求方法
35
+        EsignRequestType requestType = EsignRequestType.POST;
36
+        //生成签名鉴权方式的的header
37
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
38
+        //发起接口请求
39
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
40
+    }
41
+
42
+
43
+}