package com.paytend.api.service;

import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.paytend.api.utils.AESUtils;
import com.paytend.api.utils.PaytendUtil;
import com.paytend.api.utils.RSAUtils;


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;


/**
 * 接口demo paytend-api v2 版本
 *
 * @author wanghui
 */
public class PFService {

        //private static final String PAYTEND_BASE_URL = "http://localhost:8080";
    private static final String PAYTEND_BASE_URL = "https://sandbox-api.paytend.com";
    //private static final String PAYTEND_BASE_URL = "https://api.paytend.com/";
    private static final String PAYTEND_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/u/mZQZcLDiUbsOTrZtS6aeeLT/UA0kZq9yXT/rPoN6zhrrpbW2Xws6eNwCY8gcemAgvqU6nXJ/KewQXh0yTCuw0ud43wJ6CwWmmqhOnLyh8xclYUSiNz5yvcMSijgWPsa1qoE8bBgVi+nbDqQYO1kJsNLuQ0+5PyetDOv2jdH6dZZi6vYJUtCSpJTLPA0vQM+e2lx22E378fjshsiOw1EclvEo9oxOTQw7XRHb7jVqwAiYsn3c3fY0oefdlF4lgOUrrLWIXdO4xhGOFEZ/HF+t+kGTWQdR/XOLCQRzWvdXqMRFPLPyWiERCaaa2YUMxfXD8zeIVGaZr4g2E53O2QIDAQAB";
    private static final String PARTNER_ID = "188001000000085";
    private static final String PARTNER_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAPHshcJsBnnZfUg39yzJVaDbEoM2ss/wFRY42P3VsQQZq+PunOViksS28KezD3123URIb7OlSO9dK/HeriXYrfi3e1frkJLXBu5lszVgImYFk+kTjrrtWllmgkW7Cxd1yhyOFTwWhQlI8D70kjwqysPShVTc8OocGQcsHk49Ik4xAgMBAAECgYBcBe1HbFH2TZ2TN/6koZ0Zx9s94DOaVyeeQVeBDqT7+0vgMuapdpp/i1r1X25X+jvmemtK+WdJ7bYGlf7GVKqvwLqPGV/VsLXzmXH2U/5SQYKx1dPG7TAWKn3fQcgx6G9UYenzAAtvVgEJqk8U3E3M/QM1Mh5T8qzo7u0WudXKdQJBAPx6DelmFSFA/lAV0VdpDhCY4/OKXxINsV5pvlql9Dct3gUpIM+iGttzG/DwC4WUD4PoTokpF4LkY1dASpD9jNMCQQD1TMTrt+BRuXKE7+Kh/rBN5tkLYUbYpl05n6SOBs7torH30Mqc2FxIX0mnS7twfsp1p5wujKlLvIvNqHbXhoZrAkA/RrO/4CbBi9Fw7tblil3NCRRwUCidlLL0T5o2i8sWHTe8oV8oyp7iiwngq7inhMEStSEhvRu4YVcIYgOOLQ2jAkAk1nyUMa78Vu89y5CrZ0YuzMY3kUpEaueBKdpagec9hLtZTf+/gjaJn9W9y//AKypYdO1diD48Y3pTTkNappc1AkEAm4Y2q9MF0AxOB/Bku2YLxe0WrBcrVbc+Rjl/H9kRuRshmItsQBbQunSVxxbaHyfQmiWYHJZCGGrYJqAt2oLCcg==";
    private static final String VERSION = "2.0";
    private static final String SIGN_TYPE = "RSA";

    /**
     * @param
     */
    public static void main(String[] args) throws Exception {
        /**
         * Create merchant
          */
        //createMerchant();

        /**
         * Update merchant
          */
        //updateMerchant();

        /**
         * Query merchant
         */
        //getMerchant();

        /**
         * Merchant questionnaire
         */
        //questionnaire();

        /**
         * Upload supporting documents
         */
        //uploadSupportingDocuments();

        /**
         * settlementAccount
         */
        //settlementAccount();

        //openingMerchantPayment();

        //getSettlementFile();

        //getQRCodeLink();

        //
        //getTransactionInformation();
    }

