package com.pcloud.common.utils.string;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;

/**
 * @描述：公用函数类(生成签名数据).
 * @作者：DiSeng.H
 * @创建时间：2016年3月10日,上午11:48:08
 * @版本：1.0
 */
public class Sign {

	// 字符编码格式 目前支持 gbk 或 utf-8
		public static String input_charset = "utf-8";

		// 签名方式
		public static String sign_type = "MD5";

		/**
		 * 生成要请求给支付的秘钥
		 * 
		 * @param sParaTemp
		 *            请求前的参数数组
		 * @return String
		 */
		public static String buildRequestPara(Map<String, String> sParaTemp, String key) {
			// 除去数组中的空值和签名参数
			Map<String, String> sPara = Sign.paraFilter(sParaTemp);
			// 生成签名结果
			String mysign = buildRequestMysign(sPara, key);
			return mysign;
		}

		/**
		 * 生成签名结果
		 * 
		 * @param sPara
		 *            要签名的数组
		 * @return 签名结果字符串
		 */
		public static String buildRequestMysign(Map<String, String> sPara, String key) {
			String prestr = Sign.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
			String mysign = "";
			if (Sign.sign_type.equals("MD5")) {
				mysign = Sign.sign(prestr, key, Sign.input_charset);
			}
			return mysign;
		}

		/**
		 * 除去数组中的空值和签名参数
		 * 
		 * @param sArray
		 *            签名参数组
		 * @return 去掉空值与签名参数后的新签名参数组
		 */
		public static Map<String, String> paraFilter(Map<String, String> sArray) {
			Map<String, String> result = new LinkedHashMap<String, String>();
			if (sArray == null || sArray.size() <= 0) {
				return result;
			}
			for (String key : sArray.keySet()) {
				String value = sArray.get(key);
				if (value == null || "".equals(value)) {
					continue;
				}
				result.put(key, value);
			}
			return result;
		}

		/**
		 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
		 * 
		 * @param params
		 *            需要排序并参与字符拼接的参数组
		 * @return 拼接后字符串
		 */
		public static String createLinkString(Map<String, String> params) {
			List<String> keys = new ArrayList<String>(params.keySet());
			Collections.sort(keys);
			StringBuffer prestr = new StringBuffer("");
			for (int i = 0; i < keys.size(); i++) {
				String key = keys.get(i);
				String value = params.get(key);

				if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
					prestr.append(key)//
							.append("=")//
							.append(value);
				} else {
					prestr.append(key)//
							.append("=")//
							.append(value)//
							.append("&");
				}
			}
			return prestr.toString();
		}

		/**
		 * 签名字符串
		 * 
		 * @param text
		 *            需要签名的字符串
		 * @param key
		 *            密钥
		 * @param input_charset
		 *            编码格式
		 * @return 签名结果
		 */
		public static String sign(String text, String key, String input_charset) {
			text = text + key;
			return DigestUtils.md5Hex(getContentBytes(text, input_charset));
		}

		/**
		 * @param content
		 * @param charset
		 * @return
		 * @throws SignatureException
		 * @throws UnsupportedEncodingException
		 */
		private static byte[] getContentBytes(String content, String charset) {
			if (charset == null || "".equals(charset)) {
				return content.getBytes();
			}
			try {
				return content.getBytes(charset);
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
			}
		}
}
