package com.fjs.scenic.utils;

import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayConstants.SignType;
import org.apache.commons.net.util.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.crypto.Cipher;
import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

import static java.nio.file.Paths.get;

/**
 * 微信支付工具类
 */
public class WXPayUtil extends com.github.wxpay.sdk.WXPayUtil {

    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(WXPayUtil.class);

    /**
     * RSA属性配置
     */
    private static final int KEYLENGTH = 2048;
    private static final int RESERVESIZE = 11;
    private static final String CIPHERALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";

    /**
     * 公钥的路径
     */
    public static final String PUBLIC_KEY_FILE_NAME = "";
    /**
     * 公钥的路径
     */
    public static String CERT_FILE_NAME;
    /**
     * 微信APPID
     */
    public static String APPID;
    /**
     * 商户ID
     */
    public static String MCH_ID;
    /**
     * API密钥
     */
    public static String API_KEY;
    /**
     * 支付消息的通知地址
     */
    public static String NOTIFY_URL;
    /**
     * 退款消息的通知地址
     */
    public static String FEFUND_NOTIFY;

    /**
     * 微信统一下单地址
     */
    private static final String ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * 订单查询地址
     */
    private static final String ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
    /**
     * 微信支付发起退款地址
     */
    private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    /**
     * 退款查询地址
     */
    private static final String REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery";
    /**
     * 微信RSA公钥
     */
    private static final String RSA_URL = "https://fraud.mch.weixin.qq.com/risk/getpublickey";
    /**
     * 企业付款至零钱
     */
    private static final String TRANSFERS = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    /**
     * 企业付款零钱-查询
     */
    private static final String TRANSFERS_QUERY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
    /**
     * 企业付款至银行卡
     */
    private static final String BANK_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
    /**
     * 企业付款至银行卡-查询
     */
    private static final String BANK_URL_QUERY = "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";

    /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        Map<String, String> data = new HashMap<String, String>();
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