    /**
     * 日志类
     */
    public static Log logger = LogFactory.get();


    /**
     * Create merchant
     */
    public static void createMerchant() throws Exception {
        Map<String, Object> bizData = new HashMap<>();

        Map<String, Object> registrationAddress = new HashMap<>();
        registrationAddress.put("addressLine", Base64.encode("beijing"));
        registrationAddress.put("addressLine2", Base64.encode("beijing"));
        registrationAddress.put("cityCode", "MT_1");
        registrationAddress.put("state", "");
        registrationAddress.put("postcode", "110110");
        registrationAddress.put("countryCode", "MT");

        Map<String, Object> businessAddress = new HashMap<>();
        businessAddress.put("addressLine", Base64.encode("beijing"));
        businessAddress.put("addressLine2", Base64.encode("beijing"));
        businessAddress.put("cityCode", "MT_1");
        businessAddress.put("state", "");
        businessAddress.put("postcode", "110110");
        businessAddress.put("countryCode", "MT");


        Map<String, Object> residenceAddress = new HashMap<>();
        residenceAddress.put("addressLine", Base64.encode("beijing"));
        residenceAddress.put("addressLine2", Base64.encode("beijing"));
        residenceAddress.put("cityCode", "MT_1");
        residenceAddress.put("state", "");
        residenceAddress.put("postcode", "110110");
        residenceAddress.put("countryCode", "MT");
        Map<String, Object> identityInfo = new HashMap<>();
        identityInfo.put("idType", "1");
        identityInfo.put("idNo", "312006000003933");
        identityInfo.put("issueDate", "2020-11-01");
        identityInfo.put("expiryDate", "2099-11-01");
        Map<String, Object> legalPerson = new HashMap<>();
        legalPerson.put("firstName","王");
        legalPerson.put("lastName","怀清");
        legalPerson.put("nativeLanguageName","王怀清");
        legalPerson.put("nationalityCode","MT");
        legalPerson.put("gender","1");
        legalPerson.put("birthday","2020-11-01");
        legalPerson.put("residenceAddress",residenceAddress);
        legalPerson.put("identityInfo",identityInfo);

        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("merchantId", 1);
        bizData.put("merchantType", "2");
        bizData.put("merchantName", "ae001");
        bizData.put("shortName", "ae001");
        bizData.put("registrationNum", "00001");
        bizData.put("registrationDate", "2023-04-05");
        bizData.put("expireDate", "2099-04-05");
        bizData.put("businessCategory", "0742");
        bizData.put("contactName", "GB_LAN");
        bizData.put("contactMobile", "+861326105297");
        bizData.put("email", "352825026@qq.com");
        bizData.put("registrationAddress", registrationAddress);
        bizData.put("businessAddress", businessAddress);
        bizData.put("legalPerson", legalPerson);
        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/createMerchant", requestStr);
        handleResponse(responseStr);
    }

