
package com.fs.tzBankPay.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.tzbank.security.t.SM2Utils;
import com.tzbank.security.t.SM3Utils;
import com.tzbank.security.t.SM4Utils;
import com.tzbank.util.RandomUtils;
import com.tzbank.util.ReturnUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class TzBankUtil {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    private static final String UNICODE_TYPE = "utf-8";
    private static final Integer ConnectTimeout = 30000;
    private static final Integer ReadTimeout = 60000;
    public static final String SM2_IDA = "1234567812345678";
    public static final String ERROR00001 = "sdk00001";

    public TzBankUtil() {
    }

    public String tokenRequest(String requestUrl, String appKey, String appScrect, String param, String publicKey, String privateKey) throws Exception {
        this.logger.info("appKey:{}请求token：{}", appKey, requestUrl);
        String randomSec = RandomUtils.get16randoms();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd HHmmssS");
        String tranDate = format.format(new Date());
        JSONObject input = new JSONObject(16, true);
        input.put("equUniSeqNo", param);
        input.put("randomSec", randomSec);
        input.put("tranDate", tranDate);
        String inputJson = JSONObject.toJSONString(input);
        String sm3sgin = SM3Utils.getDigest(inputJson);
        String sgin = SM2Utils.signature(privateKey, sm3sgin, "1234567812345678");
        input.put("x-sign", sgin);
        String inputAndSginJson = JSONObject.toJSONString(input);
        String EyInputAndSginJson = SM4Utils.Encrypt(appScrect, inputAndSginJson);
        Map<String, Object> headerMap = new HashMap();
        headerMap.put("x-appKey", appKey);
        new HashMap();
        Map resultMap;
        if (requestUrl.startsWith("https")) {
            resultMap = this.httpsRequest(requestUrl, "POST", EyInputAndSginJson, headerMap);
        } else {
            resultMap = this.httpRequest(requestUrl, "POST", EyInputAndSginJson, headerMap);
        }

        if (!(Boolean)resultMap.get("isSsuccess")) {
            return (String)resultMap.get("returnJson");
        } else {
            String jso = (String)resultMap.get("returnJson");
            String result = SM4Utils.Decrypt(appScrect, jso);
            this.logger.info("获取token返回报文：{}", result);
            JSONObject outPut = (JSONObject)JSONObject.parse(result, new Feature[]{Feature.OrderedField});
            sgin = (String)outPut.get("x-sign");
            outPut.remove("x-sign");
            String message = JSONObject.toJSONString(outPut);
            String message3 = SM3Utils.getDigest(message);
            boolean signFlag = SM2Utils.verifySign(publicKey, message3, sgin, "1234567812345678");
            return signFlag ? message : JSONObject.toJSONString(ReturnUtil.getErrorMap("sdk00001", "签名验证不通过！！"));
        }
    }

    public String clientRequest(String requestUrl, String appKey, String randomSec, String inputJson, String publicKey, String privateKey, String token) throws Exception {
        this.logger.info("请求接口url：{}", requestUrl);
        this.logger.info("原始报文：{}", inputJson);
        JSONObject input = (JSONObject)JSONObject.parse(inputJson, new Feature[]{Feature.OrderedField});
        input.put("token", token);
        String inputAndToken = JSONObject.toJSONString(input);
        String sm3Sign = SM3Utils.getDigest(inputAndToken);
        String sgin = SM2Utils.signature(privateKey, sm3Sign, "1234567812345678");
        input.put("x-sign", sgin);
        Map<String, Object> headerMap = new HashMap();
        headerMap.put("x-appKey", appKey);
        headerMap.put("token", token);

        String sm4inputS = SM4Utils.Encrypt(randomSec, JSONObject.toJSONString(input));
        Map resultMap;
        if (requestUrl.startsWith("https")) {
            resultMap = this.httpsRequest(requestUrl, "POST", sm4inputS, headerMap);
        } else {
            resultMap = this.httpRequest(requestUrl, "POST", sm4inputS, headerMap);
        }
        System.out.println(resultMap);
        if (!(Boolean)resultMap.get("isSsuccess")) {
            return (String)resultMap.get("returnJson");
        } else {
            String jso = (String)resultMap.get("returnJson");
            String result = SM4Utils.Decrypt(randomSec, jso);
            JSONObject outPut = (JSONObject)JSONObject.parse(result, new Feature[]{Feature.OrderedField});
            sgin = (String)outPut.get("x-sign");
            outPut.remove("x-sign");
            String message = JSONObject.toJSONString(outPut);
            String message3 = SM3Utils.getDigest(message);
            boolean signFlag = SM2Utils.verifySign(publicKey, message3, sgin, "1234567812345678");
            return signFlag ? message : JSONObject.toJSONString(ReturnUtil.getErrorMap("sdk00001", "签名验证不通过！！"));
        }
    }

    public Map<String, Object> httpsRequest(String requestUrl, String requestMethod, String outputStr, Map<String, Object> headerMap) throws IOException {
        SSLContext ctx = null;

        try {
            ctx = SSLContext.getInstance("TLS");
            ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
        } catch (KeyManagementException var17) {
            this.logger.error(var17.getMessage());
        } catch (NoSuchAlgorithmException var18) {
            this.logger.error(var18.getMessage());
        }

        SSLSocketFactory ssf = ctx.getSocketFactory();
        boolean isSuccess = false;
        Map<String, Object> result = new HashMap();
        StringBuffer buffer = new StringBuffer();
        InputStream inputStream = null;
        URL url = new URL(requestUrl);
        HttpsURLConnection httpUrlConn = (HttpsURLConnection)url.openConnection();
        httpUrlConn.setSSLSocketFactory(ssf);
        httpUrlConn.setHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        httpUrlConn.setConnectTimeout(ConnectTimeout);
        httpUrlConn.setReadTimeout(ReadTimeout);
        httpUrlConn.setDoOutput(true);
        httpUrlConn.setDoInput(true);
        httpUrlConn.setUseCaches(false);
        httpUrlConn.setRequestProperty("Content-Type", "application/json");
        httpUrlConn.setRequestMethod(requestMethod);
        if (headerMap.get("token") != null && !"".equals(headerMap.get("token"))) {
            httpUrlConn.setRequestProperty("token", (String)headerMap.get("token"));
        }

        if (headerMap.get("x-appKey") != null && !"".equals(headerMap.get("x-appKey"))) {
            httpUrlConn.setRequestProperty("x-appKey", (String)headerMap.get("x-appKey"));
        }

        if (headerMap.get("x-sign") != null && !"".equals(headerMap.get("x-sign"))) {
            httpUrlConn.setRequestProperty("x-sign", (String)headerMap.get("x-sign"));
        }

        if ("GET".equalsIgnoreCase(requestMethod)) {
            httpUrlConn.connect();
        }

        if (outputStr != null) {
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpUrlConn.getOutputStream(), "utf-8"));
            writer.write(outputStr);
            writer.close();
        }

        int code = httpUrlConn.getResponseCode();
        if (601 == code) {
            String errBody = httpUrlConn.getHeaderField("errBody");
            result.put("isSsuccess", isSuccess);
            result.put("returnJson", new String((new BASE64Decoder()).decodeBuffer(URLDecoder.decode(errBody, "utf-8")), "utf-8"));
            return result;
        } else {
            inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;

            while((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            httpUrlConn.disconnect();
            isSuccess = true;
            result.put("isSsuccess", isSuccess);
            result.put("returnJson", buffer.toString());
            return result;
        }
    }

    public Map<String, Object> httpRequest(String requestUrl, String requestMethod, String outputStr, Map<String, Object> headerMap) throws IOException {
        boolean isSuccess = false;
        Map<String, Object> result = new HashMap();
        StringBuffer buffer = new StringBuffer();
        InputStream inputStream = null;
        URL url = new URL(requestUrl);
        HttpURLConnection httpUrlConn = (HttpURLConnection)url.openConnection();
        httpUrlConn.setConnectTimeout(ConnectTimeout);
        httpUrlConn.setReadTimeout(ReadTimeout);
        httpUrlConn.setDoOutput(true);
        httpUrlConn.setDoInput(true);
        httpUrlConn.setUseCaches(false);
        httpUrlConn.setRequestProperty("Content-Type", "application/json");
        httpUrlConn.setRequestMethod(requestMethod);
        if (headerMap.get("token") != null && !"".equals(headerMap.get("token"))) {
            httpUrlConn.setRequestProperty("token", (String)headerMap.get("token"));
        }

        if (headerMap.get("x-appKey") != null && !"".equals(headerMap.get("x-appKey"))) {
            httpUrlConn.setRequestProperty("x-appKey", (String)headerMap.get("x-appKey"));
        }

        if (headerMap.get("x-sign") != null && !"".equals(headerMap.get("x-sign"))) {
            httpUrlConn.setRequestProperty("x-sign", (String)headerMap.get("x-sign"));
        }

        if ("GET".equalsIgnoreCase(requestMethod)) {
            httpUrlConn.connect();
        }

        if (outputStr != null) {
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpUrlConn.getOutputStream(), "utf-8"));
            writer.write(outputStr);
            writer.close();
        }

        int code = httpUrlConn.getResponseCode();
        if (601 == code) {
            String errBody = httpUrlConn.getHeaderField("errBody");
            result.put("isSsuccess", isSuccess);
            result.put("returnJson", new String((new BASE64Decoder()).decodeBuffer(URLDecoder.decode(errBody, "utf-8")), "utf-8"));
            return result;
        } else {
            inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;

            while((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            httpUrlConn.disconnect();
            isSuccess = true;
            result.put("isSsuccess", isSuccess);
            result.put("returnJson", buffer.toString());
            return result;
        }
    }

    private static final class DefaultTrustManager implements X509TrustManager {
        private DefaultTrustManager() {
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }


}
