package com.hfkj.channel.weixin.utils;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.weixin.entity.OrderRefundModel;
import com.hfkj.channel.weixin.utils.sdk.WXPayConstants;
import com.hfkj.config.CommonSysConst;
import org.apache.http.HttpEntity;
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 javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.util.*;

/**
 * 微信订单处理m
 */
public class WxOrderConfig {

    private static final Logger log = LoggerFactory.getLogger(WxOrderConfig.class);

    /**
     * 微信支付商户号
     * 个体户黎杨珍
     */
    public static final String MCH_ID_1609882817 = "1609882817";

    /**
     * 微信支付商户号
     * 重庆惠兑电子商务有限公司
     */
    public static final String MCH_ID_1614670195 = "1614670195";

    /**
     * 微信支付商户号
     * 惠昕（贵州）能源有限公司
     */
    public static final String MCH_ID_1619676214 = "1619676214";

    /**
     * 微信支付商户号
     * 惠昕（贵州）能源有限公司
     */
    public static final String MCH_ID_1634835264 = "1634835264";

    /**
     * 微信支付商户号
     * 渝北区浩联物资经营部
     */
    public static final String MCH_ID_1624126902 = "1624126902";

    /**
     * 订单退款
     * @param paySerialNo  第三方支付流水
     * @param outRefundNo  退款订单号
     * @param subMchId     商户号
     * @param totalFee     交易总金额
     * @param refundFee    退款金额
     * @return
     * @throws Exception
     */
    public static OrderRefundModel orderToRefund(String paySerialNo, String outRefundNo, String subMchId, BigDecimal totalFee, BigDecimal refundFee) throws Exception {
        Map<String,String> param = new HashMap<>();
        param.put("appid", "wx637bd6f7314daa46");
        param.put("mch_id", "1289663601");
        param.put("sub_mch_id" , subMchId);
        param.put("nonce_str", WxUtils.makeNonStr());
        param.put("transaction_id", paySerialNo);
        param.put("out_refund_no", outRefundNo);
        param.put("total_fee", String.valueOf(totalFee.multiply(new BigDecimal("100")).intValue()));
        param.put("refund_fee", String.valueOf(refundFee.multiply(new BigDecimal("100")).intValue()));
        param.put("sign_type", "HMAC-SHA256");
        String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
        param.put("sign", signStr);
        String resultXmL = doSSLRequest(param.get("mch_id"), "https://api.mch.weixin.qq.com/secapi/pay/refund", WxUtils.mapToXml(param));
        return XmlUtil.getObjectFromXML(resultXmL, OrderRefundModel.class);
    }