    /**
     * Update merchant
     */
    public static void updateMerchant() throws Exception {
        Map<String, Object> bizData = new HashMap<>();

        Map<String, Object> registrationAddress = new HashMap<>();
        registrationAddress.put("addressLine", Base64.encode("beijing"));
        registrationAddress.put("addressLine2", Base64.encode("beijing"));
        registrationAddress.put("cityCode", "MT_1");
        registrationAddress.put("state", "");
        registrationAddress.put("postcode", "110110");
        registrationAddress.put("countryCode", "MT");

        Map<String, Object> businessAddress = new HashMap<>();
        businessAddress.put("addressLine", Base64.encode("beijing"));
        businessAddress.put("addressLine2", Base64.encode("beijing"));
        businessAddress.put("cityCode", "MT_1");
        businessAddress.put("state", "");
        businessAddress.put("postcode", "110110");
        businessAddress.put("countryCode", "MT");


        Map<String, Object> residenceAddress = new HashMap<>();
        residenceAddress.put("addressLine", Base64.encode("beijing"));
        residenceAddress.put("addressLine2", Base64.encode("beijing"));
        residenceAddress.put("cityCode", "MT_1");
        residenceAddress.put("state", "");
        residenceAddress.put("postcode", "110110");
        residenceAddress.put("countryCode", "MT");
        Map<String, Object> identityInfo = new HashMap<>();
        identityInfo.put("idType", "1");
        identityInfo.put("idNo", "312006000003933");
        identityInfo.put("issueDate", "2021-11-01");
        identityInfo.put("expiryDate", "2099-11-01");
        Map<String, Object> legalPerson = new HashMap<>();
        legalPerson.put("firstName","wang");
        legalPerson.put("lastName","huaiqing");
        legalPerson.put("nativeLanguageName","huaiqing.wang");
        legalPerson.put("nationalityCode","MT");
        legalPerson.put("gender","1");
        legalPerson.put("birthday","2020-11-01");
        legalPerson.put("residenceAddress",residenceAddress);
        legalPerson.put("identityInfo",identityInfo);

        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("merchantType", "2");
        bizData.put("merchantName", "ae001");
        bizData.put("shortName", "ae001");
        bizData.put("registrationNum", "00001");
        bizData.put("registrationDate", "2023-04-05");
        bizData.put("expireDate", "2099-04-05");
        bizData.put("businessCategory", "0742");
        bizData.put("contactName", "GB_LAN");
        bizData.put("contactMobile", "+861326105297");
        bizData.put("email", "352825026@qq.com");
        bizData.put("registrationAddress", registrationAddress);
        bizData.put("businessAddress", businessAddress);
        bizData.put("legalPerson", legalPerson);
        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/updateMerchant", requestStr);
        handleResponse(responseStr);
    }

