电商收付通系列②,获取微信支付平台证书

简介: 微信支付平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行验签。注意,这里的证书区别于商户API证书,商户API证书是直接从商户后台下载查看的,而微信支付平台证书是通过电商收付通的证书接口获取的。

1、介绍

微信支付平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行验签。注意,这里的证书区别于商户API证书,商户API证书是直接从商户后台下载查看的,而微信支付平台证书是通过电商收付通的证书接口获取的。

2、作用

这个证书有什么用?我们需要获取到这个证书相关的序列号和公钥,后续请求一系列接口时需要将微信支付平台证书序列号放在请求头里,而公钥是为了验证应答或回调的签名,以确保应答或回调是由微信支付发送。

image.png

3、获取微信支付平台证书

注意:不同的商户,对应的微信支付平台证书是不一样的,平台证书会周期性更换。建议商户定时通过API下载新的证书,不要依赖人工更换证书。微信支付的平台证书序列号位于HTTP头Wechatpay-Serial。验证签名前,请商户先检查序列号是否跟商户当前所持有的微信支付平台证书的序列号一致。如果不一致,请重新获取证书。否则,签名的私钥和证书不匹配,将无法成功验证签名。双手奉上获取微信支付。

 * @description
 */
public class Certificate {

private static final Logger logger = LoggerFactory.getLogger(Certificate.class);
/**
     * 获取微信支付平台证书
     * @param merchantId
     * @param timeout
     * @param serialNo
     * @param mchPrivateKeyPath
     * @param APIv3Key
     * @param savePath
     * @return
     */
public static List<X509Certificate> getCertByAPI(String merchantId, int timeout, String serialNo, String mchPrivateKeyPath,String wechatPubKeyPath,String APIv3Key,String savePath) {
    String result = "";
    //创建http请求
    HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com
/v3/certificates");
    httpGet.addHeader("Content-Type", "application/json");
    httpGet.addHeader("Accept", "application/json");

    String authorization = SignUtils.authorization("GET", "/v3/certificates", merchantId, serialNo, "", mchPrivateKeyPath);

    //设置认证信息
    httpGet.setHeader("Authorization", authorization);

    //设置请求器配置:如超时限制等
    RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();
    httpGet.setConfig(config);
    List<X509Certificate> x509Certs = new ArrayList<X509Certificate>();
    try {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity httpEntity = response.getEntity();
        result = EntityUtils.toString(httpEntity, "UTF-8");
        if(statusCode == 200){
            logger.info("下载平台证书返回结果:"+result);
            Header[] timestampHeader = response.getHeaders("Wechatpay-Timestamp");
                Header[] nonceHeader = response.getHeaders("Wechatpay-Nonce");
                Header[] signatureHeader = response.getHeaders("Wechatpay-Signature");
                if (timestampHeader != null && timestampHeader.length > 0 &&
                        nonceHeader != null && nonceHeader.length > 0 &&
                        signatureHeader != null && signatureHeader.length > 0) {
                    // 验证微信支付返回签名
                    String wTimestamp = timestampHeader[0].getValue();
                    String wNonce = nonceHeader[0].getValue();
                    String wSign = signatureHeader[0].getValue();

                    logger.info("wTimestamp:{},wNonce:{},wSign:{}", wTimestamp, wNonce, wSign);
                    // 拼装待签名串
                    StringBuffer ss = new StringBuffer();
                    ss.append(wTimestamp).append("\n");
                    ss.append(wNonce).append("\n");
                    ss.append(result).append("\n");
                    // 验证签名
                    if (SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(wSign.getBytes()), wechatPubKeyPath)) {
                        List<CertificateItem> certList = new ArrayList<CertificateItem>();
                        JSONObject json = JSONObject.parseObject(result);
                        logger.info("查询结果json字符串转证书List:" + json.get("data"));
                        JSONArray jsonArray = (JSONArray) json.get("data");
                        for (int i = 0; i < jsonArray.size(); i++) {
                            CertificateItem certificateItem = new CertificateItem();
                            EncryptedCertificateItem encryptCertificate = new EncryptedCertificateItem();
                            JSONObject bo = JSONObject.parseObject(jsonArray.get(i).toString());
                            certificateItem.setSerial_no(bo.get("serial_no").toString());
                            certificateItem.setEffective_time(bo.get("effective_time").toString());
                            certificateItem.setExpire_time(bo.get("expire_time").toString());
                            JSONObject encryptBo = JSONObject.parseObject(bo.get("encrypt_certificate").toString());
                            encryptCertificate.setAlgorithm(encryptBo.get("algorithm").toString());
                            encryptCertificate.setNonce(encryptBo.get("nonce").toString());
                            encryptCertificate.setAssociated_data(encryptBo.get("associated_data").toString());
                            encryptCertificate.setCiphertext(encryptBo.get("ciphertext").toString());
                            certificateItem.setEncrypt_certificate(encryptCertificate);
                            certList.add(certificateItem);
                        }
                        logger.info("证书List:" + certList);

                        List<PlainCertificateItem> plainList = decrypt(certList, APIv3Key);
                        if (CollectionUtils.isNotEmpty(plainList)) {
                            logger.info("平台证书开始保存");
                            x509Certs = saveCertificate(plainList, savePath);
                        }
                    }
                }
        }
          response.close();
          httpClient.close(); //throw
          return x509Certs;
      } catch (Exception e) {
          e.printStackTrace();
          logger.error("下载平台证书返回结果:"+e);
      }
      return x509Certs;
  }