        // 禁用外部实体的
        documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//        documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        documentBuilderFactory.setXIncludeAware(false);
        documentBuilderFactory.setExpandEntityReferences(false);

        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
        org.w3c.dom.Document doc = documentBuilder.parse(stream);
        doc.getDocumentElement().normalize();
        NodeList nodeList = doc.getDocumentElement().getChildNodes();
        for (int idx = 0; idx < nodeList.getLength(); ++idx) {
            Node node = nodeList.item(idx);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                data.put(element.getNodeName(), element.getTextContent());
            }
        }
        try {
            stream.close();
        } catch (Exception ex) {
            log.error(ex.toString());
        }
        return data;
    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString();
        output = output.replaceAll("&#13;", "");
        try {
            writer.close();
        } catch (Exception ex) {
        }
        return output;
    }

    /**
     * 判断签名是否正确
     *
     * @param xmlStr XML格式数据
     * @return 签名是否正确
     * @throws Exception
     */
    public static boolean isSignatureValid(String xmlStr) throws Exception {
        Map<String, String> data = xmlToMap(xmlStr);
        if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {
            return false;
        }
        String sign = data.get(WXPayConstants.FIELD_SIGN);
        return generateSignature(data, API_KEY).equals(sign);
    }

    /**
     * 判断签名是否正确，必须包含sign字段，否则返回false。使用MD5签名。
     *
     * @param data Map类型数据
     * @return 签名是否正确
     * @throws Exception
     */
    public static boolean isSignatureValid(Map<String, String> data) throws Exception {
        return isSignatureValid(data, API_KEY, SignType.MD5);
    }

    /**
     * 判断签名是否正确，必须包含sign字段，否则返回false。
     *
     * @param data     Map类型数据
     * @param signType 签名方式
     * @return 签名是否正确
     * @throws Exception
     */
    public static boolean isSignatureValid(Map<String, String> data, SignType signType) throws Exception {
        if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {
            return false;
        }
        String sign = data.get(WXPayConstants.FIELD_SIGN);
        return generateSignature(data, API_KEY, signType).equals(sign);
    }

    /**
     * POST请求
     *
     * @param url    请求的地址
     * @param outStr 参数
     * @return
     */
    public static Map<String, String> doPostStr(String url, String outStr) throws Exception {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        post.setHeader("", "");
        post.setEntity(new StringEntity(outStr, "UTF-8"));
        HttpResponse response = client.execute(post);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            String result = EntityUtils.toString(entity, "UTF-8");
            return xmlToMap(result);
        }
        return null;
    }

    /**
     * JSAPI-公众号支付(预下单)
     *
     * @param orderNo 系统订单号
     * @param total   订单金额
     * @param openId  下单人openId
     * @param ip      下单人IP
     * @return
     */
    public static Map<String, String> order(String orderNo, String total, String openId, String ip) {
        // 拼接统一下单地址参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("appid", APPID);
        paramMap.put("body", orderNo);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("device_info", "WEB");
        paramMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32));
        paramMap.put("openid", openId);
        paramMap.put("out_trade_no", orderNo);
        paramMap.put("spbill_create_ip", ip);
        paramMap.put("total_fee", total);
        paramMap.put("trade_type", "JSAPI");
        paramMap.put("notify_url", NOTIFY_URL);
        log.info("notify_url:{}", NOTIFY_URL);
        try {
            String sign = generateSignature(paramMap, API_KEY);

            paramMap.put("sign", sign);
            // 请求下单
            Map<String, String> map = doPostStr(ORDER_URL, mapToXml(paramMap));
            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code"))) {
                log.info("预下单成功.");
                // 预支付订单的ID
                String prepay_id = map.get("prepay_id");
                Map<String, String> data = new HashMap<>();
                data.put("appId", APPID);
                data.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                data.put("nonceStr", generateNonceStr());
                data.put("package", "prepay_id=" + prepay_id);
                data.put("signType", "MD5");
                data.put("paySign", generateSignature(data, API_KEY));
                return data;
            }
            log.error("下单失败.");
            return null;
        } catch (Exception e) {
            log.error("下单异常：{}", e.toString());
            return null;
        }
    }

    /**
     * 查询微信订单的支付状态
     *
     * @param orderNo 系统订单号
     * @return
     */
    public static boolean orderQuery(String orderNo) {
        // 拼接参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("appid", APPID);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("out_trade_no", orderNo);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("sign_type", "MD5");
        try {
            String sign = generateSignature(paramMap, API_KEY);
            paramMap.put("sign", sign);
            Map<String, String> map = doPostStr(ORDER_QUERY, mapToXml(paramMap));
            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code")) &&
                    "SUCCESS".equals(map.get("trade_state"))) {
                log.info(map.get("return_msg"));
                return true;
            } else {
                log.info(map.get("err_code_des"));
                return false;
            }
        } catch (Exception e) {
            log.error("查询失败：{}", e.toString());
            return false;
        }
    }

    /**
     * 发起退款
     *
     * @param orderNo  系统订单号
     * @param total    订单金额
     * @param refundNo 退款单号
     * @return
     */
    public static boolean refund(String orderNo, String total, String refundNo) {
        // 拼接统一下单地址参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("appid", APPID);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("out_trade_no", orderNo);
        paramMap.put("out_refund_no", refundNo);
        paramMap.put("total_fee", total);
        paramMap.put("refund_fee", total);
        paramMap.put("notify_url", FEFUND_NOTIFY);
        log.warn("refund_notify_url:{}", FEFUND_NOTIFY);
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, REFUND_URL);
            log.info("refund -> map:{}", map);
            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code"))) {
                log.warn("退款申请接收成功");
                return true;
            }
            log.warn("退款失败");
            return false;
        } catch (Exception e) {
            log.error("退款异常：{}", e.toString());
            return false;
        }
    }

    public static String refund(String orderNo, String total) {
        // 拼接统一下单地址参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("appid", APPID);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("out_trade_no", orderNo);
        paramMap.put("out_refund_no", orderNo);
        paramMap.put("total_fee", total);
        paramMap.put("refund_fee", total);
        paramMap.put("notify_url", FEFUND_NOTIFY);
        log.warn("refund_notify_url:{}", FEFUND_NOTIFY);
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, REFUND_URL);
            log.info("refund -> map:{}", map);
            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code"))) {
                log.warn("退款申请接收成功");
                return "true";
            } else if ("SUCCESS".equals(map.get("return_code")) &&
                    "订单已全额退款".equals(map.get("err_code_des"))) {
                log.warn("订单已全额退款");
                return "订单已全额退款";
            } else {
                log.warn("退款失败");
                return "false";
            }
        } catch (Exception e) {
            log.error("退款异常：{}", e.toString());
            return "false";
        }
    }

    /**
     * 查询退款
     *
     * @param refundNo 退款单号
     * @return
     */
    public static Map<String, String> refundQuery(String refundNo) {
        // 拼接统一下单地址参数
        Map<String, String> paramMap = new HashMap<String, String>();
        Map<String, String> data = new HashMap<>();
        paramMap.put("appid", APPID);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("out_refund_no", refundNo);
        try {
            String sign = generateSignature(paramMap, API_KEY);
            paramMap.put("sign", sign);
            // 查询退款
            Map<String, String> map = doPostStr(REFUND_QUERY, mapToXml(paramMap));

            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code"))) {
                log.info("已退款");
                data.put("status", map.get("result_code"));
                data.put("msg", "已退款");
                return data;
            }
            data.put("status", map.get("result_code"));
            data.put("msg", map.get("err_code") + ":" + map.get("err_code_des"));
            return data;
        } catch (Exception e) {
            log.error("退款异常：{}", e.toString());
            return null;
        }
    }

    /**
     * 提现至零钱
     *
     * @param openId   收款方openId
     * @param realName 用户真实姓名
     * @param total    提现金额
     * @param IP       请求的IP
     * @return
     */
    public static Map<String, String> cash(String openId, String realName, String tradeNo, String total, String IP) {
        // 拼接参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("mch_appid", APPID);
        paramMap.put("mchid", MCH_ID);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("partner_trade_no", tradeNo);
        paramMap.put("openid", openId);
        // 强制验证体现人的真实姓名-NO_CHECK | FORCE_CHECK
        paramMap.put("check_name", "FORCE_CHECK");
        // 提现人的真实姓名
        paramMap.put("re_user_name", realName);
        paramMap.put("amount", total);
        paramMap.put("desc", "用户提现");
        paramMap.put("spbill_create_ip", IP);
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, TRANSFERS);
            return map;
        } catch (Exception e) {
            log.error("提现异常：{}", e.toString());
        }
        return null;
    }

    /**
     * 获取微信公钥，落地生成本地文件 需要转PKCS#8
     *
     * @return
     */
    public static boolean getRSAKey() {
        File file = new File(PUBLIC_KEY_FILE_NAME);
        log.info("path:{}", PUBLIC_KEY_FILE_NAME);
        if (file.exists()) {
            log.info("公钥已存在.");
            return true;
        }
        // 拼接参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("sign_type", "MD5");
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, RSA_URL);
            if ("SUCCESS".equals(map.get("return_code")) &&
                    "SUCCESS".equals(map.get("result_code"))) {
                // 转存本地
                String absolutePath = file.getAbsolutePath();
                Path path = get(absolutePath);
                try (BufferedWriter writer = Files.newBufferedWriter(path)) {
                    writer.write(map.get("pub_key"));
                } catch (IOException e) {
                    log.error("写入公钥失败:{}", e.toString());
                }
                return true;
            } else {
                log.info(map.get("err_code"));
                log.info(map.get("err_code_des"));
            }
            return false;
        } catch (Exception e) {
            log.error("获取公钥异常：{}", e.toString());
            return false;
        }
    }

    /**
     * 提现至银行卡
     *
     * @param bankNo   收款方银行卡号
     * @param realName 开户人姓名
     * @param tradeNo  交易号
     * @param total    提现金额
     * @param code     微信对应银卡的编码
     * @return
     */
    public static Map<String, String> cashToBank(String bankNo, String realName, String tradeNo, String total, String code) {
        // 拼接统一下单地址参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("partner_trade_no", tradeNo);
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("enc_bank_no", encryptData(bankNo));
        paramMap.put("enc_true_name", encryptData(realName));
        paramMap.put("bank_code", code);
        paramMap.put("amount", total);
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, BANK_URL);
            return map;
        } catch (Exception e) {
            log.error("提现异常：{}", e.toString());
        }
        return null;
    }

    /**
     * 读取本地公钥
     *
     * @return
     * @throws IOException
     */
    public static String readLocalPubKey() throws IOException {
        File file = new File(PUBLIC_KEY_FILE_NAME);
        String absolutePath = file.getAbsolutePath();
        List<String> lines = Files.readAllLines(Paths.get(absolutePath), StandardCharsets.UTF_8);
        StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            if (line.charAt(0) == '-') {
                continue;
            } else {
                sb.append(line);
                sb.append('\r');
            }
        }
        return sb.toString();
    }

    /**
     * RSA加密
     *
     * @param str
     * @return
     */
    public static String encryptData(String str) {
        try {
            String key = readLocalPubKey();
            str = encrypt(str.getBytes(), loadPublicKey(key));
            log.info(str);
            return str;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 用公钥加密 <br>
     * 每次加密的字节数，不能超过密钥的长度值减去11
     *
     * @param plainBytes 需加密数据的byte数据
     * @param publicKey  公钥
     * @return 加密后的byte型数据
     */
    private static String encrypt(byte[] plainBytes, PublicKey publicKey) throws Exception {
        int keyByteSize = KEYLENGTH / 8;
        int encryptBlockSize = keyByteSize - RESERVESIZE;
        int nBlock = plainBytes.length / encryptBlockSize;
        if ((plainBytes.length % encryptBlockSize) != 0) {
            nBlock += 1;
        }
        ByteArrayOutputStream outbuf = null;
        try {
            Cipher cipher = Cipher.getInstance(CIPHERALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
            for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
                int inputLen = plainBytes.length - offset;
                if (inputLen > encryptBlockSize) {
                    inputLen = encryptBlockSize;
                }
                byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
                outbuf.write(encryptedBlock);
            }
            outbuf.flush();
            byte[] encryptedData = outbuf.toByteArray();
            return Base64.encodeBase64String(encryptedData);
        } catch (Exception e) {
            throw new Exception("ENCRYPT ERROR:", e);
        } finally {
            try {
                if (outbuf != null) {
                    outbuf.close();
                }
            } catch (Exception e) {
                throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
            }
        }
    }

    /**
     * 从字符串中加载公钥
     *
     * @param publicKeyStr 公钥数据字符串
     * @throws Exception 加载公钥时产生的异常
     */
    private static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
        try {
            byte[] buffer = Base64Util.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("公钥非法");
        } catch (NullPointerException e) {
            throw new Exception("公钥数据为空");
        }
    }

    /**
     * 加载商户证书文件
     * 请求接口
     *
     * @return
     */
    private static Map<String, String> doSSLPost(Map<String, String> paramMap, String url) {
        try {
            String sign = generateSignature(paramMap, API_KEY);
            paramMap.put("sign", sign);
            // 加载商户证书
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            File sslFile = ResourceUtils.getFile(CERT_FILE_NAME);
            FileInputStream instream = new FileInputStream(sslFile);
            keyStore.load(instream, MCH_ID.toCharArray());
            instream.close();
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, MCH_ID.toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            HttpPost httppost = new HttpPost(url);
            String xml = mapToXml(paramMap);
            StringEntity entitys = new StringEntity(xml, "utf-8");
            httppost.setEntity((HttpEntity) entitys);
            CloseableHttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            String result = "";
            if (entity != null) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                String text = "";
                String t = "";
                while ((text = bufferedReader.readLine()) != null) {
                    t += text;
                }
                byte[] temp = t.getBytes("utf-8");
                String str = new String(temp, "utf-8");
                result = str;
                EntityUtils.consume(entity);
            }
            response.close();
            httpclient.close();
            // 判断返回的参数
            Map<String, String> map = xmlToMap(result);
            return map;
        } catch (Exception e) {
            log.error("请求接口异常：{}", e.toString());
            return null;
        }
    }

    /**
     * 提现至零钱-根据交易号查询状态
     *
     * @param partnerTradeNo 交易号
     * @return
     */
    public static Map<String, String> cashQuery(String partnerTradeNo) {
        // 拼接参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("nonce_str", generateNonceStr());
        paramMap.put("partner_trade_no", partnerTradeNo);
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("appid", APPID);
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, TRANSFERS_QUERY);
            return map;
        } catch (Exception e) {
            log.error("提现至零钱异常：{}", e.toString());
        }
        return null;
    }

    /**
     * 提现至银行卡-根据交易号查询状态
     *
     * @param partnerTradeNo 交易号
     * @return
     */
    public static Map<String, String> cashToBankQuery(String partnerTradeNo) {
        // 拼接参数
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("mch_id", MCH_ID);
        paramMap.put("partner_trade_no", partnerTradeNo);
        paramMap.put("nonce_str", generateNonceStr());
        try {
            // 判断返回的参数
            Map<String, String> map = doSSLPost(paramMap, BANK_URL_QUERY);
            return map;
        } catch (Exception e) {
            log.error("提现至银行卡异常：{}", e.toString());
        }
        return null;
    }
}
