package com.wechat.pay;

import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.library.config.ConfigCon;
import com.library.util.ClientInternet;
import com.library.util.Tools;



public class WeChatAPPManager {
	public static void main(String[] args) {
//		String post=getWeiXinXML("198.168.1.1", 12,"13");
//		System.out.println(post);
//		String res=ClientInternet.OpearConnect("https://api.mch.weixin.qq.com/pay/unifiedorder", null, post);
//		System.out.println(res);
//		String resc="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[wxb1da7561feb15929]]></appid><mch_id><![CDATA[1437388502]]></mch_id><nonce_str><![CDATA[usLgwY7LaXlf4F4m]]></nonce_str><sign><![CDATA[8F77B5A7D701C2E1D98EE6AFC54B09CE]]></sign><result_code><![CDATA[SUCCESS]]></result_code><prepay_id><![CDATA[wx20170209102827423e5aa5ca0083727592]]></prepay_id><trade_type><![CDATA[APP]]></trade_type></xml>";
//		System.out.println(Tools.gson.toJson(CreatBean(AnalysisXML(resc))));
		
		System.out.println(Tools.gson.toJson(GetAccess_token("051gFS7s01O5Cc19Fmas0z2R7s0gFS7s")));
	}
	
	
	/**
	 * 通过code获取access_token以及其他信息
	 */
	public static AccessToken GetAccess_token(String code){
		String address="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ConfigCon.WeChatAPP_Appid+
				"&secret="+ConfigCon.WeChatAPP_AppSecret+"&code="+code+"&grant_type=authorization_code";
		String res=ClientInternet.OpearConnect(address, null, "");
		AccessToken accessToken=Tools.gson.fromJson(res, AccessToken.class);
		return accessToken;
	}
	
