package com.kmall.common.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author Scott Chen
 * @since 1.0
 * 2018-03-10
 */
public class MD5Sign {

    private final static Logger logger = LoggerFactory.getLogger(MD5Sign.class);

    private static String INPUT_CHARSET_UTF8 = "UTF-8";

    /**
     * Map按Key排序
     * @param params
     * @return
     */
    public static Map<String, Object> sortMapByKey(Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return null;
        }

        Map<String, Object> sortMap = new TreeMap<String, Object>(
                (x, y) -> x.compareTo(y)
        );

        sortMap.putAll(params);
        return sortMap;
    }

    /**
     * Map 的Key和Value连接
     * @param params
     * @return
     */
    public static String buildParamsStr(Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry entry : params.entrySet()) {
            sb.append(String.valueOf(entry.getKey()) + String.valueOf(entry.getValue()));
        }
        return sb.toString();
    }

    /**
     * 请求参数前添加密钥
     * @param text
     * @param secretKey
     * @return
     */
    public static String insertSecretKey(String text, String secretKey) {
        return new StringBuffer(text).insert(0, secretKey).toString();
    }

    /**
     * 签名
     * @param params 请求参数
     * @param secretKey 密钥
     * @return
     */
    public static String sign(Map<String, Object> params, String secretKey) {
        String paramsStr = insertSecretKey(buildParamsStr(sortMapByKey(params)), secretKey);
        String signature = DigestUtils.md5Hex(getContentBytes(paramsStr, INPUT_CHARSET_UTF8));
        logger.debug("加签: {}", signature);
        return signature;
    }

    /**
     * 验证签名
     * @param signature 签名
     * @param params 请求参数
     * @param secretKey 密钥
     * @return
     */
    public static boolean verify(String signature, Map<String, Object> params, String secretKey) {
        String paramsStr = insertSecretKey(buildParamsStr(sortMapByKey(params)), secretKey);
        String calculateSign = DigestUtils.md5Hex(getContentBytes(paramsStr, INPUT_CHARSET_UTF8));
        boolean verify =  calculateSign.equals(signature) ? true : false;
        logger.debug("系统生成的签名：:{}",calculateSign);
        logger.debug("验签: {}", signature);
        logger.debug("验签结果: {}", verify);
        return verify;
    }


    /**
     * @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("M" +
                    "" +
                    "" +
                    "" +
                    "" +
                    "D5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }



    public static void main(String[] args) {
        Map map = new HashMap();
        //测试环境秘钥
        String data = "{\"idCard\":\"430527199312244222\",\"name\":\"黄亚琴\",\"videoBase64\":\"111\",\"livenessType\":\"SILENT\",\"merchId\":\"mhbs990053989883052032\",\"merchName\":\"中网科技\",\"platSn\":\"mhpt990060576152485888\"}";
        map.put("data", data);
        map.put("timestamp", "1574240977");
        map.put("merchId", "mhbs990053989883052032");

        String si = sign(map, "IxyIvP0sJqlUZinx");

        verify(si, map, "IxyIvP0sJqlUZinx");
    }

}
