package com.iamberry.wechat.tools;

import com.alibaba.fastjson.JSON;
import com.iamberry.wechat.tools.MoneyUtils;
import com.iamberry.wechat.tools.NameUtils;
import com.iamberry.wechat.tools.ResponseJson;
import com.iamberry.wechat.tools.payUtil.CollectionUtil;
import com.iamberry.wechat.tools.payUtil.JsonResult;
import com.iamberry.wechat.tools.payUtil.PayUtils;
import com.iamberry.wechat.tools.payUtil.ResponseData;
import com.iamberry.wechat.tools.payUtil.SerializerFeatureUtil;
import com.iamberry.wechat.tools.payUtil.WebUtil;
import com.iamberry.wechat.tools.payUtil.XmlUtil;

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.protocol.HTTP;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.Args;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 创建时间：2017年5月4日14:52:30
 * 
 * @author LJK
 * @version 2.2
 */
public class PayUtil {

	private static final Logger LOG = Logger.getLogger(PayUtil.class);
	
    private static final String TRANSFERS_PAY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; // 企业付款

    private static final String TRANSFERS_PAY_QUERY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; // 企业付款查询

	/**
	 * 发起转账（转账调用此方法）
	 * @param openid
	 * @param orderid
	 * @param amount
	 * @param dese
	 * @return
	 */
	 public static ResponseJson transferPay(String openid, String orderid,Integer amount,String dese) {
         Map<String, String> restmap = null;
         ResponseJson json = new ResponseJson();
         String partner_trade_no = getTransgerOrderno(NameUtils.getConfig("partner"));//生成商户订单号
         try {
        	 SortedMap<String,String> parm=new TreeMap<String,String>();  
             parm.put("mch_appid", NameUtils.getConfig("appId")); //公众账号appid
             parm.put("mchid", NameUtils.getConfig("partner")); //商户号
             parm.put("nonce_str", PayUtils.getNonceStr()); //随机字符串
             parm.put("partner_trade_no", partner_trade_no); //商户订单号
             parm.put("openid", openid); //用户openid  
             parm.put("check_name", "NO_CHECK"); //校验用户姓名选项 OPTION_CHECK
             //parm.put("re_user_name", "流健康"); //check_name设置为FORCE_CHECK或OPTION_CHECK，则必填
             parm.put("amount",String.valueOf(amount)); //转账金额
             parm.put("desc", dese); //企业付款描述信息
             parm.put("spbill_create_ip",getLocalIP()); //服务器Ip地址"112.74.68.5"
             parm.put("sign", PayUtils.createSign("UTF-8",parm, NameUtils.getConfig("appSecret")));
            // parm.put("sign", PayUtil.createSign(parm, NameUtils.getConfig("appSecret")));
             String xmlparm = XmlUtil.xmlFormat(parm, false);
             String restxml = doSendMoney(TRANSFERS_PAY, xmlparm);
             restmap = XmlUtil.xml2map(restxml, false);
         } catch (Exception e) {
             LOG.error(e.getMessage(), e);
            json.setReturnCode(503);
 			json.setResultCode(200);
 			json.addResponseKeyValue("支付异常！");
 			return json;
         }

         if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
             LOG.info("转账成功：" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
             Map<String, Object> transferMap = new HashMap<>();
             transferMap.put("partner_trade_no", restmap.get("partner_trade_no"));//商户转账订单号
             transferMap.put("payment_no", restmap.get("payment_no")); //微信订单号
             transferMap.put("payment_time", restmap.get("payment_time")); //微信支付成功时间 
             /*WebUtil.response(response,
                     WebUtil.packJsonp(null,
                             JSON.toJSONString(new JsonResult(1, "转账成功", new ResponseData(null, transferMap)),
                                     SerializerFeatureUtil.FEATURES)));*/
             json.setReturnCode(200);
  			json.setResultCode(200);
  			json.addResponseKeyValue("支付成功！");
  			json.setReturnMsg(transferMap);
             json.addResponseKeyValue("partner_trade_no",partner_trade_no);
  			return json;
         }else {
             if (CollectionUtil.isNotEmpty(restmap)) {
                 LOG.info("转账失败：" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
             }
            /* WebUtil.response(response, WebUtil.packJsonp(null, JSON
                     .toJSONString(new JsonResult(-1, "转账失败", new ResponseData()), SerializerFeatureUtil.FEATURES)));*/
            json.setReturnCode(503);
  			json.setResultCode(200);
  			json.addResponseKeyValue(restmap.get("err_code_des"));
             json.addResponseKeyValue("partner_trade_no",partner_trade_no);
  			return json;
         }
     }
	
	 public static ResponseJson checkEnterprisePayment(HttpServletRequest request, HttpServletResponse response,  String orderid) {
        LOG.info("[/transfer/checkEnterprisePayment]");
        Map<String, String> restmap = null;
        ResponseJson json = new ResponseJson();
        try {
       	 SortedMap<String,String> parm=new TreeMap<String,String>();  
            parm.put("appid", NameUtils.getConfig("appId")); //公众账号appid
            parm.put("mch_id", NameUtils.getConfig("partner")); //商户号
            parm.put("nonce_str", PayUtils.getNonceStr()); //随机字符串
            parm.put("partner_trade_no", orderid); //商户订单号
            parm.put("sign", PayUtils.createSign("UTF-8",parm, NameUtils.getConfig("appSecret")));
           // parm.put("sign", PayUtil.createSign(parm, NameUtils.getConfig("appSecret")));
            String xmlparm = XmlUtil.xmlFormat(parm, false);
            String restxml = doSendMoney(TRANSFERS_PAY_QUERY, xmlparm);
            restmap = XmlUtil.xml2map(restxml, false);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
           json.setReturnCode(503);
			json.setResultCode(200);
			json.addResponseKeyValue("支付异常！");
			return json;
        }

        if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
            LOG.info("查询成功：" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
            Map<String, Object> transferMap = new HashMap<>();
            transferMap.put("partner_trade_no", restmap.get("partner_trade_no"));//商户转账订单号
            transferMap.put("payment_no", restmap.get("payment_no")); //微信订单号
            transferMap.put("payment_time", restmap.get("payment_time")); //微信支付成功时间 
            WebUtil.response(response,
                    WebUtil.packJsonp(null,
                            JSON.toJSONString(new JsonResult(1, "查询成功", new ResponseData(null, transferMap)),
                                    SerializerFeatureUtil.FEATURES)));
           json.setReturnCode(200);
 			json.setResultCode(200);
 			json.addResponseKeyValue("查询成功！");
 			json.setReturnMsg(transferMap);
 			return json;
        }else {
            if (CollectionUtil.isNotEmpty(restmap)) {
                LOG.info("查询失败：" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
            }
            WebUtil.response(response, WebUtil.packJsonp(null, JSON
                    .toJSONString(new JsonResult(-1, "查询失败", new ResponseData()), SerializerFeatureUtil.FEATURES)));
           json.setReturnCode(503);
 			json.setResultCode(200);
 			json.addResponseKeyValue(restmap.get("err_code_des"));
 			return json;
        }
    }
	/**
	 * 发送转账请求
	 * */
	public static String doSendMoney(String url, String data) throws Exception {
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		// FileInputStream instream = new FileInputStream(new
		// File(KEYSTORE_FILE));//P12文件目录
		InputStream instream = MoneyUtils.class.getResourceAsStream("/apiclient_cert.p12");
		try {
			keyStore.load(instream, NameUtils.getConfig("KEYSTORE_PASSWORD").toCharArray());// 这里写密码..默认是你的MCHID
		} finally {
			instream.close();
		}
		// Trust own CA and all self-signed certs
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, NameUtils.getConfig("KEYSTORE_PASSWORD").toCharArray())// 这里也是写密码的
				.build();
		// Allow TLSv1 protocol only
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
				sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		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",
					"application/x-www-form-urlencoded; charset=UTF-8");
			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 = toStringInfo(response.getEntity(), "UTF-8");
				EntityUtils.consume(entity);
				return jsonStr;
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
	}
	
