微信支付V3获取平台证书并解密平台证书详细流程 您所在的位置:网站首页 为什么微信支付变成无效 微信支付V3获取平台证书并解密平台证书详细流程

微信支付V3获取平台证书并解密平台证书详细流程

2024-07-07 13:33| 来源: 网络整理| 查看: 265

公司要搞服务号商户卷功能,所以用到了创建商户号接口,有很多数据需要平台证书单独加密,并且图片上传接口返回数据也需要平台证书验签。

   就搞了一下,现在说一下具体细节:

     1:直接点进 敏感信息加密说明

 2 看到微信说加密需要 平台证书

 这里你要搞清楚:商户号证书  和  平台证书不是一个东西,

 商户号证书:是服务商下载的证书

平台证书:微信支付证书

3:现在就去下载微信平台证书,请求接口方式下载

 

 不废话了,直接上获取平台证书代码:

   

//获取 获取平台证书列表 测试成功 public static void main(String[] args) throws Exception { //时间戳 long timestamp = System.currentTimeMillis() / 1000; //随机字符串(用UUID去掉-就行) String nonce = IdUtil.fastSimpleUUID().toUpperCase(); String body = ""; //拼接要签名的字符串 PrivateKey privateKey = PayKit.getPrivateKey("这里填商户平台私钥证书"); //拼接要签名的字符串 String orgSignText = "GET\n" + "/v3/certificates\n" + timestamp + "\n" + nonce + "\n" + body + "\n"; // 生成签名 String sign = RsaKit.encryptByPrivateKey(orgSignText, privateKey); //要放在HttpHeader中的auth信息 // 获取商户证书序列号 这里填写公钥路径 也就是apiclient_cert.pem这个文件的路径 //证书序列号 X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream("填你的apiclient_cert.pem")); String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); String auth = "WECHATPAY2-SHA256-RSA2048 " + "mchid=\"商户号\",nonce_str=\"" + nonce + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + serialNo + "\",signature=\"" + sign + "\""; String url = "https://api.mch.weixin.qq.com/v3/certificates"; HashMap tmap = new HashMap(); tmap.put("Authorization",auth);//tmap.put("token","tonken值"); tmap.put("Accept","application/json"); tmap.put("User-Agent","https://zh.wikipedia.org/wiki/User_agent"); String vmsg= httpGet(url,tmap);//获取请求的返回结果 String rs = HttpClientUtil.sendGetRequest(url, null); System.out.println("获取平台证书"+vmsg); }

下面是具体用到的工具类:

public class RsaKit { /** * 加密算法RSA */ private static final String KEY_ALGORITHM = "RSA"; /** * 私钥签名 * * @param data 需要加密的数据 * @param privateKey 私钥 * @return 加密后的数据 * @throws Exception 异常信息 */ public static String encryptByPrivateKey(String data, PrivateKey privateKey) throws Exception { java.security.Signature signature = java.security.Signature.getInstance("SHA256WithRSA"); signature.initSign(privateKey); signature.update(data.getBytes(StandardCharsets.UTF_8)); byte[] signed = signature.sign(); return StrUtil.str(Base64.encode(signed)); } /** * 从字符串中加载私钥 * 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。 * * @param privateKeyStr 私钥 * @return {@link PrivateKey} * @throws Exception 异常信息 */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { byte[] buffer = Base64.decode(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); } } /** * 公钥验证签名 * * @param data 需要加密的数据 * @param sign 签名 * @param publicKey 公钥 * @return 验证结果 * @throws Exception 异常信息 */ public static boolean checkByPublicKey(String data, String sign, PublicKey publicKey) throws Exception { java.security.Signature signature = java.security.Signature.getInstance("SHA256WithRSA"); signature.initVerify(publicKey); signature.update(data.getBytes(StandardCharsets.UTF_8)); return signature.verify(Base64.decode(sign.getBytes(StandardCharsets.UTF_8))); } } public class PayKit { /** * 获取证书 * * @param inputStream 证书文件 * @return {@link X509Certificate} 获取证书 */ public static X509Certificate getCertificate(InputStream inputStream) { try { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书", e); } } /** * 简化的UUID,去掉了横线,使用性能更好的 ThreadLocalRandom 生成UUID * * @return 简化的 UUID,去掉了横线 */ public static String generateStr() { return IdUtil.fastSimpleUUID(); } /** * 构造签名串 * * @param method {@link RequestMethod} GET,POST,PUT等 * @param url 请求接口 /v3/certificates * @param timestamp 获取发起请求时的系统当前时间戳 * @param nonceStr 随机字符串 * @param body 请求报文主体 * @return 待签名字符串 */ public static String buildSignMessage(String method, String url, String timestamp, String nonceStr, String body) { ArrayList arrayList = new ArrayList(); arrayList.add(method); arrayList.add(url); arrayList.add(String.valueOf(timestamp)); arrayList.add(nonceStr); arrayList.add(body); return buildSignMessage(arrayList); } /** * 构造签名串 * * @param signMessage 待签名的参数 * @return 构造后带待签名串 */ public static String buildSignMessage(ArrayList signMessage) { if (signMessage == null || signMessage.size() = dataLen) { out.write(data, off, dataLen); } else { out.write(data, off, len); } out.flush(); off += len; dataLen -= len; } } public static SSLContext getSSLContext(FileInputStream trustFileInputStream, String trustPasswd, FileInputStream keyFileInputStream, String keyPasswd) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); KeyStore trustKeyStore = KeyStore.getInstance("JKS"); trustKeyStore.load(trustFileInputStream, str2CharArray(trustPasswd)); tmf.init(trustKeyStore); char[] kp = str2CharArray(keyPasswd); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(keyFileInputStream, kp); kmf.init(ks, kp); SecureRandom rand = new SecureRandom(); SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand); return ctx; } public static Certificate getCertificate(File cafile) throws CertificateException, IOException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(cafile); Certificate cert = cf.generateCertificate(in); in.close(); return cert; } public static char[] str2CharArray(String str) { if (str == null) { return null; } return str.toCharArray(); } public static void storeCACert(Certificate cert, String alias, String password, OutputStream out) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); ks.setCertificateEntry(alias, cert); ks.store(out, str2CharArray(password)); } public static InputStream String2Inputstream(String str) { return new ByteArrayInputStream(str.getBytes()); } }

返回结果:

这就获取到了微信平台证书,但是要注意,这只是获取到了平台证书加密密文 还要进行解密,直接用微信支付文档里面的解密代码就可以。

 

然后解析出真正的微信证书。

注意这里解密有个问题:解密出现Illegal key size错误

   解决:微信支付V3支付通知JAVA解密出现Illegal key size错误 | 微信开放社区

可以用微信证书去加/解密指定内容:

 好了,结束,希望对你有所帮助!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有