admin 管理员组

文章数量: 1184232

1、微信文档

  • 下载平台证书
https://pay.weixin.qq/doc/v3/merchant/4012551764

2、接口说明

接口的频率限制: 单个商户号1000 次/s

  • 支持商户
    【普通商户】
  • 请求方式
    【GET】/v3/certificates
  • 请求域名
    【主域名】https://api.mch.weixin.qq

3、代码实现

  • 引入依赖
<!-- 微信支付 V3 -->
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-java</artifactId>
    <version>0.2.15</version>
</dependency>
  • 下载证书
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.http.*;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;

@Slf4j
public class WxPayUtils {

    /**
     * 下载证书
     */
    public void downLoadCertificates() {
        OkHttpClient okHttpClient = new OkHttpClient();
        HttpClient httpClient = new DefaultHttpClientBuilder()
                .config(rsaAutoCertificateConfig())
                .okHttpClient(okHttpClient)
                .build();
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        HttpRequest executeSendGetHttpRequest = new HttpRequest.Builder()
                .httpMethod(HttpMethod.GET)
                .url("https://api.mch.weixin.qq/v3/certificates")
                .headers(headers)
                .build();
        try {
			HttpResponse<JSONObject> execute = httpClient.execute(executeSendGetHttpRequest, JSONObject.class);
            JSONObject responseBody = execute.getServiceResponse();
            log.info("下载平台证书返回:{}", responseBody.toString());
        } catch (Exception e) {
            log.error("下载平台证书异常", e);
        }
    }

    /**
     * API安全加密配置
     */
    private RSAAutoCertificateConfig rsaAutoCertificateConfig() {
        return new RSAAutoCertificateConfig.Builder()
                // 商户号
                .merchantId("xxxxxxxxxxx")
                // 商户API证书私钥的存放路径
                .privateKeyFromPath("v3/apiclient_key.pem")
                // 商户API证书序列号
                .merchantSerialNumber("xxxxxxxxxxx")
                // APIv3密钥
                .apiV3Key("xxxxxxxxxxx")
                .build();
    }
}

得到数据

{
    "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… "
            }
        }
    ]
}
  • 解密工具
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class WXTransferAesUtil {
    
    static final int KEY_LENGTH_BYTE = 32;
    static final int TAG_LENGTH_BIT = 128;
    private final byte[] aesKey;

    /**
     * @param key ApiV3Key
     */
    public WXTransferAesUtil(byte[] key) {
        if (key.length != KEY_LENGTH_BYTE) {
            throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
        }
        this.aesKey = key;
    }

    /**
     * AES 解密
     *
     * @param associatedData 附加数据
     * @param nonce          随机串
     * @param ciphertext     数据密文
     */
    public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData);
            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (GeneralSecurityException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static void main(String[] args) {
        String associatedData = "certificate";
        String nonce = "61f9c719728a";
        String ciphertext = "sRvt… ";
        WXTransferAesUtil WXTransferAesUtil = new WXTransferAesUtil("APIv3密钥".getBytes());
        String s = WXTransferAesUtil.decryptToString(associatedData.getBytes(), nonce.getBytes(), ciphertext);
        System.out.println(s);
    }
}

就可以解密出平台证书的明文了,装进 platform_cert.pem 文件里面,以后就可以直接使用了

-----BEGIN CERTIFICATE-----
MIIExxxxxXDkQ==
-----END CERTIFICATE-----

如您在阅读中发现不足,欢迎留言!!!

本文标签: 证书 平台