package com.saye.hospitalgd.util;

import com.saye.hospitalgd.commons.getBean.GetBeanUtil;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.service.ThirdSftpConfigService;
import com.saye.hospitalgd.service.impl.ThirdSftpConfigServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author thuang
 * @version 1.0
 * @description: 退款处理
 * @date 2021/12/1 11:21
 */
@Slf4j
public class RefundUtil {

    private static String ORG_CODE = "3301001";
    private static String APP_CODE = "HNWJZFPT";
    private static String TERMINAL_CODE = "Joju01";
    private static String APP_KEY = "3E4DAD56226E4EB68C89560D5A9589AE";
    private static String OPERATOR = "40404";
    private static String OPERATOR_NAME = "dzpt";

    public String refundManager(String url, String inputXml) throws Exception {


        RestTemplate restTemplate = RestTemplateUtil.getInstance();

        // 创建一个请求头对象
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("text/xml;charset=UTF-8");
        // 设置请求头对象contentTyp的为text/xml;charset=UTF-8
        headers.setContentType(type);

        // 将请求参数进行封装并进行远程接口服务调用
        // 构造webservice请求参数
        StringBuffer soapRequestData = new StringBuffer("");
        soapRequestData.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">");
        soapRequestData.append("<soapenv:Header/>");
        soapRequestData.append("<soapenv:Body>");
        soapRequestData.append("<tem:DoTrans>");
        soapRequestData.append("<tem:Inxml>");

        //传入参数 < > 符号需要转义
        inputXml = inputXml.replaceAll("<", "&lt;");
        inputXml = inputXml.replaceAll(">", "&gt;");

        soapRequestData.append(inputXml);

        soapRequestData.append("</tem:Inxml>");
        soapRequestData.append("</tem:DoTrans>");
        soapRequestData.append("</soapenv:Body>");
        soapRequestData.append("</soapenv:Envelope>");

        // 创建请求
        HttpEntity<String> request = new HttpEntity<String>(soapRequestData + "", headers);

        // 发送post请求并获取到响应结果
        String str = restTemplate.postForObject(url, request, String.class);

        Document document = DocumentHelper.parseText(str);

        Element rootElt = document.getRootElement();

        //直接获取body
        Iterator body = rootElt.elementIterator("Body");
        Element recordEless = (Element) body.next();

        Iterator callThirdResponse = recordEless.elementIterator("DoTransResponse");
        Element thirdResponse = (Element) callThirdResponse.next();

        Iterator callThirdResult = thirdResponse.elementIterator("DoTransResult");
        Element thirdResult = (Element) callThirdResult.next();