	/**
	 * 一套生成所有订单参数
	 */
	public static AppPayBean CreatAllPaream(String spbill_create_ip,String body,String out_trade_no,int total_fee,String WX_Notify_url){
		String post=getWeiXinXML(spbill_create_ip, total_fee, out_trade_no,WX_Notify_url,body);
		String return_res=ClientInternet.OpearConnect("https://api.mch.weixin.qq.com/pay/unifiedorder", null, post);
		String prepay_id=AnalysisXML(return_res);
		return CreatBean(prepay_id);
	}
	
	
	/**
	 * 生成返回给APP支付的Bean
	 */
	private static AppPayBean CreatBean(String prepay_id){
		AppPayBean bean=new AppPayBean();
		bean.appId=ConfigCon.WeChatAPP_Appid;
		bean.nonceStr=Md5(""+System.currentTimeMillis());
		bean.partnerId=ConfigCon.WeChatAPP_Mch_id;
		bean.prepayId=prepay_id;
		bean.packageValue = "Sign=WXPay";
		bean.timeStamp=""+System.currentTimeMillis()/1000;
		
		SortedMap<String,String> parameters = new TreeMap<String,String>();  
	    parameters.put("appid", bean.appId);  
	    parameters.put("partnerid", bean.partnerId); 
	    parameters.put("prepayid", bean.prepayId);  
	    parameters.put("package", bean.packageValue);  
	    parameters.put("noncestr", bean.nonceStr); 
	    parameters.put("timestamp", bean.timeStamp);
	    
	    bean.sign=createSign("UTF-8",parameters);
	    return bean;
	}
	
	
	/**
	 * 解析下单返回的XML,获得prepay_id，预支付交易会话标识,下单出错则返回空字符
	 * <xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[wxb1da7561feb15929]]></appid><mch_id><![CDATA[1437388502]]></mch_id><nonce_str><![CDATA[usLgwY7LaXlf4F4m]]></nonce_str><sign><![CDATA[8F77B5A7D701C2E1D98EE6AFC54B09CE]]></sign><result_code><![CDATA[SUCCESS]]></result_code><prepay_id><![CDATA[wx20170209102827423e5aa5ca0083727592]]></prepay_id><trade_type><![CDATA[APP]]></trade_type></xml>
	 */
	private static String AnalysisXML(String XMLcon){
		try {
			Document document=DocumentHelper.parseText(XMLcon);
			Element element=document.getRootElement();
			String return_code=element.elementText("return_code");
			String result_code=element.elementText("result_code");
			if(return_code.equals("SUCCESS") && result_code.equals("SUCCESS")){
				return element.elementText("prepay_id");
			}else{
				return "";
			}
		} catch (DocumentException e) {
			e.printStackTrace();
			return "";
		}
	}
	
	
	/**
	 * 下单生成的字符串
	 */
	private static String getWeiXinXML(String spbill_create_ip,int total_fee,String out_trade_no,String WX_Notify_url,String body){
//		String body="APP支付";
//		String WX_Notify_url=ConfigCon.WeChat_Notify_urlshopBond;
		
		String trade_type="APP";
		String nonce_str=Md5(System.currentTimeMillis()+"");
		
		
		SortedMap<String,String> parameters = new TreeMap<String,String>();  
	    parameters.put("appid", ConfigCon.WeChatAPP_Appid);  
	    parameters.put("body", body); 
	    parameters.put("mch_id", ConfigCon.WeChatAPP_Mch_id);  
	    parameters.put("nonce_str", nonce_str);  
	    parameters.put("notify_url",WX_Notify_url ); 
	    parameters.put("out_trade_no", out_trade_no);  
	    parameters.put("spbill_create_ip", spbill_create_ip);  
	    parameters.put("total_fee", ""+total_fee);
	    parameters.put("trade_type", trade_type);
	    
	    String sign=createSign("UTF-8",parameters);;
		
		String con="<xml>";
		con+="<appid>"+ConfigCon.WeChatAPP_Appid+"</appid>";
		con+="<body>"+body+"</body>";
		con+="<mch_id>"+ConfigCon.WeChatAPP_Mch_id+"</mch_id>";
		con+="<nonce_str>"+nonce_str+"</nonce_str>";//随机字符串，不长于32位
		con+="<notify_url>"+WX_Notify_url+"</notify_url>";
		con+="<out_trade_no>"+out_trade_no+"</out_trade_no>";
		con+="<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>";//用户端实际ip
		con+="<total_fee>"+total_fee+"</total_fee>";//订单总金额，单位为分
		con+="<trade_type>"+trade_type+"</trade_type>";// 支付类型 
		con+="<sign>"+sign+"</sign>";
		con+="</xml>";
		return con;
	}
	
	
	
	
	
	
	
	
	/** 
	 * 生成下单签名
	 */
	    //定义签名，微信根据参数字段的ASCII码值进行排序 加密签名,故使用SortMap进行参数排序
	private static String createSign(String characterEncoding,SortedMap<String,String> parameters){
	        StringBuffer sb = new StringBuffer();
	        Set es = parameters.entrySet();
	        Iterator it = es.iterator();
	        while(it.hasNext()) {
	            Map.Entry entry = (Map.Entry)it.next();
	            String k = (String)entry.getKey();
	            Object v = entry.getValue();
	            if(null != v && !"".equals(v)
	                    && !"sign".equals(k) && !"key".equals(k)) {
	                sb.append(k + "=" + v + "&");
	            }
	        }
	        sb.append("key=" + ConfigCon.WeChatAPP_APIKey);//最后加密时添加商户密钥，由于key值放在最后，所以不用添加到SortMap里面去，单独处理，编码方式采用UTF-8
	        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
	        return sign;
	    }
	    
	    
	private static String Md5(String password) {
			try {
				// ʵ���ַ���
				StringBuffer buffer = new StringBuffer();
				// �����ַ���
				char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
						'A', 'B', 'C', 'D', 'E', 'F' };
				// ������ת���ɶ���������
				byte[] bytes = password.getBytes();
				// ʹ��md5�������?
				MessageDigest md = MessageDigest.getInstance("MD5");
				// ����
				byte[] targ = md.digest(bytes);
				for (byte b : targ) {
					buffer.append(chars[(b >> 4) & 0x0F]);
					buffer.append(chars[b & 0x0F]);
				}
				return buffer.toString();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}
		
		
		
		////////////////////////一些属性类////////////////////////////
		
		public static class AccessToken{
			public String access_token;//接口调用凭证
			public String expires_in;//access_token接口调用凭证超时时间，单位（秒）
			public String refresh_token;//用户刷新access_token
			public String openid;//授权用户唯一标识
			public String scope;//用户授权的作用域，使用逗号（,）分隔
			public String unionid;//当且仅当该移动应用已获得该用户的userinfo授权时，才会出现该字段

		}
		
	
}
