package com.hfkj.channel.tianque.utils;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.tianque.config.TianQueConfig;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * RSA签名验签类
 */
public class RSASignature {

    /**
     * 签名算法
     */
    public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    
	/**
	 * 针对参数进行排序拼装
	 * @param requestParam
	 * @return
	 */
	public static String getContent(Map<String, Object> requestParam) {
		Map<String, Object> sortedParams = new TreeMap<String, Object>();
		if ((requestParam != null) && (requestParam.size() > 0)) {
			sortedParams.putAll(requestParam);
		}
		StringBuffer content = new StringBuffer();
		List<String> keys = new ArrayList<String>(sortedParams.keySet());
		Collections.sort(keys);
		int index = 0;
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			Object value = sortedParams.get(key);
			if (key!=null &&!"".equals(key)&& value != null) {
				content.append((index == 0 ? "" : "&") + key + "=" + value);
				index++;
			}
		}
		return content.toString();
	}

    /**
     * rsa 签名
     * @param content 待签名内容
     * @param privateKey  私钥
     * @return
     */
    public static byte[] sign(String content, String privateKey) {
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decryptBASE64(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            signature.initSign(priKey);
            signature.update(content.getBytes("UTF-8"));
            byte[] signed = signature.sign();
            return signed;
        } catch (Exception e) {
        	e.printStackTrace();
            return null;
        }
    }

    /**
     * RSA验签名检查
     * @param content 待签名数据
     * @param sign 签名值
     * @param publicKey 分配给开发商公钥
     * @return 布尔值
     */
    public static boolean doCheck(String content, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = decryptBASE64(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));


            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.getBytes("UTF-8"));

            boolean bverify = signature.verify(decryptBASE64(sign));
            return bverify;

        } catch (Exception e) {
        	e.printStackTrace();
            return false;
        }
    }

    public static String encryptBASE64(byte[] key) {
        String base64encodedString = Base64.getEncoder().encodeToString(key);
        return base64encodedString.replaceAll("[\\s*\t\n\r]", "");
    }
    public static byte[] decryptBASE64(String key) {
        byte[] base64decodedBytes = Base64.getDecoder().decode(key.replaceAll("[\\s*\t\n\r]", ""));
        return base64decodedBytes;
    }


    public static void main(String[] args) {
        String paramStr = "{\n" +
                "\t\"orgId\": \"00205462\",\n" +
                "\t\"reqData\": {\n" +
                "\t\t\"cprRegAddr\": \"贵州省贵阳市观山湖区观山西路与诚信南路交叉市科技馆主楼第一层1号\",\n" +
                "\t\t\"businessLicStt\": \"20210617\",\n" +
                "\t\t\"operationalType\": \"01\",\n" +
                "\t\t\"settlePersonIdcardOpposite\": \"deb136972d01478ca322508edcb5b607\",\n" +
                "\t\t\"letterOfAuthPic\": \"9d6c22c4449746c0a97b0f599bfb449f\",\n" +
                "\t\t\"insideScenePic\": \"8661acbd30504501bf219ac385531e1a\",\n" +
                "\t\t\"businessLicEnt\": \"29991231\",\n" +
                "\t\t\"identityNo\": \"511303200001121959\",\n" +
                "\t\t\"licenseMatch\": \"00\",\n" +
                "\t\t\"haveLicenseNo\": \"02\",\n" +
                "\t\t\"legalPersonidOppositePic\": \"ce26a46dbf5c43f98cfcf0cf548555ea\",\n" +
                "\t\t\"cprRegNmCn\": \"贵州拾贰季企业管理咨询有限公司\",\n" +
                "\t\t\"mccCd\": \"5812\",\n" +
                "\t\t\"regDistCd\": \"520111000000\",\n" +
                "\t\t\"identityName\": \"胡锐\",\n" +
                "\t\t\"regCityCd\": \"520100000000\",\n" +
                "\t\t\"mecTypeFlag\": \"00\",\n" +
                "\t\t\"licensePic\": \"43250a93a3fe4c9e80a172d208a2b5d9\",\n" +
                "\t\t\"legalPersonLicEnt\": \"20290823\",\n" +
                "\t\t\"qrcodeList\": [{\n" +
                "\t\t\t\"rateType\": \"061\",\n" +
                "\t\t\t\"rate\": \"0.30\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"01\",\n" +
                "\t\t\t\"rate\": \"0.30\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"06\",\n" +
                "\t\t\t\"rate\": \"0.30\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"02\",\n" +
                "\t\t\t\"rate\": \"0.30\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"07\",\n" +
                "\t\t\t\"rate\": \"0.54\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"071\",\n" +
                "\t\t\t\"rate\": \"0.45\"\n" +
                "\t\t}, {\n" +
                "\t\t\t\"rateType\": \"072\",\n" +
                "\t\t\t\"rate\": \"0.45\"\n" +
                "\t\t}],\n" +
                "\t\t\"legalPersonidPositivePic\": \"4afe2a2d2763465c9f792f97668ee170\",\n" +
                "\t\t\"regProvCd\": \"520000000000\",\n" +
                "\t\t\"legalPersonLicStt\": \"20190823\",\n" +
                "\t\t\"accountLicEnt\": \"20380706\",\n" +
                "\t\t\"storePic\": \"7c814e656ff04ad7b2814007d7de18a6\",\n" +
                "\t\t\"identityTyp\": \"00\",\n" +
                "\t\t\"actNm\": \"尹永喜\",\n" +
                "\t\t\"mecDisNm\": \"测试商户\",\n" +
                "\t\t\"mblNo\": \"15583658692\",\n" +
                "\t\t\"actTyp\": \"01\",\n" +
                "\t\t\"actNo\": \"6210813520003655795\",\n" +
                "\t\t\"lbnkNo\": \"102701007053\",\n" +
                "\t\t\"registCode\": \"91520115MAALPPMM90\",\n" +
                "\t\t\"accountLicStt\": \"20180706\",\n" +
                "\t\t\"settlePersonIdcardPositive\": \"f999d38a95ee4115b9d82c1d82365dd7\",\n" +
                "\t\t\"csTelNo\": \"15583658692\",\n" +
                "\t\t\"bankCardPositivePic\": \"976899f062904c82b52a7161574b0b8b\",\n" +
                "\t\t\"stmManIdNo\": \"150221198809057119\",\n" +
                "\t\t\"actNoType\": \"00\"\n" +
                "\t},\n" +
                "\t\"reqId\": \"202392942026175103\",\n" +
                "\t\"signType\": \"RSA\",\n" +
                "\t\"timestamp\": \"20230825134026\",\n" +
                "\t\"version\": \"1.0\"\n" +
                "}";
        System.out.println(RSASignature.encryptBASE64(RSASignature.sign(RSASignature.getContent(JSONObject.parseObject(paramStr, Map.class)), TianQueConfig.priKey)));
    }

}