	private static String toStringInfo(HttpEntity entity, String defaultCharset)
			throws Exception, IOException {
		final InputStream instream = entity.getContent();
		if (instream == null) {
			return null;
		}
		try {
			Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
					"HTTP entity too large to be buffered in memory");
			int i = (int) entity.getContentLength();
			if (i < 0) {
				i = 4096;
			}
			Charset charset = null;
			if (charset == null) {
				charset = Charset.forName(defaultCharset);
			}
			if (charset == null) {
				charset = HTTP.DEF_CONTENT_CHARSET;
			}
			final Reader reader = new InputStreamReader(instream, charset);
			final CharArrayBuffer buffer = new CharArrayBuffer(i);
			final char[] tmp = new char[1024];
			int l;
			while ((l = reader.read(tmp)) != -1) {
				buffer.append(tmp, 0, l);
			}
			return buffer.toString();
		} finally {
			instream.close();
		}
	}
	
	public static String getLocalIP() {
		try {
			String localIP = "";
			InetAddress addr = (InetAddress) InetAddress.getLocalHost();
			// 获取本机IP
			localIP = addr.getHostAddress().toString();
			return localIP;
		} catch (Exception e) {
			return "120.76.152.52";
		}
	}

	public static String getTransgerOrderno(String mchid){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        StringBuffer s = new StringBuffer();
        for (int i=0;i<10;i++){
            s.append(String.valueOf((int)(10*(Math.random()))));
        }
        String transgerOrderno =  mchid+formatter.format(new Date())+s;
        return transgerOrderno;
    }
}
