package com.ematou.wxservice.common.utils;

import com.ematou.wxservice.common.constant.WeChatConstant;
import org.springframework.util.StringUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 根据服务器配置的令牌校验签名
 *
 * @author lhm
 * @version 1.0
 * 2021-05-11 11:49
 */
public class SignUtil {
    private static final String token = WeChatConstant.TOKEN;// 服务器配置中的令牌

    /**
     * 校验签名
     *
     * @param signature 签名
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @return true 成功，false 失败
     */
    public static boolean checkSignature(String signature, String timestamp, String nonce) {

        String checktext = null;
        if (null != signature) {
            // 对Token，timestamp nonce 按字典排序
            String[] paramArr = new String[]{token, timestamp, nonce};
            Arrays.sort(paramArr);
            // 将排序后的结果拼成一个字符串
            String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
            try {
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                // 对接后的字符串进行sha1加密
                byte[] digest = md.digest(content.toString().getBytes());
                checktext = byteToStr(digest);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        // 将加密后的字符串与signature进行对比
        return checktext != null && checktext.matches(signature.toUpperCase());
    }

    /**
     * jsapi签名
     *
     * @param ticket    ticket
     * @param url       url
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @return true 成功，false 失败
     */
    public static String jsApiSign(String ticket, String url, String timestamp, String nonce) {
        String sign = "";
        SortedMap<String, Object> param = new TreeMap<>();
        param.put("jsapi_ticket", ticket);
        param.put("url", url);
        param.put("timestamp", timestamp);
        param.put("noncestr", nonce);
        String signStr = buildSignStr(param);
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(signStr.getBytes("UTF-8"));
            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }

    private static String buildSignStr(SortedMap<String, Object> params) {
        String signStr = "";
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            if (!StringUtils.isEmpty(signStr)) {
                signStr += "&";
            }
            signStr += entry.getKey() + "=" + entry.getValue();
        }
        return signStr;
    }

    /**
     * 将字节数组转化为16进制字符串
     *
     * @return 字符串
     */
    private static String byteToStr(byte[] byteArrays) {
        StringBuilder str = new StringBuilder();
        for (byte byteArray : byteArrays) {
            str.append(byteToHexStr(byteArray));
        }
        return str.toString();
    }

    /**
     * 将字节转化为十六进制字符串
     *
     * @param myByte 字节
     * @return 字符串
     */
    private static String byteToHexStr(byte myByte) {

        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(myByte >>> 4) & 0X0F];
        tempArr[1] = Digit[myByte & 0x0F];
        return new String(tempArr);
    }
}