    /**
     * Query merchant
     */
    public static void getMerchant() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        //bizData.put("subMerchantId", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/getMerchant", requestStr);
        handleResponse(responseStr);
    }

    /**
     * Merchant questionnaire
     */
    public static void questionnaire() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("hasLicense", "1");
        bizData.put("employeeNum", "1");
        bizData.put("annualTurnover", "1");
        bizData.put("monthExpected", "1");
        bizData.put("singleTransAverage", "1");
        bizData.put("pep", "0");
        bizData.put("website", "www.baidu.com");
        bizData.put("businessScope", "111111");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/merchantQuestionnaire", requestStr);
        handleResponse(responseStr);
    }

    /**
     * Upload supporting documents
     */
    public static void uploadSupportingDocuments() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("fileType", "5");
        bizData.put("fileContent", Base64.encode(new File("C:\\Users\\Admin\\Desktop\\test.jpg")));
        bizData.put("suffix", "jpg");
        bizData.put("fileDesc", "");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), false);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/uploadFile", requestStr);
        handleResponse(responseStr);
    }

    /**
     * Opening merchant payment
     */
    public static void openingMerchantPayment() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("channelType", "3");
        bizData.put("businessType", "1");
        bizData.put("accessModeType", "1");
        bizData.put("nonEuropeFeeRate", "1.1");
        //bizData.put("europeFeeRate", "1.2");
        bizData.put("fixedFee", "10");
        bizData.put("currency", "EUR");
        bizData.put("webSite", "https://www.baidu.com");
        bizData.put("appDownloadURL", "");
        bizData.put("officeAccount", "");
        bizData.put("miniProgram", "");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/openPayment", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query opening merchant payment result
     */
    public static void getOpeningPaymentResult() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("subMerchantId", "312006000003933");
        bizData.put("channelType", "312006000003933");
        bizData.put("businessType", "312006000003933");
        bizData.put("accessModeType", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/getOpenPaymentResult", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Set settlement account
     */
    public static void settlementAccount() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "000001");
        bizData.put("currency", "EUR");
        bizData.put("accountName", "wanghuaiqing");
        bizData.put("accountNum", "312006000003933");
        bizData.put("swiftCode", "312006000003933");
        bizData.put("bankName", "312006000003933");
        bizData.put("bankAddress", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/settlementAccount", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query settlement account
     */
    public static void getSettlementAccount() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("merchantId", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getSettlementAccount", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Withdraw
     */
    public static void withdraw() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("orderNo", "312006000003933");
        bizData.put("currency", "312006000003933");
        bizData.put("swiftCode", "312006000003933");
        bizData.put("benBankName", "312006000003933");
        bizData.put("benAccountNum", "312006000003933");
        bizData.put("benAccountName", "312006000003933");
        bizData.put("amount", "312006000003933");
        bizData.put("reference", "312006000003933");
        bizData.put("clientDate", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/withdrawal", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query Withdrawal Result
     */
    public static void getWithdrawResult() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("orderNo", "312006000003933");
        bizData.put("currency", "312006000003933");
        bizData.put("swiftCode", "312006000003933");
        bizData.put("benBankName", "312006000003933");
        bizData.put("benAccountNum", "312006000003933");
        bizData.put("benAccountName", "312006000003933");
        bizData.put("amount", "312006000003933");
        bizData.put("reference", "312006000003933");
        bizData.put("clientDate", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getWithdrawalResult", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query Merchant Balance
     */
    public static void getAccountBalance() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("currency", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getAccountBalance", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query merchant payment
     */
    public static void queryMerchantPayment() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("merchantId", "312006000003933");
        bizData.put("settlementDate", "312006000003933");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getPayment", requestStr);
         handleResponse(responseStr);
    }

    /**
     * Query transaction information
     */
    public static void getTransactionInformation() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("merchantId", "312006000158357");
        bizData.put("beginDate", "2024-04-01");
        bizData.put("endDate", "2024-04-25");
        bizData.put("merchantType", "1");
        //bizData.put("paymentType", "1501");
        bizData.put("start", "2");

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        long start = System.currentTimeMillis();
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getTransactions", requestStr);
        long end = System.currentTimeMillis();
        System.out.println("cost:" + (end - start));
         handleResponse(responseStr);
    }

    /**
     * Query transaction information
     */
    public static void getSettlementFile() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("merchantId", "312006000004505");
        bizData.put("settlementDate", "2024-03-28");
        bizData.put("currency", "EUR");

        //

        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/settlement/getSettlementFile", requestStr);
        Map<String, Object> rspMap = handleResponse(responseStr);
        Map<String, Object> rspDate = (Map<String, Object>) rspMap.get("respData");
        String file = rspDate.get("fileContent").toString();
        String suffix = rspDate.get("suffix").toString();
        InputStream inputStream = new ByteArrayInputStream(org.apache.commons.codec.binary.Base64.decodeBase64(file));
        String filePath = "C:\\Users\\Admin\\Desktop\\test" + suffix;
        writeBinaryToFile(inputStream,filePath);

    }

    public static void getQRCodeLink() throws Exception {
        Map<String, Object> bizData = new HashMap<>();
        // Add parameters
        bizData.put("partnerMerchantId", "312006000004505");
        bizData.put("fileType", "51");
        //bizData.put("currency", "EUR");

        //
        //https://sandbox-api.paytend.com/pf/merchant/getQRCodeLink
        String requestStr = initCommonRequest(JSONUtil.toJsonStr(bizData), true);
        logger.debug("REQUEST:{}", JSONUtil.toJsonPrettyStr(requestStr));
        long start = System.currentTimeMillis();
        String responseStr = PaytendUtil.postJson(PAYTEND_BASE_URL + "/pf/merchant/getQRCodeLink", requestStr);
        long end = System.currentTimeMillis();
        System.out.println("cost:" + (end - start));
        handleResponse(responseStr);

    }



    public static void writeBinaryToFile(InputStream inputStream, String outputFile) {
        try (OutputStream outputStream = new FileOutputStream(outputFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            System.out.println("文件写入成功：" + outputFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * Initialization public request information
     *
     * @return
     */
    public static String initCommonRequest(String requestStr, boolean isAES) throws Exception {
        String aesKey = AESUtils.generateKey();

        Map<String, Object> commonRequestMap = new HashMap<>();

        commonRequestMap  .put("requestId", PaytendUtil.genOutTradeNo());
        commonRequestMap.put("partnerId", PARTNER_ID);
        commonRequestMap.put("version", VERSION);
        commonRequestMap.put("signType", SIGN_TYPE);
        commonRequestMap.put("bizData", requestStr);
        commonRequestMap.put("randomKey", aesKey);
        String signDataString = getTreeValue(commonRequestMap, false);
        System.out.println("signData" + JSONUtil.parseObj(commonRequestMap));
        System.out.println("signDataString:" + signDataString);
        commonRequestMap.put("signature", RSAUtils.signSHA256(signDataString.getBytes("UTF-8"), PARTNER_PRIVATE_KEY));

        commonRequestMap.put("bizData", isAES == true ? AESUtils.encrypt(requestStr, aesKey) : JSONUtil.parseObj(requestStr));
        commonRequestMap.put("randomKey", RSAUtils.encryptedDataOnJava(aesKey, PAYTEND_PUBLIC_KEY));
        return JSONUtil.toJsonStr(commonRequestMap);
    }

    /**
     * Handle response
     *
     * @param responseStr
     * @return
     * @throws Exception
     */
    public static Map<String, Object> handleResponse(String responseStr) throws Exception {
        Map<String, Object> responseMap = JSONUtil.toBean(responseStr, Map.class);

        String respCode = String.valueOf(responseMap.get("respCode"));
        if (!"00".equals(respCode)) {
            logger.debug("Request exception");
            logger.debug(JSONUtil.toJsonStr(responseStr));
            return new HashMap<>();
        }

        String randomKey = String.valueOf(responseMap.get("randomKey"));
        String respData = String.valueOf(responseMap.get("respData"));
        String signature = String.valueOf(responseMap.get("signature"));

        /**
         * randomKey RSA decrypt
         */
        String randomKeyMsg = RSAUtils.decryptDataOnJava(randomKey, PARTNER_PRIVATE_KEY);
        responseMap.put("randomKey", randomKeyMsg);
        /**
         * respData AES decrypt
         */
        String respDataMsg = "";
        if(StrUtil.isNotBlank(respData)){
            respDataMsg = AESUtils.decrypt(respData, randomKeyMsg);
            responseMap.put("respData", JSONUtil.parseObj(respDataMsg));
        }

        /**
         * verify signature
         */
        responseMap.remove("encryptFlag");// Reserved field does not participate in signature
        responseMap.remove("signature"); // Not participating in signing
        String signDataString = getTreeValue(responseMap, false); // Compute signature string
        boolean flag = RSAUtils.verifySHA256(signDataString.getBytes("UTF-8"), PAYTEND_PUBLIC_KEY, signature);

        if (flag) {
            if(StrUtil.isNotBlank(respDataMsg)){
                responseMap.put("respData", JSONUtil.parse(respDataMsg));
            }
            logger.debug("RESPONSE:{}", JSONUtil.toJsonPrettyStr(responseMap));
        } else {
            logger.debug("Response verification fail");
        }

        return responseMap;
    }

    public static String getTreeValue(Map<String, Object> toSortData, boolean emptyParamIsSign) {
        TreeMap<String, Object> params = new TreeMap<String, Object>();
        params.putAll(toSortData);
        StringBuffer orgin = new StringBuffer();
        Iterator<String> iter = params.keySet().iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            String value = String.valueOf(params.get(key));
            if (emptyParamIsSign) {//Null value parameters participate in the signature
                orgin.append("&").append(key).append("=").append(value);
            } else {// Null value parameters do not participate in the signature
                if (!StrUtil.isEmpty(value)) {
                    orgin.append("&").append(key).append("=").append(value);
                }
            }
        }
        return orgin.toString().substring(1);
    }
}
