package com.xxfc.platform.universal.weixin.api;

import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.util.MD5Util;
import com.github.wxiaoqi.security.common.util.OrderUtil;
import com.github.wxiaoqi.security.common.util.process.SystemConfig;
import com.xxfc.platform.universal.weixin.util.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.jdom.JDOMException;
import org.springframework.core.io.ClassPathResource;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Map;
import java.util.TreeMap;


/**
 * 商家向用户转账，实现提现功能
 * @author SunnyShang
 *
 */
@Slf4j
public class WXSuppToUserPay {

	private static String suppTouser = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//商家向用户付款
    
    private String mch_appid; //公众账号appid
    private String mchid; //商户号
    private String nonce_str;//随机字符串
    private String sign;//签名
    private String partner_trade_no;//商户订单号
    private String openid;//用户openid
    private String check_name;//校验用户姓名选项 
    private String re_user_name;//收款用户姓名(可选)
    private String amount;//金额
    private String desc;//企业付款描述信息
    private String spbill_create_ip;//Ip地址
    private String key;
	
	public static Map<String,String> WeiXinTiXian(String openid,String partnerTradeNo,String check_name,String amount,String desc,String spbill_create_ip)
	{
		WXSuppToUserPay prePay = new WXSuppToUserPay();
			prePay.setMch_appid(SystemConfig.APP_ID);
			prePay.setMchid(SystemConfig.APP_PARTNER);
			prePay.setNonce_str( OrderUtil.CreateNoncestr());
			prePay.setPartner_trade_no(partnerTradeNo);
			prePay.setOpenid(openid);
			prePay.setCheck_name(check_name);
			prePay.setAmount(amount);
			prePay.setDesc(desc);
			prePay.setSpbill_create_ip(spbill_create_ip);
			String result =postXML(suppTouser,prePay.getXMLTuiKuan());
			result = result.replaceAll("<![CDATA[|]]>", "").replaceAll("支付成功", "pay sucess");
		Map<String, String> map = null;
		try {
			map = XMLUtil.doXMLParse(result);
		} catch (JDOMException e) {
		    throw  new BaseException("微信转账参数xml解析错误",e);
		} catch (IOException e) {
			throw new BaseException("微信转账参数xml解析读写IO异常",e);
		}
		return map;
	}
	public static String postXML(String uri, String xml) {
		CloseableHttpClient httpclient = null;
		try {
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
//			FileInputStream instream = new FileInputStream(new File("E:/cert/apiclient_cert.p12"));
			ClassPathResource classPathResource = new ClassPathResource("apiclient_cert.p12");
			InputStream instream = classPathResource.getInputStream();
			try {
				keyStore.load(instream, SystemConfig.APP_PARTNER.toCharArray());
			} finally {
				if (instream != null) {
					instream.close();
				}
			}
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, SystemConfig.APP_PARTNER.toCharArray()).build();
			@SuppressWarnings("deprecation")
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" },
					null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			return post(httpclient, uri, xml, "text/xml; charset=UTF-8", "UTF-8", null, null);
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
		} finally {
			if (httpclient != null) {

				try {
					httpclient.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);;
				}
			}
		}
		return null;
	}
	
	
	public static String post(CloseableHttpClient httpclient, String uri, String data, String miniType, String charset,
			String cookie, String refer) {
		HttpPost httpPost = new HttpPost(uri);
		if (miniType != null) {
			httpPost.setHeader("Content-Type", miniType);
		}

		if (data != null) {
			StringEntity stringEntity = null;
			try {
				if (charset != null) {
					stringEntity = new StringEntity(data, charset);
				} else {
					stringEntity = new StringEntity(data);
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);;
				return "failure";
			}

			httpPost.setEntity(stringEntity);
		}
		if (cookie != null) {
			httpPost.setHeader("Cookie", cookie);
		}
		if (refer != null) {
			httpPost.setHeader("Refer", refer);
		}
	
		CloseableHttpResponse httpResponse = null;
		HttpContext httContext = HttpClientContext.create();
		try {
			httpResponse = httpclient.execute(httpPost, httContext);
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
			return "failure";
		}

		HttpEntity httpEntity = null;
		try {
			httpEntity = httpResponse.getEntity();
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
			return "failure";
		}

		String response_body = null;
		try {
			response_body = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
			return "failure";
		}
		try {
			httpResponse.close();
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
		}
		try {
			httpclient.close();
		} catch (Exception e) {
			log.error(e.getMessage(), e);;
		}

		return response_body;
	}
	
	
	
	
	
	
	public String getXMLTuiKuan(){
		TreeMap<String, String> treeMap = new TreeMap<String, String>();
		treeMap.put("mch_appid", this.mch_appid);
		treeMap.put("mchid", this.mchid);
		treeMap.put("nonce_str", this.nonce_str);
		treeMap.put("partner_trade_no", this.partner_trade_no);
		treeMap.put("openid", this.openid);
		treeMap.put("check_name", this.check_name);
		//treeMap.put("re_user_name", this.re_user_name);
		treeMap.put("amount", this.amount);
		treeMap.put("desc", this.desc);
		treeMap.put("spbill_create_ip", this.spbill_create_ip);
		//treeMap.put("key", this.key);
		//treeMap.put("sign", this.sign);
		StringBuilder sb = new StringBuilder();
		for (String key : treeMap.keySet()) {
			sb.append(key).append("=").append(treeMap.get(key)).append("&");
		}
		sb.append("key=" + SystemConfig.WINXIN_PARTNER_KEY);
		sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase();
		treeMap.put("sign", sign);
		StringBuilder xml = new StringBuilder();
		xml.append("<xml>\n");
		for (Map.Entry<String, String> entry : treeMap.entrySet()) {
			if ("body".equals(entry.getKey()) || "sign".equals(entry.getKey())) {
				xml.append("<" + entry.getKey() + "><![CDATA[").append(entry.getValue()).append("]]></" + entry.getKey() + ">\n");
			} else {
				xml.append("<" + entry.getKey() + ">").append(entry.getValue()).append("</" + entry.getKey() + ">\n");
			}
		}
		xml.append("</xml>");
		return xml.toString();	
	}
	
	
	public String getMch_appid() {
		return mch_appid;
	}
	public void setMch_appid(String mch_appid) {
		this.mch_appid = mch_appid;
	}
	public String getMchid() {
		return mchid;
	}
	public void setMchid(String mchid) {
		this.mchid = mchid;
	}
	public String getNonce_str() {
		return nonce_str;
	}
	public void setNonce_str(String nonce_str) {
		this.nonce_str = nonce_str;
	}
	public String getSign() {
		return sign;
	}
	public void setSign(String sign) {
		this.sign = sign;
	}
	public String getPartner_trade_no() {
		return partner_trade_no;
	}
	public void setPartner_trade_no(String partner_trade_no) {
		this.partner_trade_no = partner_trade_no;
	}
	public String getOpenid() {
		return openid;
	}
	public void setOpenid(String openid) {
		this.openid = openid;
	}
	public String getCheck_name() {
		return check_name;
	}
	public void setCheck_name(String check_name) {
		this.check_name = check_name;
	}
	public String getRe_user_name() {
		return re_user_name;
	}
	public void setRe_user_name(String re_user_name) {
		this.re_user_name = re_user_name;
	}
	public String getAmount() {
		return amount;
	}
	public void setAmount(String amount) {
		this.amount = amount;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	public String getSpbill_create_ip() {
		return spbill_create_ip;
	}
	public void setSpbill_create_ip(String spbill_create_ip) {
		this.spbill_create_ip = spbill_create_ip;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}
 
}
