package org.jeecg.modules.pay.paytest;


import me.zhyd.oauth.utils.UuidUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.pay.config.WechatConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.List;
import java.util.Map;

/**
 * @date 2020-03-18 11:02
 * @description 签名相关
 */
public class SignUtils {
private static final Logger logger = LoggerFactory.getLogger(SignUtils.class);

    /**
     * 签名生成
     * @param method 请求方法 如POST
     * @param urlSuffix 请求地址后缀 如/v3/certificates
     * @param mchId 电商平台商户号
     * @param serialNo 电商平台商户API证书序列号
     * @param body 请求请求报文主体，如果没有，就传空字符串
     * @param mchPrivateKeyPath 电商平台商户API私钥
     * @return
     */
    public static String authorization(String method,String urlSuffix,String mchId,String serialNo,String body,
                                       String mchPrivateKeyPath) {
    try {
        //商户私钥
        String mchPrivateKey = WechatConstants.WECHAT_MCH_PRIVATE_KEY;
        //时间戳
        String timestamp = Long.toString(System.currentTimeMillis()/1000);
        //随机数
        String nonceStr = UuidUtils.getUUID();

        //拼签名串
        StringBuilder sb = signMessage(method,urlSuffix,timestamp,nonceStr,body);

        logger.info("sign original string:{}",sb.toString());

        //计算签名
        String sign = new String(Base64.encodeBase64(v3signRSA(sb.toString(),mchPrivateKey)));

        logger.info("sign result:{}",sign);

        //拼装http头的Authorization内容
        String authorization ="WECHATPAY2-SHA256-RSA2048 mchid=\""+mchId+"\",nonce_str=\""+nonceStr+"\",signature=\""+sign+"\",timestamp=\""+timestamp+"\",serial_no=\""+serialNo+"\"";

        logger.info("authorization result:{}",authorization);

        return authorization;

    } catch (Exception e) {
        logger.error("authorization Exception result:{}",e);
        e.printStackTrace();
        return null;
    }
}

/**
* Authorization 签名串
* @param method
* @param urlSuffix
* @param timestamp
* @param nonceStr
* @param body
* @return
*/
private static StringBuilder signMessage(String method,String urlSuffix,String timestamp,String nonceStr,String body) {
return new StringBuilder()
        .append(method)
        .append("\n")
        .append(urlSuffix)
        .append("\n")
        .append(timestamp)
        .append("\n")
        .append(nonceStr)
        .append("\n")
        .append(body)
        .append("\n");
}

/**
* 私钥签名
* @param data 需要加密的数据
* @param mchPriKey
* @return
* @throws Exception
*/
public static byte[] v3signRSA(String data, String mchPriKey) throws Exception {
  //签名的类型
  Signature sign = Signature.getInstance("SHA256withRSA");
  //读取商户私钥,该方法传入商户私钥证书的内容即可
  byte[] keyBytes = Base64.decodeBase64(mchPriKey);
  PKCS8EncodedKeySpec keySpec =new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  PrivateKey priKey = keyFactory.generatePrivate(keySpec);
  sign.initSign(priKey);
  sign.update(data.getBytes(StandardCharsets.UTF_8));
  return sign.sign();
}
}