    /**
     * 【微信】创建分账
     * @param appId
     * @param subMchId
     * @param transactionId        第三方交易订单号
     * @param outOrderNo          交易订单号
     */
    public static TreeMap<String,String> profitsharingCreate(String appId,
                                                             String subMchId,
                                                             String transactionId,
                                                             String outOrderNo,
                                                             List<Map<String,Object>> receiversList) {
        try {
            Map<String,String> param = new LinkedHashMap<>();
            param.put("appid", appId);
            param.put("mch_id", "1289663601");
            param.put("sub_mch_id" , subMchId);
            param.put("transaction_id" , transactionId);
            param.put("out_order_no" , outOrderNo);
            param.put("nonce_str" , WxUtils.makeNonStr());

/*            List<Map<String,Object>> receiversList = new ArrayList<>();
            Map<String,Object> receiversMap = new LinkedHashMap<>();
            receiversMap.put("type", "MERCHANT_ID");
            receiversMap.put("account", receiversAccount);
            receiversMap.put("amount", amount.multiply(new BigDecimal("100")).intValue());
            receiversMap.put("description", "分给商户：" + receiversAccountName);
            receiversList.add(receiversMap);*/

            param.put("receivers" , JSONObject.toJSONString(receiversList));
            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);

            // 请求分账返回的结果
            String resultXmL = wechatRequest("https://api.mch.weixin.qq.com/secapi/pay/profitsharing", param.get("mch_id"), WxUtils.mapToXml(param));
            return XmlUtil.parseXmlToTreeMap(resultXmL, "utf-8");


        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
        }
        return null;
    }
    /**
     * 【微信】添加分账接收方
     * @param receiversName        接收方商户全称
     * @param receiversAccount     接收方商户
     */
    public static TreeMap<String,String> profitsharingAddReceiver(String subMchId,String receiversName,String receiversAccount) {
        try {
            Map<String,String> param = new LinkedHashMap<>();
            param.put("mch_id", "1289663601");
            param.put("sub_mch_id" , subMchId);
            param.put("appid", "wx637bd6f7314daa46");
            param.put("nonce_str" , WxUtils.makeNonStr());

            Map<String,Object> receivers = new LinkedHashMap<>();
            receivers.put("type", "MERCHANT_ID");
            receivers.put("account", receiversAccount);
            receivers.put("name", receiversName);
            receivers.put("relation_type", "SERVICE_PROVIDER");

            param.put("receiver" , JSONObject.toJSONString(receivers));
            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);

            // 请求分账返回的结果
            String resultXmL = wechatRequest("https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver", param.get("mch_id"), WxUtils.mapToXml(param));
            return XmlUtil.parseXmlToTreeMap(resultXmL, "utf-8");


        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
        }
        return null;
    }

  /*  *//**
     * 【微信】回退分账
     * @param appId
     * @param subMchId
     * @param transactionId        第三方交易订单号
     * @param outOrderNo          交易订单号
     *//*
    public static TreeMap<String,String> profitsharingReturn(String subMchId,
                                                             String profitsharingOrderNo,
                                                             String return_mchid,
                                                             String amount,
                                                             String description) {
        try {
            Map<String,String> param = new LinkedHashMap<>();
            param.put("sub_mchid" , subMchId);
            param.put("transaction_id" , transactionId);
            param.put("out_order_no" , outOrderNo);
            param.put("nonce_str" , WxUtils.makeNonStr());

*//*            List<Map<String,Object>> receiversList = new ArrayList<>();
            Map<String,Object> receiversMap = new LinkedHashMap<>();
            receiversMap.put("type", "MERCHANT_ID");
            receiversMap.put("account", receiversAccount);
            receiversMap.put("amount", amount.multiply(new BigDecimal("100")).intValue());
            receiversMap.put("description", "分给商户：" + receiversAccountName);
            receiversList.add(receiversMap);*//*

            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);

            // 请求分账返回的结果
            String resultXmL = wechatRequest("https://api.mch.weixin.qq.com/v3/profitsharing/return-orders", param.get("mch_id"), WxUtils.mapToXml(param));
            return XmlUtil.parseXmlToTreeMap(resultXmL, "utf-8");

        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
        }
        return null;
    }*/


    /**
     * 【微信】完结分账
     * @param appId
     * @param subMchId
     * @param transactionId         第三方交易订单号
     * @param profitSharingOrderNo  分账订单号
     * @param description           交易订单号
     */
    public static TreeMap<String,String> profitSharingFinish(String appId,
                                                               String subMchId,
                                                               String transactionId,
                                                               String profitSharingOrderNo,
                                                               String description) {
        try {
            Map<String,String> param = new LinkedHashMap<>();
            param.put("appid", appId);
            param.put("mch_id", "1289663601");
            param.put("sub_mch_id", subMchId);
            param.put("transaction_id" , transactionId);
            param.put("out_order_no" , profitSharingOrderNo);
            param.put("description" , description);
            param.put("nonce_str" , WxUtils.makeNonStr());

            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);

            // 请求分账返回的结果
            String resultXmL = wechatRequest("https://api.mch.weixin.qq.com/secapi/pay/profitsharingfinish", "1289663601", WxUtils.mapToXml(param));
            return XmlUtil.parseXmlToTreeMap(resultXmL, "utf-8");

        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
        }
        return null;
    }

    /**
     * 【微信】请求
     * @param mchId
     * @param data
     * @return
     * @throws Exception
     */
    public static String wechatRequest(String url,String mchId, String data) throws Exception {
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //P12文件目录 证书路径，这里需要你自己修改，linux下还是windows下的根路径
        FileInputStream instream = new FileInputStream("/home/project/wx_cert/1289663601_apiclient_cert.p12");
        try {
            keyStore.load(instream, "1289663601".toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "1289663601".toCharArray()).build();//这里也是写密码的
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        //小程序退款需要调用双向证书的认证
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "text/xml");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            httpClient.close();
        }
    }

    private static String doSSLRequest(String mchId, String url, String data) throws Exception {
        //双向证书的认证
        CloseableHttpClient httpClient = readCertificate(mchId);
        try {
            //HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund"); // 设置响应头信息
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "text/xml");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            httpClient.close();
        }
    }

    private static CloseableHttpClient readCertificate(String mchId) throws Exception{
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //P12文件目录 证书路径，这里需要你自己修改，linux下还是windows下的根路径
        // FileInputStream instream = new FileInputStream("/home/project/wx_cert/1289663601_apiclient_cert.p12");
        FileInputStream instream = new FileInputStream("/home/project/wx_cert/"+mchId+"_apiclient_cert.p12");
        try {
            keyStore.load(instream, mchId.toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();//这里也是写密码的
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        // Allow TLSv1 protocol only
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

}
