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.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
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.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.jdom.JDOMException;


/**
 * 商家向用户转账，实现提现功能
 * @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 void main(String[] args) throws Exception, IOException { 

	 	Map<String, String> map = WXSuppToUserPay.WeiXinTiXian("oRhMfwKwjNq2Ce-TxlqfoAqsYfww",OrderUtil.GetOrderNumber("TX"),"NO_CHECK", 500+"", "活动提现", "192.168.8.109");
		if("SUCCESS".equals(map.get("return_code")))
		{
			if(!StringUtils.isBlank(map.get("payment_no")) && !StringUtils.isBlank(map.get("partner_trade_no")) )
			{
				System.out.println(map.get("partner_trade_no"));
				System.out.println(map.get("payment_no"));
				System.out.println(Integer.parseInt(System.currentTimeMillis()/1000+""));
	 
			 
			} 
			System.out.println(map.get("return_code"));
		} 
//		WXSuppToUserPay prePay = new WXSuppToUserPay();
	/*	prePay.setMch_appid(SystemConfig.WINXIN_AppID);
		prePay.setMchid(SystemConfig.WINXIN_PARTNER);*/
//		prePay.setMch_appid(SystemConfig.APP_ID);
//		prePay.setMchid(SystemConfig.APP_PARTNER);
//		prePay.setNonce_str( OrderUtil.CreateNoncestr());
//		prePay.setPartner_trade_no(OrderUtil.GetOrderNumber("TX"));
//		prePay.setOpenid("oRhMfwBQ-Ouqhff4AeFOqovgJOAs");
//		prePay.setCheck_name("NO_CHECK");
//		prePay.setAmount("100");
//		prePay.setDesc("活动提现");
//		prePay.setSpbill_create_ip("192.168.8.109");
//		//prePay.setKey(SystemConfig.WINXIN_PARTNER_KEY);
//		String result =postXML(suppTouser,prePay.getXMLTuiKuan());
		
//		String result = "<xml>"+
//		"<return_code><![CDATA[SUCCESS]]></return_code>"+
//		"<return_msg><![CDATA[]]></return_msg>"+
//		"<mch_appid><![CDATA[wxa9805823769294b6]]></mch_appid>"+
//		"<mchid><![CDATA[1327473801]]></mchid>"+
//		"<device_info><![CDATA[]]></device_info>"+
//		"<nonce_str><![CDATA[FD45EBC1E1D76BC1FE0BA933E60E9957]]></nonce_str>"+
//		"<result_code><![CDATA[SUCCESS]]></result_code>"+
//		"<partner_trade_no><![CDATA[TX20160504120550000001]]></partner_trade_no>"+
//		"<payment_no><![CDATA[1000018301201605040163328553]]></payment_no>"+
//		"<payment_time><![CDATA[2016-05-04 12:05:51]]></payment_time>"+
//		"</xml>";
//		
//		
//		result = result.replaceAll("<![CDATA[|]]>", "");
//		
//		Map<String, String> map = XMLUtil.doXMLParse(result);
//		
//		System.out.println(map.get("return_code"));
//		System.out.println(map.get("mchid"));
//		System.out.println(map.get("payment_no"));
//		System.out.println(map.get("partner_trade_no"));
//		System.out.println(map.get("payment_time"));
	}
	
	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.WINXIN_AppID);
			prePay.setMchid(SystemConfig.WINXIN_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"));
			String path = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
			FileInputStream instream = new FileInputStream(new File(path+"/apiclient_cert.p12"));
			try {
				keyStore.load(instream, SystemConfig.WINXIN_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.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			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;
	}
 
}
