package com.friday.custody.service.trustService.ebscn.utils;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <pre>
 * 摘  要：网络请求辅助类
 *
 * 作  者：吴丰辉(wufh@ebscn.com)
 * 时  间：2021/11/09 20:45
 *
 * Copyright © 版权2021 光大证券股份有限公司
 * </pre>
 **/
public class HttpUtils {

    /**
     * GET 请求
     *
     * @param url 目标地址
     * @return 结果
     */
    public static String get(String url) {
        return get(url, null);
    }

    /**
     * GET 请求
     *
     * @param url     目标地址
     * @param headers 请求头
     * @return 结果
     */
    public static String get(String url, Map<String, String> headers) {
        return httpRequest(url, "get", headers, null);
    }

    /**
     * POST 请求
     *
     * @param url    目标地址
     * @param params 请求参数
     * @return 结果
     */
    public static String post(String url, Map<String, Object> params) {
        return post(url, null, params);
    }

    /**
     * POST 请求
     *
     * @param url     目标地址
     * @param headers 请求头
     * @param params  请求参数
     * @return 结果
     */
    public static String post(String url, Map<String, String> headers, Map<String, Object> params) {
        return httpRequest(url, "post", headers, params);
    }

    /**
     * http请求
     *
     * @param url     目标地址
     * @param method  请求方法
     * @param headers 请求头
     * @param params  请求参数
     * @return 结果
     */
    public static String httpRequest(String url, String method, Map<String, String> headers, Map<String, Object> params) {
        // 根据url确定是否是https请求，并创建客户端
        CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(
                StringUtils.startsWith(url, "https:") ? getSSLSocketFactory() : null).build();
        try {
            //创建post方式请求对象
            HttpRequestBase httpReq;

            if ("get".equalsIgnoreCase(method)) {
                // GET方法
                httpReq = new HttpGet(url);
            } else {
                // 其他情况使用POST方法，需要细分时再加分支
                httpReq = new HttpPost(url);

                // 指定默认报文头Content-type
                httpReq.setHeader("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

                // POST 时需要组装参数
                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                if (null != params) {
                    for (String paramName : params.keySet()) {
                        NameValuePair nameValuePair = new BasicNameValuePair(paramName,
                                ObjectUtils.toString(params.get(paramName)));
                        parameters.add(nameValuePair);
                    }
                }
                // 设置参数
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
                ((HttpPost) httpReq).setEntity(urlEncodedFormEntity);
            }

            // 指定默认Host和Referer
            httpReq.setHeader("Host", httpReq.getURI().getHost());
            httpReq.setHeader("Referer", url);
            if (null != headers) {
                // 补充自定义头
                for (String headerName : headers.keySet()) {
                    httpReq.setHeader(headerName, headers.get(headerName));
                }
            }

            //执行请求操作，并拿到结果（同步阻塞）
            CloseableHttpResponse response = client.execute(httpReq);

            //获取结果实体
            HttpEntity entity = response.getEntity();
            String resMes = null;
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                resMes = EntityUtils.toString(entity, "UTF-8");
            }

            EntityUtils.consume(entity);
            //释放链接
            response.close();

            return resMes;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     * 绕过验证
     */
    public static SSLConnectionSocketFactory getSSLSocketFactory() {
        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager UnSafeTrustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }
        };

        try {
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, new TrustManager[]{UnSafeTrustManager}, null);
            ////创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
            return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

