package com.xzx.gc.util.pay.util;
import com.xzx.gc.model.admin.UserAccountModel;
import com.xzx.gc.util.pay.util.entity.ResultEntity;
import com.xzx.gc.util.pay.util.entity.TransfersDtoAdmin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
public class WechatpayUtil
{
    public static String queryErrorMessage(String xmlStr){
        Document document = StringTOXml(xmlStr);
        String nodePath = "/xml/err_code_des";
        String msg = getNodeValue(document,nodePath);
        return msg;
    }
    /**
     *
     * @param
     * @return Document 对象
     */
    public static Document StringTOXml(String str) {
        StringBuilder sXML = new StringBuilder();
        sXML.append(str);
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document doc = null;
        try {
            InputStream is = new ByteArrayInputStream(sXML.toString().getBytes("utf-8"));
            doc = dbf.newDocumentBuilder().parse(is);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }
    /**
     *
     * @param document
     * @return 某个节点的值 前提是需要知道xml格式,知道需要取的节点相对根节点所在位置
     */
    public static String getNodeValue(Document document, String nodePaht) {
        XPathFactory xpfactory = XPathFactory.newInstance();
        XPath path = xpfactory.newXPath();
        String servInitrBrch = "";
        try {
            servInitrBrch = path.evaluate(nodePaht, document);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return servInitrBrch;
    }
    public static void main(String[] args) {
        String xmlStr = "\n" +
                "\n" +
                "\n" +
                "\n" +
                "\n" +
                "\n" +
                "\n" +
                "\n" +
                "";
        String message = queryErrorMessage(xmlStr);
        System.out.println(message);
    }
    /**
     * @param model
     *            微信接口请求参数DTO对象
     * @return ResultEntity 返回结构体
     */
    public static ResultEntity doTransfers(String url, String path, TransfersDtoAdmin model, UserAccountModel userAccount, String stringBuild)
    {
        try
        {
            // 3.加载证书请求接口
            String result = HttpRequestHandler.httpsRequest(url, stringBuild,
                    model, path);
            log.debug(("response xml = " + result));
            if(result.contains("CDATA[FAIL]")){
                String message = queryErrorMessage(result);
                return new ResultEntity(false, message);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return new ResultEntity(false, e.getMessage());
        }
        return new ResultEntity(true);
    }
    public static String getStringBuild(TransfersDtoAdmin model){
        // 1.计算参数签名
        String paramStr = createLinkString(model);
        String mysign = paramStr + "&key=" + model.getAppkey();
        String sign = DigestUtils.md5Hex(mysign).toUpperCase();
        // 2.封装请求参数
        StringBuilder reqXmlStr = new StringBuilder();
        reqXmlStr.append("");
        reqXmlStr.append("" + model.getMchid() + "");
        reqXmlStr.append("" + model.getMch_appid() + "");
        reqXmlStr.append("" + model.getNonce_str() + "");
        reqXmlStr.append("" + model.getCheck_name() + "");
        reqXmlStr.append("" + model.getOpenid() + "");
        reqXmlStr.append("" + model.getAmount() + "");
        reqXmlStr.append("" + model.getDesc() + "");
        reqXmlStr.append("" + sign + "");
        reqXmlStr.append("" + model.getPartner_trade_no() + "");
        reqXmlStr.append("" + model.getSpbill_create_ip() + "");
        reqXmlStr.append("");
        log.debug("request xml = " + reqXmlStr);
        return reqXmlStr.toString();
    }
    private static String createLinkString(TransfersDtoAdmin model)
    {
        // 微信签名规则 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3
        Map paramMap = new HashMap();
        // 订单号默认用商户号+时间戳+4位随机数+可以根据自己的规则进行调整
        model.setAppkey(model.getAppkey());
        model.setNonce_str(WechatpayUtil.getNonce_str());
        model.setPartner_trade_no(model.getMchid()
                + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
                + (int)((Math.random() * 9 + 1) * 1000));
        paramMap.put("mch_appid", model.getMch_appid());
        paramMap.put("mchid", model.getMchid());
        paramMap.put("openid", model.getOpenid());
        paramMap.put("amount", model.getAmount());
        paramMap.put("check_name", model.getCheck_name());
        paramMap.put("desc", model.getDesc());
        paramMap.put("partner_trade_no", model.getPartner_trade_no());
        paramMap.put("nonce_str", model.getNonce_str());
        paramMap.put("spbill_create_ip", model.getSpbill_create_ip());
        List keys = new ArrayList(paramMap.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++ )
        {
            String key = keys.get(i);
            Object value = (Object)paramMap.get(key);
            if (i == keys.size() - 1)
            {// 拼接时,不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            }
            else
            {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }
    private static String getNonce_str()
    {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 15; i++ )
        {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}