package com.iamberry.wechat.tools;

import java.net.URL;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import com.alibaba.dubbo.common.utils.ConfigUtils;
import com.alibaba.fastjson.JSONObject;
import com.iamberry.app.tool.des.MD5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 支付核心类
 */
@Component
public class WxPayUtil {
	
	@Autowired
	private RequestHandler reqHandler;
	public void setReqHandler(RequestHandler reqHandler) {
		this.reqHandler = reqHandler;
	}

	private static Logger logger = LoggerFactory.getLogger(WxPayUtil.class);
	
	/**
	 * 获取微信扫码支付二维码连接
	 */
	public String getCodeurl(WxPayDto tpWxPayDto, String notifyurl){
		// 1 参数
		// 订单号
		String orderId = tpWxPayDto.getOrderId();
		// 附加数据 原样返回
		String attach = "";
		// 总金额以分为单位，不带小数点
		String totalFee = getMoney(tpWxPayDto.getTotalFee());
		
		// 订单生成的机器 IP
		String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
		// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
		String notify_url = notifyurl;
		String trade_type = "NATIVE";

		// 商户号
		String mch_id = NameUtils.getConfig("partner");
		// 随机字符串
		String nonce_str = getNonceStr();

		// 商品描述根据情况修改
		String body = tpWxPayDto.getBody();

		// 商户订单号
		String out_trade_no = orderId;

		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", NameUtils.getConfig("appId"));
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		packageParams.put("attach", attach);
		packageParams.put("out_trade_no", out_trade_no);

		// 这里写的金额为1 分到时修改
		packageParams.put("total_fee", totalFee);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);

		packageParams.put("trade_type", trade_type);

		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(NameUtils.getConfig("appId"), NameUtils.getConfig("appsecret"), NameUtils.getConfig("partnerkey"));

		String sign = reqHandler.createSign(packageParams);
		String xml = "<xml>" + "<appid>" + NameUtils.getConfig("appId") + "</appid>" + "<mch_id>"
				+ mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
				+ "</nonce_str>" + "<sign>" + sign + "</sign>"
				+ "<body><![CDATA[" + body + "]]></body>" 
				+ "<out_trade_no>" + out_trade_no
				+ "</out_trade_no>" + "<attach>" + attach + "</attach>"
				+ "<total_fee>" + totalFee + "</total_fee>"
				+ "<spbill_create_ip>" + spbill_create_ip
				+ "</spbill_create_ip>" + "<notify_url>" + notify_url
				+ "</notify_url>" + "<trade_type>" + trade_type
				+ "</trade_type>" + "</xml>";
		String code_url = "";
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		
		
		code_url = GetWxOrderno.getCodeUrl(createOrderURL, xml);
		
