001package top.cenze.utils.http.request;
002
003import cn.hutool.core.collection.CollectionUtil;
004import cn.hutool.core.util.StrUtil;
005import cn.hutool.crypto.digest.DigestUtil;
006import cn.hutool.http.HttpRequest;
007import cn.hutool.http.HttpResponse;
008import cn.hutool.http.HttpUtil;
009import cn.hutool.http.Method;
010import com.alibaba.fastjson.JSON;
011import com.alibaba.fastjson.parser.Feature;
012import lombok.extern.slf4j.Slf4j;
013import org.apache.commons.lang3.StringUtils;
014import org.springframework.util.CollectionUtils;
015
016import javax.net.ssl.*;
017import java.io.*;
018import java.net.HttpURLConnection;
019import java.net.URL;
020import java.util.*;
021
022/**
023 * https请求工具
024 * author: cz
025 */
026
027@Slf4j
028public class HttpsUtil {
029
030    public static <T> T post(String url, Map<String, String> headers, Class<T> clazz) {
031        return request(url, new HashMap<>(), headers, Method.POST, clazz);
032    }
033
034    public static <T> T postMap(String url, Map<String, Object> params, Map<String, String> headers, Class<T> clazz) {
035        return request(url, params, headers, Method.POST, clazz);
036    }
037
038    public static <T> T postMap(String url, Map<String, Object> params, Class<T> clazz) {
039        return request(url, params, null, Method.POST, clazz);
040    }
041
042    public static <T> T postObj(String url, Object obj, Class<T> clazz) {
043        return request(url, JSON.toJSONString(obj), null, Method.POST, clazz);
044    }
045
046    public static <T> T postObj(String url, Object obj, Map<String, String> headers, Class<T> clazz) {
047        return request(url, JSON.toJSONString(obj), headers, Method.POST, clazz);
048    }
049
050    public static <T> T postStr(String url, String str, Map<String, String> headers, Class<T> clazz) {
051        return request(url, str, headers, Method.POST, clazz);
052    }
053
054    public static <T> T get(String url, Map<String, String> headers, Class<T> clazz) {
055        return request(url, new HashMap<>(), headers, Method.GET, clazz);
056    }
057
058    public static <T> T getMap(String url, Map<String, Object> params, Map<String, String> headers, Class<T> clazz) {
059        return request(url, params, headers, Method.GET, clazz);
060    }
061
062    public static <T> T getObj(String url, Object obj, Map<String, String> headers, Class<T> clazz) {
063        return request(url, JSON.toJSONString(obj), headers, Method.GET, clazz);
064    }
065
066    public static <T> T getStr(String url, String str, Map<String, String> headers, Class<T> clazz) {
067        return request(url, str, headers, Method.GET, clazz);
068    }
069
070    public static <T> T putObj(String url, Object obj, Map<String, String> headers, Class<T> clazz) {
071        return request(url, JSON.toJSONString(obj), headers, Method.PUT, clazz);
072    }
073
074    public static <T> T del(String url, Map<String, String> headers, Class<T> clazz) {
075        return request(url, "", headers, Method.DELETE, clazz);
076    }
077
078    public static <T> T delObj(String url, Object obj, Map<String, String> headers, Class<T> clazz) {
079        return request(url, JSON.toJSONString(obj), headers, Method.DELETE, clazz);
080    }
081
082    public static String getCookie(String url, Map<String, Object> params) {
083        HttpRequest httpRequest = HttpUtil.createGet(url);
084        httpRequest.form(params);
085
086        log.info("getCookie url: {}, req: {}", url, JSON.toJSONString(params));
087        String result = httpRequest.execute()
088                .getCookieStr();
089        log.info("getCookie result: {}", result);
090
091        return result;
092    }
093
094    public static HttpResponse get(String url, Map<String, Object> params, Map<String, String> headers) {
095        // 创建HttpRequest对象,指定请求方式为GET,并设置URL
096        HttpRequest request = HttpRequest.get(url);
097
098        if (CollectionUtil.isNotEmpty(headers)) {
099            for (Map.Entry<String, String> head : headers.entrySet()) {
100                request.header(head.getKey(), head.getValue());
101            }
102        }
103
104        if (CollectionUtil.isNotEmpty(params)) {
105            request.form(params);
106        }
107
108        return request.execute();
109    }
110
111    public static <T> T request(String url, String str, Map<String, String> headers, Method method, Class<T> clazz) {
112        if (null == method) {
113            method = Method.POST;
114        }
115
116        HttpRequest httpRequest = HttpUtil.createRequest(method, url);
117        httpRequest.setConnectionTimeout(60000000);
118
119        if (CollectionUtil.isNotEmpty(headers)) {
120            for (Map.Entry<String, String> head : headers.entrySet()) {
121                httpRequest.header(head.getKey(), head.getValue());
122            }
123        }
124
125        if (StrUtil.isNotEmpty(str)) {
126            httpRequest.body(str);
127        }
128
129        log.info("request url: {}, req: {}", url, str);
130        String result = httpRequest.execute().body();
131        log.info("request result: {}", result);
132
133        if (!StringUtils.isBlank(result)) {
134            if (null != clazz) {
135                try {
136                    return JSON.parseObject(result, clazz);
137                } catch (Exception e) {
138                    log.error("request err: {}, result: {}", e.getMessage(), result);
139                }
140            } else {
141                return (T) result;
142            }
143        }
144
145        return null;
146    }
147
148    public static <T> T request(String url, Map<String, Object> params, Map<String, String> headers, Method method, Class<T> clazz) {
149        if (null == method) {
150            method = Method.POST;
151        }
152
153        HttpRequest httpRequest = HttpUtil.createRequest(method, url);
154
155        if (CollectionUtil.isNotEmpty(headers)) {
156            for (Map.Entry<String, String> head : headers.entrySet()) {
157                httpRequest.header(head.getKey(), head.getValue());
158            }
159        }
160
161        if (CollectionUtil.isNotEmpty(params)) {
162            httpRequest.form(params);
163        }
164
165        log.info("request url: {}, req: {}", url, JSON.toJSONString(params));
166        String result = httpRequest.execute().body();
167        log.info("request result: {}", result);
168
169        if (StrUtil.isNotEmpty(result)) {
170            if (null != clazz) {
171                try {
172                    return JSON.parseObject(result, clazz);
173                } catch (Exception e) {
174                    log.error("request err: {}, result: {}", e.getMessage(), result);
175                }
176            } else {
177                return (T) result;
178            }
179        }
180
181        return null;
182    }
183
184
185    /**
186     * 发送HTTPS请求
187     * 访问https资源时,忽略证书信任问题
188     * @param toURL 请求地址
189     * @param data 请求参数
190     * @param dateType 参数类型,“JSON”,other
191     * @return
192     * @throws Exception
193     */
194    public static String httpsPost(String toURL, String data, String dateType)
195            throws Exception {
196        StringBuffer bs = new StringBuffer();
197
198        //  直接通过主机认证
199        HostnameVerifier hv = new HostnameVerifier() {
200            @Override
201            public boolean verify(String arg0, SSLSession arg1) {
202                return true;
203            }
204        };
205        //  配置认证管理器
206        javax.net.ssl.TrustManager[] trustAllCerts = {new TrustAllTrustManager()};
207        SSLContext sc = SSLContext.getInstance("SSL");
208        SSLSessionContext sslsc = sc.getServerSessionContext();
209        sslsc.setSessionTimeout(0);
210        sc.init(null, trustAllCerts, null);
211        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
212        //  激活主机认证
213        HttpsURLConnection.setDefaultHostnameVerifier(hv);
214        URL url = new URL(toURL);
215        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
216        connection.setConnectTimeout(30000);
217        connection.setReadTimeout(30000);
218        connection.setDoOutput(true);
219        if("JSON".equalsIgnoreCase(dateType)){
220            connection.setRequestProperty("Content-Type","application/json;chert=UTF-8");
221        }else{
222            connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
223        }
224        OutputStreamWriter out = new OutputStreamWriter(
225                connection.getOutputStream(), "UTF-8");
226        out.write(data);
227        out.flush();
228        out.close();
229        connection.connect();
230        int code = ((HttpURLConnection) connection).getResponseCode();
231        InputStream is =  null;
232        if (code == 200) {
233            is = connection.getInputStream(); // 得到网络返回的正确输入流
234        } else {
235            is = ((HttpURLConnection) connection).getErrorStream(); // 得到网络返回的错误输入流
236        }
237        BufferedReader buffer = new BufferedReader(new InputStreamReader(is,"UTF-8"));
238
239        String l = null;
240        while ((l = buffer.readLine()) != null) {
241            bs.append(l);
242        }
243        //return bs.toString();
244        return String.valueOf(bs);
245    }
246
247    /**
248     * 对象转有map
249     *
250     * @param obj
251     * @return
252     */
253    public static Map<String, Object> objToMap(Object obj) {
254        return JSON.parseObject(JSON.toJSONString(obj), HashMap.class, Feature.OrderedField);
255    }
256
257    public static StringBuilder mapToSortStr(Map<String, Object> params) {
258        // 移除值为空的
259        params.entrySet().removeIf(
260                entry -> Objects.isNull(entry.getValue()) ||
261                "".equals(entry.getValue()));
262
263        List<Map.Entry<String, Object>> infoIds = new ArrayList<>(params.entrySet());
264        // 对所有传入参数按照字段名的ASCII码从小到大排序(字典序)
265        infoIds.sort((o1, o2) -> o1.getKey().compareToIgnoreCase(o2.getKey()));
266        StringBuilder sb = new StringBuilder();
267        for (Map.Entry<String, Object> infoId : infoIds) {
268            sb.append(infoId.getKey());
269            sb.append("=");
270            sb.append(infoId.getValue());
271            sb.append("&");
272        }
273
274        // 删除末尾的 "&"
275        sb.deleteCharAt(sb.length() - 1);
276
277        return sb;
278    }
279
280    /**
281     * map按Key顺序排序
282     * @param params
283     * @return
284     */
285    public static LinkedHashMap<String, Object> mapToSortMap(Map<String, Object> params) {
286        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
287
288        // 移除值为空的
289        params.entrySet().removeIf(
290                entry -> Objects.isNull(entry.getValue()) ||
291                        "".equals(entry.getValue()));
292
293        List<Map.Entry<String, Object>> infoIds = new ArrayList<>(params.entrySet());
294
295        // 对所有传入参数按照字段名的ASCII码从小到大排序(字典序)
296        infoIds.sort((o1, o2) -> o1.getKey().compareToIgnoreCase(o2.getKey()));
297        for (Map.Entry<String, Object> infoId : infoIds) {
298            map.put(infoId.getKey(), infoId.getValue());
299        }
300
301        return map;
302    }
303
304    /**
305     * obj 转 mac buff
306     * @param obj
307     * @return
308     */
309    public static String objToMacBuff(Object obj) {
310        StringBuilder sb = new StringBuilder();
311
312        Map<String, Object> mapParams = objToMap(obj);
313
314        LinkedHashMap<String, Object> map = mapToSortMap(mapParams);
315
316        for (Map.Entry<String, Object> e : mapParams.entrySet()) {
317            sb.append(" ").append(e.getValue());
318        }
319
320        return StrUtil.trim(sb.toString());
321    }
322
323    /**
324     * 获取排序参数签名
325     * @param key
326     * @return
327     * @throws UnsupportedEncodingException
328     */
329    public static String getSign(StringBuilder sb, String key) throws UnsupportedEncodingException {
330        // 最后拼接上key得到signTemp字符串
331        String signTemp = sb.append(key).toString();
332
333        // 对signTemp进行SHA-256运算,再将得到的字符串所有字符转换为大写,得到sign值signValue
334        String signValue = DigestUtil.sha256Hex(signTemp).toUpperCase();
335
336        return signValue;
337    }
338
339    /**
340     * 获取排序参数签名
341     * @param key
342     * @return
343     * @throws UnsupportedEncodingException
344     */
345    public static String getSign(Object obj, String key) throws UnsupportedEncodingException {
346        Map<String, Object> params = objToMap(obj);
347
348        StringBuilder sb = mapToSortStr(params);
349
350        String sign = getSign(sb, key);
351
352        return sign;
353    }
354
355    /**
356     * 获取排序参数签名(含签名参数)
357     * @param obj
358     * @param key
359     * @return
360     * @throws UnsupportedEncodingException
361     */
362    public static String getParamsAndSign(Object obj, String key) throws UnsupportedEncodingException {
363        Map<String, Object> params = objToMap(obj);
364
365        StringBuilder sb = mapToSortStr(params);
366
367        String sign = getSign(sb, key);
368
369        sb.append("&sign=").append(sign);
370
371        return sb.toString();
372    }
373}