|
@@ -0,0 +1,119 @@
|
|
|
+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();
|
|
|
+}
|
|
|
+}
|