		return code_url;
	}

	/**
	 * 订单退款,退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后重新查询退款状态
	 * @param transaction_id	微信订单号
	 * @param out_trade_no		商户订单号
	 * @param out_refund_no		商户退款订单号
	 * @param total_fee			订单总金额,单位为分
	 * @param refund_fee		退款金额，单位为分
	 * @return ResponseJson		result = 200，表示成功，resultMsg 为微信退款ID，需要保存；其他均为失败
	 */
	public static ResponseJson refund(String transaction_id, String out_trade_no, String out_refund_no, int total_fee, int refund_fee) {
		ResponseJson json = new ResponseJson();
		json.setReturnCode(200);

		String appid = NameUtils.getConfig("appId");
		String machId = NameUtils.getConfig("partner");
		String nonce_str = getNonceStr();

		// 签名
		String temp = new StringBuilder("appid=").append(appid).append("&mch_id=").append(machId).append("&nonce_str=").append(nonce_str).append("&op_user_id=").append(machId)
						.append("&out_refund_no=").append(out_refund_no).append("&out_trade_no=").append(out_trade_no)
						.append("&refund_fee=").append(refund_fee).append("&total_fee=").append(total_fee).append("&transaction_id=")
						.append(transaction_id).append("&key=").append(NameUtils.getConfig("partnerkey")).toString();
		String sign = MD5Util.MD5Encode(temp, "UTF-8").toUpperCase();
		// 拼装XML参数
		String params = new StringBuilder("<xml>").append("<appid>").append(appid).append("</appid>").append("<mch_id>").append(machId)
							.append("</mch_id>").append("<nonce_str>").append(nonce_str).append("</nonce_str>").append("<op_user_id>")
							.append(machId).append("</op_user_id>").append("<out_refund_no>").append(out_refund_no).append("</out_refund_no>")
							.append("<out_trade_no>").append(out_trade_no).append("</out_trade_no>").append("<refund_fee>").append(refund_fee)
							.append("</refund_fee>").append("<total_fee>").append(total_fee).append("</total_fee>").append("<transaction_id>")
							.append(transaction_id).append("</transaction_id>").append("<sign>").append(sign).append("</sign>").append("</xml>").toString();
		// 请求支付
		try {
			String path = WxPayUtil.class.getClassLoader().getResources("apiclient_cert.p12").nextElement().getPath().substring(1);
			// 发送请求
			String result = HttpClient431Util.doDualSSLPost(params, "https://api.mch.weixin.qq.com/secapi/pay/refund", path, machId);
			Map<String, String> resMap = GetWxOrderno.doXMLParse(result);
			logger.info("{}:{}", "微信退款操作返回", result);
			if (!"SUCCESS".equals(resMap.get("return_code"))) {
				// 失败
				json.setResultCode(500);
				json.setResultMsg(resMap.get("return_msg"));
				return json;
			}
			if (!"SUCCESS".equals(resMap.get("result_code"))) {
				// 业务失败
				json.setResultCode(500);
				json.setResultMsg(resMap.get("err_code_des"));
				return json;
			}

			json.setResultCode(200);
			json.setResultMsg(resMap.get("refund_id"));
			return json;
		} catch (Exception e) {
			logger.error("申请订单退款操作失败,错误结果:{}", e);
		}
		json.setResultCode(500);
		json.setResultMsg("ERROR");
		return json;
	}
	
	
	/**
	 * 获取请求预支付id报文
	 * @return
	 */
	public Object getPackage(
			String openid, 
			String orderid, 
			Integer total, 
			String ip, 
			String bodyStr,
			String appIdStr,
			String notifyurl) {
		
		String openId = openid;
		// 1 参数
		// 订单号
		String orderId = orderid;
		// 附加数据 原样返回,此处对订单idMD5加密
		
		String attach = null;
		try {
			attach = StaticInfo.orderIdMD5.encrypt(orderid);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 总金额以分为单位，不带小数点
		String totalFee = total.toString(); 
				//getMoney(total);
		// 订单生成的机器 IP
		String spbill_create_ip = ip;
		// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
		String notify_url = notifyurl;
		String trade_type = "JSAPI";
		// ---必须参数
		// 商户号
		String mch_id = NameUtils.getConfig("partner");
		// 随机字符串
		String nonce_str = getNonceStr();
		// 商品描述根据情况修改
		String body = bodyStr;
		// 商户订单号
		String out_trade_no = orderId;
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appIdStr);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		packageParams.put("attach", attach);
		packageParams.put("out_trade_no", out_trade_no);
		// 这里写的金额为1 分到时修改
		packageParams.put("total_fee", totalFee);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);
		packageParams.put("trade_type", trade_type);
		packageParams.put("openid", openId);
		reqHandler.init(NameUtils.getConfig("appId"), NameUtils.getConfig("appsecret"), NameUtils.getConfig("partnerkey"));
		String sign = reqHandler.createSign(packageParams);
		String xml = "<xml>"
					+ "<appid>" + NameUtils.getConfig("appId") + "</appid>" 
					+ "<mch_id>" + mch_id + "</mch_id>" 
					+ "<nonce_str>" + nonce_str + "</nonce_str>" 
					+ "<sign>" + sign + "</sign>"
					+ "<body><![CDATA[" + body + "]]></body>" 
					+ "<out_trade_no>" + out_trade_no + "</out_trade_no>" 
					+ "<attach>" + attach + "</attach>"
					+ "<total_fee>" + totalFee + "</total_fee>"
					+ "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>" 
					+ "<notify_url>" + notify_url + "</notify_url>" 
					+ "<trade_type>" + trade_type + "</trade_type>" 
					+ "<openid>" + openId + "</openid>"
				+ "</xml>";
		String prepay_id = "";
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		//判断
		Object string = GetWxOrderno.getPayNo(createOrderURL, xml);
		if (string.getClass() == String.class) {
			prepay_id = string.toString();
		} else {
			WxPrepayIdErrorResult errorResult = (WxPrepayIdErrorResult) string;
			if (errorResult.getErr_code_des() != null && errorResult.getErr_code_des().equals("商户订单号重复")) {
				// 最大的可能意味着，此订单的金额发生改变
				errorResult.setErr_code_des("对不起，您的订单号重复，请重新下单!");
			} else {
				errorResult.setErr_code_des(errorResult.getReturn_msg());
			}
			return errorResult;
		}
		//获取prepay_id后，拼接最后请求支付所需要的package
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = Sha1Util.getTimeStamp();
		String packages = "prepay_id="+prepay_id;
		finalpackage.put("appId", NameUtils.getConfig("appId"));  
		finalpackage.put("timeStamp", timestamp);  
		finalpackage.put("nonceStr", nonce_str);  
		finalpackage.put("package", packages);  
		finalpackage.put("signType", "MD5");
		//签名
		String finalsign = reqHandler.createSign(finalpackage);
		String finaPackage = "\"appId\":\"" + NameUtils.getConfig("appId") + "\",\"timeStamp\":\"" + timestamp + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\"" + packages + "\",\"signType\":\"MD5" + "\",\"paySign\":\"" + finalsign + "\"";
		return finaPackage;
	}

	/**
	 * 获取随机字符串
	 * @return
	 */
	public static String getNonceStr() {
		// 随机数
		String currTime = TenpayUtil.getCurrTime();
		// 8位日期
		String strTime = currTime.substring(8, currTime.length());
		// 四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		// 10位序列号,可以自行调整。
		return strTime + strRandom;
	}

	/**
	 * 元转换成分
	 * @param money
	 * @return
	 */
	public static String getMoney(String amount) {
		if(amount==null){
			return "";
		}
		// 金额转化为分为单位
		String currency =  amount.replaceAll("\\$|\\￥|\\,", "");  //处理包含, ￥ 或者$的金额  
        int index = currency.indexOf(".");  
        int length = currency.length();  
        Long amLong = 0l;  
        if(index == -1){  
            amLong = Long.valueOf(currency+"00");  
        }else if(length - index >= 3){  
            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));  
        }else if(length - index == 2){  
            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);  
        }else{  
            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");  
        }  
        return amLong.toString(); 
	}
}