        return thirdResult.getText();
    }

    /**
     * @description: 调用三方退款接口
     * @author thuang
     * @date 2021/12/2 10:16
     * @version 1.0
     */
    public HashMap<Object, Object> refundThird(HashMap<Object, Object> bankbillObj, String url, String refundRequestId) throws Exception {
        String c_ysddh = StringDUtil.changeNullToEmpty(bankbillObj.get("C_YSDDH"));
        String c_shddh = StringDUtil.changeNullToEmpty(bankbillObj.get("C_SHDDH"));

        String originalOrderId = c_ysddh;
        String merchantOrderId = c_shddh;

        String czyh = ""; //暂时不知道  传空
        String Amount = StringDUtil.changeNullToEmpty(bankbillObj.get("C_JYJE"));

        //单位分 所以乘100
        Amount = new BigDecimal(Amount).multiply(new BigDecimal(100)).intValue() + "";

        String xmlStr = "<Req>" +
                "<czyh>" + czyh + "</czyh>" +
                "<hzid/>" +
                "<hzxm/>" +
                "<tranType>02</tranType>" + //02 代表退货
                "<Amount>" + Amount + "</Amount>" +
                "<payType/>" +
                "<payCode/>" +
                "<originalOrderId>" + originalOrderId + "</originalOrderId>" +
                "<merchantOrderId>" + merchantOrderId + "</merchantOrderId>" +
                "<refundRequestId>" + refundRequestId + "</refundRequestId>" +
                "</Req>";

        //对返回结果进行解析
        String dataStr = refundManager(url, xmlStr);

        HashMap<Object, Object> resultMap = new HashMap<>();

        String errCode = "0";
        String errMsg = "";

        try {
            Document document = DocumentHelper.parseText(dataStr);
            Element rootElt = document.getRootElement();

            //是否成功 00表示成功
            Element respCodeElm = rootElt.element("respCode");
            String respCode = respCodeElm.getText();
            if (!"00".equals(respCode)) {
                errCode = respCode;
            }

            //错误信息 如果respCode不为00时候有效
            Element errMsgElm = rootElt.element("errMsg");
            errMsg = errMsgElm.getText();

            //交易金额
            Element transactionAmountElm = rootElt.element("transactionAmount");
            String transactionAmount = transactionAmountElm.getText();

            //交易参考号
            Element retrievalRefNumElm = rootElt.element("retrievalRefNum");
            String retrievalRefNum = retrievalRefNumElm.getText();

            //退款请求标识 主动发送 直接存发的

            //实际退款金额
            Element refundInvoiceAmountElm = rootElt.element("refundInvoiceAmount");
            String refundInvoiceAmount = refundInvoiceAmountElm.getText();

            resultMap.put("transactionAmount", transactionAmount);
            resultMap.put("retrievalRefNum", retrievalRefNum);
            resultMap.put("refundRequestId", refundRequestId);
            resultMap.put("refundInvoiceAmount", refundInvoiceAmount);
        } catch (Exception e) {
            e.printStackTrace();
            errCode = "999";
            errMsg = "处理退款返回信息失败,原因：" + e.getMessage();
            System.out.println(dataStr);
        }

        resultMap.put("errCode", errCode);
        resultMap.put("errMsg", errMsg);
        return resultMap;
    }

    /**
     * @description: 退货查询
     * @author thuang
     * @date 2021/12/5 16:15
     * @version 1.0
     */
    public HashMap<Object, Object> searchRefundThird(HashMap<Object, Object> bankbillObj, String url, String refundRequestId) throws Exception {
        String c_ysddh = StringDUtil.changeNullToEmpty(bankbillObj.get("C_YSDDH"));
        String c_shddh = StringDUtil.changeNullToEmpty(bankbillObj.get("C_SHDDH"));

        String originalOrderId = c_ysddh;
        String merchantOrderId = c_shddh;

        String czyh = ""; //暂时不知道  传空
        String Amount = StringDUtil.changeNullToEmpty(bankbillObj.get("C_JYJE"));


        String xmlStr = "<Req>" +
                "<czyh>" + czyh + "</czyh>" +
                "<hzid/>" +
                "<hzxm/>" +
                "<tranType>04</tranType>" + //04 代表退货查询
                "<Amount/>" +
                "<payType/>" +
                "<payCode/>" +
                "<originalOrderId>" + originalOrderId + "</originalOrderId>" +
                "<merchantOrderId>" + merchantOrderId + "</merchantOrderId>" +
                "<refundRequestId>" + refundRequestId + "</refundRequestId>" +
                "</Req>";

        //对返回结果进行解析 外层应该和退款一样
        String dataStr = refundManager(url, xmlStr);

        HashMap<Object, Object> resultMap = new HashMap<>();

        String errCode = "0";
        String errMsg = "";

        try {
            Document document = DocumentHelper.parseText(dataStr);
            Element rootElt = document.getRootElement();

            //是否成功 00表示成功
            Element respCodeElm = rootElt.element("respCode");
            String respCode = respCodeElm.getText();
            if (!"00".equals(respCode)) {
                errCode = respCode;
            }

            //错误信息 如果respCode不为00时候有效
            Element errMsgElm = rootElt.element("errMsg");
            errMsg = errMsgElm.getText();

            //交易参考号
            Element retrievalRefNumElm = rootElt.element("retrievalRefNum");
            String retrievalRefNum = retrievalRefNumElm.getText();

            //查询退货返回 代表着之前退款是否成功
            Element queryResCodeElm = rootElt.element("queryResCode");
            String queryResCode = queryResCodeElm.getText();

            //代表之前退款失败的错误信息
            String queryResInfo = "";
            if (!"00".equals(queryResCode)) {
                Element queryResInfoElm = rootElt.element("queryResInfo");
                queryResInfo = queryResInfoElm.getText();
            }

            //实际退款金额
            Element refundInvoiceAmountElm = rootElt.element("refundInvoiceAmount");
            String refundInvoiceAmount = refundInvoiceAmountElm.getText();

            resultMap.put("retrievalRefNum", retrievalRefNum);
            resultMap.put("queryResCode", queryResCode);
            resultMap.put("queryResInfo", queryResInfo);
            resultMap.put("refundInvoiceAmount", refundInvoiceAmount);
            resultMap.put("refundRequestId", refundRequestId);

            //交易金额没返回
            resultMap.put("transactionAmount", "");
        } catch (Exception e) {
            e.printStackTrace();
            errCode = "999";
            errMsg = "处理查询退款返回信息失败,原因：" + e.getMessage();
        }

        resultMap.put("errCode", errCode);
        resultMap.put("errMsg", errMsg);
        return resultMap;
    }

    /**
     * @description: 调用掌医接口
     * @author thuang
     * @date 2021/12/2 10:14
     * @version 1.0
     */
    public HashMap<Object, Object> refundPalmHospital(HashMap<Object, Object> bankbillObj, String palm_hospital, String refundRequestId) {

        HashMap<Object, Object> resultMap = new HashMap<>();
        ThirdSftpConfigService thirdSftpConfigService = GetBeanUtil.getBean(ThirdSftpConfigServiceImpl.class);

        String i_jyje = StringDUtil.changeNullToEmpty(bankbillObj.get("I_JYJE"));
        String i_ddh = StringDUtil.changeNullToEmpty(bankbillObj.get("I_DDH"));

        HashMap<Object, Object> searchMap = new HashMap<>();
        searchMap.put("FUBS", "3");
        List<HashMap<Object, Object>> wlConfigList = thirdSftpConfigService.findWLIF(searchMap);
        HashMap<Object, Object> configMap = wlConfigList.get(0);

        String requset_sn = String.valueOf(System.currentTimeMillis());

        String cust_id = StringDUtil.changeNullToEmpty(configMap.get("CUST_ID"));
        String user_id = StringDUtil.changeNullToEmpty(configMap.get("USER_ID"));
        String password = StringDUtil.changeNullToEmpty(configMap.get("PASSWORD"));
        String tx_code = StringDUtil.changeNullToEmpty(configMap.get("TX_CODE"));
        String language = StringDUtil.changeNullToEmpty(configMap.get("LANGUAGE"));
        String wlip = StringDUtil.changeNullToEmpty(configMap.get("WLIP"));
        String wlport = StringDUtil.changeNullToEmpty(configMap.get("WLPORT"));
        String ipAdress = wlip + ":" + wlport;
        String requestXml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?>  \n" +
                "<TX>   \n" +
                "  <REQUEST_SN>" + requset_sn + "</REQUEST_SN>  \n" +
                "  <CUST_ID>" + cust_id + "</CUST_ID>  \n" +
                "  <USER_ID>" + user_id + "</USER_ID>  \n" +
                "  <PASSWORD>" + password + "</PASSWORD>  \n" +
                "  <TX_CODE>" + tx_code + "</TX_CODE>  \n" +
                "  <LANGUAGE>" + language + "</LANGUAGE>  \n" +
                "  <TX_INFO>  \n" +
                "    <MONEY>" + i_jyje + "</MONEY>  \n" +
                "    <ORDER>" + i_ddh + "</ORDER>  \n" +
                "    <REFUND_CODE></REFUND_CODE>  \n" +
                "</TX_INFO>" +
                "</TX> ";

        String params = "requestXml=" + requestXml;
        log.info("退款发送的报文是：" + params);
        String errCode = "0";
        try {
            URI uri = new URI(ipAdress.trim());
            CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(uri);
            httpPost.setHeader("content-type", "application/x-www-form-urlencoded");
            httpPost.setHeader("Connection", "close");
            StringEntity entity = new StringEntity(params, "GB18030");
            httpPost.setEntity(entity);
            CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity(), "GB18030");
            log.info("接受到的数据是s：" + s);
            Document document = DocumentHelper.parseText(s);
            Iterator iterator = document.nodeIterator();


            Element tx = (Element) iterator.next();
            Element return_code = tx.element("RETURN_CODE");
            Element return_msg = tx.element("RETURN_MSG");
            Element amount = null;
//        Element txInfo = null;

            if (!return_code.getText().equals("000000")) {
                errCode = return_code.getText();
            } else {
                Iterator tx_info = tx.elementIterator("TX_INFO");
                Element txInfo = (Element) tx_info.next();

                amount = txInfo.element("AMOUNT");
            }

            resultMap.put("errCode", errCode);
            resultMap.put("errMsg", return_msg.getText());
            if (amount != null) {

                resultMap.put("transactionAmount", amount.getText());
            } else {
                resultMap.put("transactionAmount", "");
            }
            resultMap.put("refundRequestId", refundRequestId);

            //掌医没有这参数
            resultMap.put("retrievalRefNum", "");
            resultMap.put("refundInvoiceAmount", "");
        } catch (Exception e) {
            log.info("退款失败返回信息：" + e.getMessage());
            resultMap.put("errCode", "-1");
            resultMap.put("errMsg", "退款接口调用失败，退款失败");
        }

        return resultMap;
    }

    /**
     * @description: 查询掌医退款结果
     * @author thuang
     * @date 2021/12/5 16:25
     * @version 1.0
     */
    public HashMap<Object, Object> searchRefundPalmHospital(HashMap<Object, Object> bankbillObj, String palm_hospital, String refundRequestId) throws Exception {

        String ddh = bankbillObj.get("I_DDH").toString();

        ThirdSftpConfigService thirdSftpConfigService = GetBeanUtil.getBean(ThirdSftpConfigServiceImpl.class);
        HashMap<Object, Object> searchMap = new HashMap<>();
        searchMap.put("FUBS", "4");
        List<HashMap<Object, Object>> wlConfigList = thirdSftpConfigService.findWLIF(searchMap);
        HashMap<Object, Object> configMap = wlConfigList.get(0);

        String requset_sn = String.valueOf(System.currentTimeMillis());

        String cust_id = StringDUtil.changeNullToEmpty(configMap.get("CUST_ID"));
        String user_id = StringDUtil.changeNullToEmpty(configMap.get("USER_ID"));
        String password = StringDUtil.changeNullToEmpty(configMap.get("PASSWORD"));
        String tx_code = StringDUtil.changeNullToEmpty(configMap.get("TX_CODE"));
        String language = StringDUtil.changeNullToEmpty(configMap.get("LANGUAGE"));
        String wlip = StringDUtil.changeNullToEmpty(configMap.get("WLIP"));
        String wlport = StringDUtil.changeNullToEmpty(configMap.get("WLPORT"));
        String ipAdress = wlip + ":" + wlport;
        String requestXml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?> \n" +
                "<TX> \n" +
                "  <REQUEST_SN>" + requset_sn + "</REQUEST_SN> \n" +
                "  <CUST_ID>" + cust_id + "</CUST_ID> \n" +
                "  <USER_ID>" + user_id + "</USER_ID> \n" +
                "  <PASSWORD>" + password + "</PASSWORD> \n" +
                "  <TX_CODE>" + tx_code + "</TX_CODE> \n" +
                "  <LANGUAGE>" + language + "</LANGUAGE> \n" +
                "  <TX_INFO> \n" +
                "    <START></START> \n" +
                "    <STARTHOUR></STARTHOUR> \n" +
                "    <STARTMIN></STARTMIN> \n" +
                "    <END></END> \n" +
                "    <ENDHOUR></ENDHOUR> \n" +
                "    <ENDMIN></ENDMIN> \n" +
                "    <KIND>1</KIND> \n" +
                "    <ORDER>" + ddh + "</ORDER> \n" +
                "    <ACCOUNT></ACCOUNT> \n" +
                "    <MONEY></MONEY> \n" +
                "    <NORDERBY>1</NORDERBY> \n" +
                "    <PAGE>1</PAGE> \n" +
                "    <POS_CODE></POS_CODE> \n" +
                "    <STATUS>1</STATUS> \n" +
                "    <Mrch_No></Mrch_No>  \n" +
                "    <TXN_TPCD></TXN_TPCD>  \n" +
                "  </TX_INFO> \n" +
                "</TX> \n";
        String params = "requestXml=" + requestXml;
        URI uri = new URI(ipAdress.trim());
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setHeader("content-type", "application/x-www-form-urlencoded");
        httpPost.setHeader("Connection", "close");
        StringEntity entity = new StringEntity(params, "GB18030");
        httpPost.setEntity(entity);
        CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
        String s = EntityUtils.toString(response.getEntity(), "GB18030");
        log.info("接受到的数据是s：" + s);
        Document document = DocumentHelper.parseText(s);
        Iterator iterator = document.nodeIterator();


        Element tx = (Element) iterator.next();
        Element return_code = tx.element("RETURN_CODE");
        Element return_msg = tx.element("RETURN_MSG");
        String errCode = "0";
        Element refundement_amount = null;
        Element order_number = null;
        Element oriOvrlsttnEV_trck_no = null;
        Element orig_amt = null;
        if (!return_code.getText().equals("000000")) {
            errCode = return_code.getText();
        } else {
            Iterator tx_info = tx.elementIterator("TX_INFO");
            Element txInfo = (Element) tx_info.next();

            Iterator list = txInfo.elementIterator("LIST");

            Element list_ = (Element) list.next();
            refundement_amount = list_.element("REFUNDEMENT_AMOUNT");//退款金额
            order_number = list_.element("ORDER_NUMBER");//订单号
            oriOvrlsttnEV_trck_no = list_.element("OriOvrlsttnEV_Trck_No");//银行流水号
            orig_amt = list_.element("Orig_Amt");//订单金额
        }


//        HashMap<Object, Object> postMap = new HashMap<>();
//        postMap.put("refundRequestId", refundRequestId);
//        postMap.put("tranType", "05");
//
//        String post = HttpDutil.post(palm_hospital, postMap);
//
//        JSONObject jsonObject = JSONObject.parseObject(post);

        HashMap<Object, Object> resultMap = new HashMap<>();
//        String errCode = "0";

        //查询返回编码
//        String respCode = StringDUtil.changeNullToEmpty(jsonObject.get("respCode"));
//        if (!"00".equals(respCode)) {
//            errCode = respCode;
//        }

        //查询返回的信息
        String errMsg = return_msg.getText();
        String refundInvoiceAmount = null;
        String originalOrderId = null;
        String merchantOrderId = null;
        String transactionAmount = null;
        //实际退款金额 单位分
        if (refundement_amount != null) {

            refundInvoiceAmount = refundement_amount.getText();
        } else {
            refundInvoiceAmount = "";
        }

        //银商订单号
        if (oriOvrlsttnEV_trck_no != null) {
            originalOrderId = oriOvrlsttnEV_trck_no.getText();
        } else {
            originalOrderId = "";
        }

        //商户订单号
        if (order_number != null) {
            merchantOrderId = order_number.getText();
        } else {
            merchantOrderId = "";
        }

        //订单金额 单位分
        if (orig_amt != null) {
            transactionAmount = orig_amt.getText();
        } else {
            transactionAmount = "";
        }

        // 查询扣款返回的编码
//        String queryResCode = StringDUtil.changeNullToEmpty(jsonObject.get("queryResCode"));

        String queryResInfo = "";
        if (!"000000".equals(return_code.getText())) {
            //查询扣款返回的信息  只有当之前扣款错误时才有
            queryResInfo = return_msg.getText();
        }

        resultMap.put("errCode", errCode);
        resultMap.put("errMsg", errMsg);
        resultMap.put("transactionAmount", transactionAmount);
        resultMap.put("refundInvoiceAmount", refundInvoiceAmount);
        resultMap.put("originalOrderId", originalOrderId);
        resultMap.put("merchantOrderId", merchantOrderId);
        resultMap.put("queryResCode", return_code.getText());
        resultMap.put("queryResInfo", queryResInfo);
        resultMap.put("refundRequestId", refundRequestId);
        //掌医没有这参数
        resultMap.put("retrievalRefNum", "");
        return resultMap;
    }

    public HashMap<String, String> refundTrade(HashMap<Object, Object> refundObj, String palm_hospital) throws DocumentException {

//        String i_ghddh = StringDUtil.changeNullToEmpty(bankbillObj.get("I_GHDDH"));
        //单位分 所以乘100


        String refundXML = getRefundXML(refundObj);

        RestTemplate restTemplate = RestTemplateUtil.getInstance();

        // 创建一个请求头对象
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("text/xml;charset=UTF-8");
        // 设置请求头对象contentTyp的为text/xml;charset=UTF-8
        headers.setContentType(type);

        HttpEntity<String> request = new HttpEntity<String>(refundXML + "", headers);

        // 发送post请求并获取到响应结果
        String inputXML = restTemplate.postForObject(palm_hospital, request, String.class);
        Map<String, Object> parse = resultParse(inputXML);
        String return_code = String.valueOf(parse.get("RETURN_CODE"));
        HashMap<String, String> resultMap = new HashMap<>();
        String errCode = "0";
        String errMsg = "";
        if (return_code.equals("0")) {
            resultMap.put("transactionAmount", String.valueOf(parse.get("REFUND_COST")));
        } else {
            log.info("返回错误信息是" + String.valueOf(parse.get("RETURN_MSG")));
            errMsg = String.valueOf(parse.get("RETURN_MSG"));
            errCode = return_code;
        }
        resultMap.put("errCode", errCode);
        resultMap.put("errMsg", errMsg);
//        resultMap.put("refundRequestId", refundRequestId);

        //掌医没有这参数
//        resultMap.put("retrievalRefNum", "");
//        resultMap.put("refundInvoiceAmount", "");
        return resultMap;

    }

    /**
     * 调用支付平台的退款接口
     */
    public String getRefundXML(HashMap<Object, Object> refundObj) {
        String cardNo = StringDUtil.changeNullToEmpty(refundObj.get("CARD_NO"));
        String hospitalNo = StringDUtil.changeNullToEmpty(refundObj.get("HOSPITAL_NO"));
        String thridplatformNo = StringDUtil.changeNullToEmpty(refundObj.get("THRIDPLATFORM_NO"));
        String platformNo = StringDUtil.changeNullToEmpty(refundObj.get("PLATFORM_NO"));
//        String oldPlatformNo = StringDUtil.changeNullToEmpty(refundObj.get("OLD_PLATFORM_NO"));
        String payChannel = StringDUtil.changeNullToEmpty(refundObj.get("PAY_CHANNEL"));
        String paySource = StringDUtil.changeNullToEmpty(refundObj.get("PAY_SOURCE"));
        String payWay = StringDUtil.changeNullToEmpty(refundObj.get("PAY_WAY"));

        String refundCost = StringDUtil.changeNullToEmpty(refundObj.get("REFUND_COST"));
        String canRefundCost = StringDUtil.changeNullToEmpty(refundObj.get("CAN_REFUND_COST"));
        String serverChannel = StringDUtil.changeNullToEmpty(refundObj.get("SERVER_CHANNEL"));
        String sickName = StringDUtil.changeNullToEmpty(refundObj.get("SICK_NAME"));
//        String sickName = "zs";
        String timeStamp = StringDUtil.changeNullToEmpty(refundObj.get("TIME_STAMP"));

//        APP_CODE CARD_NO HOSPITAL_NO OLD_CHANNEL_NO OLD_PLATFORM_NO OPERATOR OPERATOR_NAME ORG_CODE PAY_CHANNEL PAY_SOURCE PAY_WAY REFUND_COST SERVER_CHANNEL SICK_NAME SIGN TERMINAL_CODE TIME_STAMP
        String str_md5 = "APP_CODE=" + APP_CODE + "&CARD_NO=" + cardNo + "&HOSPITAL_NO=" + hospitalNo + "&OLD_CHANNEL_NO=" + thridplatformNo + "&OLD_PLATFORM_NO=" + platformNo + "&OPERATOR=" + OPERATOR +
                "&OPERATOR_NAME=" + OPERATOR_NAME + "&ORG_CODE=" + ORG_CODE + "&PAY_CHANNEL=" + payChannel + "&PAY_SOURCE=" + paySource + "&PAY_WAY=" + payWay + "&REFUND_COST=" + canRefundCost + "&SERVER_CHANNEL=" + serverChannel + "&SICK_NAME=" + sickName + "&TERMINAL_CODE=" + TERMINAL_CODE + "&TIME_STAMP=" + timeStamp + "&KEY=" + APP_KEY;
        log.info("打印加密前的数据：" + str_md5);
        String s_md5 = DigestUtils.md5DigestAsHex(str_md5.getBytes(StandardCharsets.UTF_8)).toUpperCase();
        log.info("打印加密前的数据：" + s_md5);
        StringBuffer str = new StringBuffer();
        str.append("<tem:callInterface>");
        str.append("<tem:msgHeader>");
        str.append("<![CDATA[");
        str.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        str.append("<ROOT>");
        str.append("<APP_CODE>");
        str.append(APP_CODE);
        str.append("</APP_CODE>");
        str.append("<TERMINAL_CODE>");
        str.append(TERMINAL_CODE);
        str.append("</TERMINAL_CODE>");
        str.append("<INTERFACE>");
        str.append("upay.trade.refund");
        str.append("</INTERFACE>");
        str.append("</ROOT>");
        str.append("]]>");
        str.append("</tem:msgHeader>");

        str.append("<tem:msgBody>");
        str.append("<![CDATA[");
        str.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        str.append("<ROOT>");
        str.append("<ORG_CODE>");
        str.append(ORG_CODE);
        str.append("</ORG_CODE>");
        str.append("<APP_CODE>");
        str.append(APP_CODE);
        str.append("</APP_CODE>");
        str.append("<TERMINAL_CODE>");
        str.append(TERMINAL_CODE);
        str.append("</TERMINAL_CODE>");
        str.append("<TIME_STAMP>");
        str.append(timeStamp);
        str.append("</TIME_STAMP>");
        str.append("<SERVER_CHANNEL>");
        str.append(serverChannel);
        str.append("</SERVER_CHANNEL>");
        str.append("<HOSPITAL_NO>");
        str.append(hospitalNo);
        str.append("</HOSPITAL_NO>");

        str.append("<PAY_CHANNEL>");
        str.append(payChannel);
        str.append("</PAY_CHANNEL>");

        str.append("<OLD_PLATFORM_NO>");
        str.append(platformNo);
        str.append("</OLD_PLATFORM_NO>");
        str.append("<OLD_CHANNEL_NO>");
        str.append(thridplatformNo);
        str.append("</OLD_CHANNEL_NO>");
        str.append("<REFUND_COST>");
        str.append(canRefundCost);
        str.append("</REFUND_COST>");
        str.append("<OPERATOR>");
        str.append(OPERATOR);
        str.append("</OPERATOR>");
        str.append("<OPERATOR_NAME>");
        str.append(OPERATOR_NAME);
        str.append("</OPERATOR_NAME>");
        str.append("<PAY_WAY>");
        str.append(payWay);
        str.append("</PAY_WAY>");
        str.append("<PAY_SOURCE>");
        str.append(paySource);
        str.append("</PAY_SOURCE>");
        str.append("<SICK_NAME>");
        str.append(sickName);
        str.append("</SICK_NAME>");
        str.append("<CARD_NO>");
        str.append(cardNo);
        str.append("</CARD_NO>");
        str.append("<SIGN>");
        str.append(s_md5);
        str.append("</SIGN>");
        str.append("</ROOT>");

        str.append("]]>");
        str.append("</tem:msgBody>");
        str.append("</tem:callInterface>");
        return getRequestXMl(str);
    }

    public String getRequestXMl(StringBuffer strXML) {
        StringBuffer str = new StringBuffer();
        str.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">");
        str.append("<soapenv:Header/>");
        str.append("<soapenv:Body>");
        str.append(strXML.toString());
        str.append("</soapenv:Body>");
        str.append("</soapenv:Envelope>");
        return str.toString();
    }

    public Map<String, Object> resultParse(String soap) throws DocumentException {
        //map.clear();
        String soapWeb = StringEscapeUtils.unescapeXml(soap);
        soapWeb = soapWeb.replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
        Document doc = DocumentHelper.parseText(soapWeb);// 报文 转成 xml
        Element root = doc.getRootElement();//获取根元素，准备递归解析这个XML树

        Map<String, Object> map = getCodeNC(root);
        return map;
    }

    // 非递归遍历所有的 节点 和 数据
    public Map<String, Object> getCodeNC(Element root) {
        Map<String, Object> map = new HashMap<String, Object>();

        Stack a = null;
        a = new Stack<>();
        a.push(root);

        if (root.elements().size() == 0 || root.elements() == null) {
            return map;
        }
        //top 是栈顶元素
        Element top = null;
        while (!a.empty()) {
            top = (Element) a.peek();
            a.pop();

            //如果当前跟节点有子节点，找到子节点
            List<Element> list = top.elements();
            int size = top.elements().size();

            for (Element e : list) {
                //遍历每个节点
                if (e.elements().size() > 0) {
                    //对栈顶元素进行反向遍历，入栈
                    a.push((Element) e);
                }
                if (e.elements().size() == 0) {
                    map.put(e.getName(), e.getTextTrim());
                }//如果为叶子节点，那么直接把名称和值放入map
            }
        }

        return map;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {

//        76A1136C6C502BDAC3544050877DBCA8 fh
//        7BD2520E9DC77C8C9A637BFB47503C1E fm
//        46ECF7E7B52E21D9F1EE3C283715F274
//        76A1136C6C502BDAC3544050877DBCA8

//        String s = "APP_CODE=HNWJZFPT&CARD_NO=3303821999091" +
//                "30346&HOSPITAL_NO=JJ20231009154936066&OLD_CHANNEL_NO=&OLD_PLATFORM_NO=&OPERATOR=" +
//                "40404&OPERATOR_NAME=dzpt&ORG_CODE=3301001&PAY_CHANNEL=1&PAY_SOURCE=1&PAY_WAY=5&R" +
//                "EFUND_COST=0.00&SERVER_CHANNEL=1&SICK_NAME=张三&TERMINAL_CODE=Joju01&TIME_STAMP=" +
//                "2023-10-09 15:50:07&KEY=3E4DAD56226E4EB68C89560D5A9589AE";
//        String s = "APP_CODE=HNWJZFPT&CARD_NO=3303821999091" +
//                "30346&HOSPITAL_NO=JJ20231009154936066&OLD_CHANNEL_NO=&OLD_PLATFORM_NO=&OPERATOR=" +
//                "40404&OPERATOR_NAME=dzpt&ORG_CODE=3301001&PAY_CHANNEL=1&PAY_SOURCE=1&PAY_WAY=5&R" +
//                "EFUND_COST=0.00&SERVER_CHANNEL=1&SICK_NAME=张三&TERMINAL_CODE=Joju01&TIME_STAMP=" +
//                "2023-10-09 15:50:07&KEY=3E4DAD56226E4EB68C89560D5A9589AE";
        String s = "APP_CODE=HNWJZFPT&CARD_NO=3303821999091" +
                "30346&HOSPITAL_NO=JJ20231009154936066&OLD_CHANNEL_NO=&OLD_PLATFORM_NO=&OPERATOR=" +
                "40404&OPERATOR_NAME=dzpt&ORG_CODE=3301001&PAY_CHANNEL=1&PAY_SOURCE=1&PAY_WAY=5&R" +
                "EFUND_COST=0.00&SERVER_CHANNEL=1&SICK_NAME=张三&TERMINAL_CODE=Joju01&TIME_STAMP=\n" +
                "2023-10-09 15:50:07&KEY=3E4DAD56226E4EB68C89560D5A9589AE";
        String s_md5 = DigestUtils.md5DigestAsHex(s.getBytes()).toUpperCase();
        log.info("打印加密后的数据：" + s_md5);

    }

}