image.png

4、结果

1、接口返回的内容是json串

{
  "data": [{
    "serial_no": "5157F09EFDC096DE15EBE81A47057A7232F1B8E1",
      "effective_time ": "2018-06-08T10:34:56+08:00",
      "expire_time ": "2018-12-08T10:34:56+08:00",
      "encrypt_certificate": {
      "algorithm": "AEAD_AES_256_GCM",
      "nonce": "61f9c719728a",
      "associated_data": "certificate",
      "ciphertext": "sRvt… "
      }
  }]
}

2、通过接口下载的微信支付平台证书

image.png

image.png

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

上一篇:电商收付通系列①,对请求进行签名,拼接Authorization

相关文章
|
5月前
|
小程序 Java 关系型数据库
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
|
5月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的校园资讯平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的校园资讯平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)
|
3月前
|
小程序 开发者
第一个微信小程序的初始化过程、小程序微信开发平台的下载、如何注册一个微信小程序的账号
这篇文章介绍了微信小程序的初始化过程,包括如何注册微信小程序账号、下载微信小程序开发者平台,并指导了新建小程序的详细步骤。
第一个微信小程序的初始化过程、小程序微信开发平台的下载、如何注册一个微信小程序的账号
|
4月前
|
安全 API Windows
支付系统13------支付系统的资料在技术库里的在线支付当中,怎样获取微信平台证书那?怎样获取微信平台证书那?第一步打开我们的微信支付平台的文档中心
支付系统13------支付系统的资料在技术库里的在线支付当中,怎样获取微信平台证书那?怎样获取微信平台证书那?第一步打开我们的微信支付平台的文档中心
|
4月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的童装购买平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的童装购买平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)
|
4月前
|
API
支付系统----微信支付24--APlv3介绍,首先我们要引入支付参数,包含商户号,APPID、API秘钥,数字证书,用代码加载到应用程序当中,之后加载商户私钥,商户需要用私钥进行验签,微信平台接收商
支付系统----微信支付24--APlv3介绍,首先我们要引入支付参数,包含商户号,APPID、API秘钥,数字证书,用代码加载到应用程序当中,之后加载商户私钥,商户需要用私钥进行验签,微信平台接收商
|
4月前
|
安全 API 数据安全/隐私保护
支付系统05------微信支付,接入指引----获取密钥和证书,随机密码生成器的工具,
支付系统05------微信支付,接入指引----获取密钥和证书,随机密码生成器的工具,https://suijimimashengcheng.bmcx.com/随机密码生成器的工具
|
5月前
|
小程序 Java 关系型数据库
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
|
5月前
|
Java Linux API
微信API:探究Android平台下Hook技术的比较与应用场景分析
微信API:探究Android平台下Hook技术的比较与应用场景分析
|
5月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的大学生就业平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的大学生就业平台微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)