package com.jeecg.p3.commonweixin.util;

import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import org.jeecgframework.p3.core.util.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jeecg.p3.commonweixin.exception.CommonweixinException;





/**
 * 加签、验签工具.
 *
 * @author zhoujf
 */
public abstract class SignatureUtil {
    private static final Logger LOG = LoggerFactory.getLogger(SignatureUtil.class);
    
    /**
     * 加签,MD5.
     * @param paramMap 参数Map,不包含商户秘钥且顺序确定
     * @param key  商户秘钥
     * @return  签名串
     */
    public static String sign(Map<String, String> paramMap, String key) {
        if(key == null){
            throw new CommonweixinException("key不能为空");
        }
        String sign = createSign(paramMap,key);
        return sign;
    }
    
    /**
	 * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
	 */
	private static String createSign(Map<String, String> paramMap, String key) {
		StringBuffer sb = new StringBuffer();
		SortedMap<String,String> sort=new TreeMap<String,String>(paramMap);  
		Set<Entry<String, String>> es = sort.entrySet();
		Iterator<Entry<String, String>> it = es.iterator();
		while (it.hasNext()) {
			@SuppressWarnings("rawtypes")
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v)&& !"null".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + key);
		LOG.info("HMAC source:{}", new Object[] { sb.toString() } );
		String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
		LOG.info("HMAC:{}", new Object[] { sign } );
		return sign;
	}

    /**
     * 验签, 仅支持MD5.
     * @param paramMap 参数Map,不包含商户秘钥且顺序确定
     * @param key  商户秘钥
     * @param sign     签名串
     * @return         验签结果
     */
    public static boolean checkSign(Map<String, String> paramMap, String key, String sign) {
        if(key == null){
            throw new CommonweixinException("key不能为空");
        }
        if(sign == null){
            throw new CommonweixinException("需要验签的字符为空");
        }

        return sign.equals(sign(paramMap,key));
    }
    
    
    /**
     * 通过request获取签名Map
     * @param request
     * @return
     */
    public static Map<String,String> getSignMap(HttpServletRequest request){
		Map<String,String>  paramMap = new HashMap<String, String>();
		Map<String, String[]> map = request.getParameterMap();
		Set<Entry<String, String[]>> es = map.entrySet();
		Iterator<Entry<String, String[]>> it = es.iterator();
		while (it.hasNext()) {
			@SuppressWarnings("rawtypes")
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			Object ov =  entry.getValue();
			String v="";
			if(ov instanceof String[]){
				String[] value=(String[])ov;
				v= value[0];
            }else{
                v=ov.toString();
            }
			paramMap.put(k, v);
		}
		return paramMap;
	}
    
    /**
     * 通过request获取签名Map
     * @param request
     * @return
     */
    public static Map<String,String> getSignMap(String url){
    	Map<String,String>  paramMap = new HashMap<String, String>();
    	url = url.substring(url.indexOf("?")+1);
    	String[] params = url.split("&");
    	for(int i=0;i<params.length;i++){
    		String param = params[i];
    		if(param.indexOf("=")!=-1){
    			String[] values = param.split("=");
    			if(values!=null&&values.length==2){
    				//update----begin---author:scott----date:20160115----for:昵称转码,签名问题处理----
    				if ("nickname".equals(values[0])) {
    					paramMap.put(values[0],URLDecoder.decode(values[1]));
					}else{
						paramMap.put(values[0], values[1]);
					}
    				//update----begin---author:scott----date:20160115----for:昵称转码,签名问题处理----
    			}
    		}
    	}
		return paramMap;
	}
    
    public static void main(String[] args) {
    	String url = "http://www.saphao.com:9999/P3-Web/commonxrs/toIndex.do?actId=402880ee51334a520151334c3eaf0001&openid=oR0jFt_DTsAUJebWqGeq3A1VWfRw&nickname=JEFF&subscribe=1&jwid=&sign=F5E56A64B650A98E67CCCFFF871C7133";
    	Map<String,String> t = getSignMap(url);
    	for(Map.Entry<String, String> entry:t.entrySet()){    
    	     System.out.println(entry.getKey()+"--->"+entry.getValue());    
    	}   
	}
}