packages/docs/docs/guide/wxpay/api-v3.md
相较于的之前微信支付API,主要区别是:
更多证书和签名的详细内容请参官方文档 WeChatPay-API-v3
API密钥的详细内容请参见:API证书及密钥
请在商户平台下载证书。具体操作请参见:如何获取API证书
X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream("apiclient_cert.pem 证书路径"));
String serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
:::tip 如何验证序列号
// 构建签名参数
String buildSignMessage = PayKit.buildSignMessage(method, urlSuffix, timestamp, nonceStr, body);
// 构建签名参数,也可通过列表传入待签名的参数
String buildSignMessage = PayKit.buildSignMessage(ArrayList<String> signMessage)
// 创建签名
String signature = PayKit.createSign(buildSignMessage,keyPath);
// 创建签名,整合版
String signature = PayKit.createSign(ArrayList<String> signMessage, String keyPath)
String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, keyPath, body, nonceStr, timestamp, authType);
// 或者
String authorization = WxPayKit.buildAuthorization(method, urlSuffix, mchId, serialNo, keyPath, body);
参数说明
获取平台证书列表为例
String keyPath = "/Users/Javen/cert/apiclient_key.pem";// 私钥证书
String mchId = "商户号";
String serialNo = "公钥证书序列号";
String body = ""; // 请求报文主体,没有查询参数。
String platformCertPath = "";//微信平台证书 验证签名时需要使用
@Test
public void v3Get() {
// 获取平台证书列表
try {
Map<String, Object> result = WxPayApi.v3Execution(
RequestMethod.GET,
WxDomain.CHINA.toString(),
WxApiType.GET_CERTIFICATES.toString(),
mchId,
serialNo,
keyPath,
body
);
String serialNumber = MapUtil.getStr(result, "serialNumber");
String body = MapUtil.getStr(result, "body");
int status = MapUtil.getInt(result, "status");
System.out.println("serialNumber:" + serialNumber);
System.out.println("status:" + status);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(result, platformCertPath);
System.out.println("verifySignature:" + verifySignature + "\nbody:" + body);
} catch (Exception e) {
e.printStackTrace();
}
}
返回数据 body 格式
{
"data": [
{
"effective_time": "XXX",
"encrypt_certificate": {
"algorithm": "AEAD_AES_256_GCM",
"associated_data": "certificate",
"ciphertext": "XXX",
"nonce": "XXX"
},
"expire_time": "XXX",
"serial_no": "XXX"
}
]
}
:::warning 如果接口包含感信息时,必须传入 平台公钥证书 的序列号 :::
@RequestMapping("/sensitive")
@ResponseBody
public String sensitive() {
// 带有敏感信息接口
try {
String body = "处理请求参数";
Map<String, Object> result = WxPayApi.v3Execution(
RequestMethod.POST,
WxDomain.CHINA.toString(),
WxApiType.APPLY_4_SUB.toString(),
wxPayV3Bean.getMchId(),
getSerialNumber(),
getPlatSerialNumber(),
wxPayV3Bean.getKeyPath(),
body
);
System.out.println(result);
return JSONUtil.toJsonStr(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
根据证书序列号查询对应微信平台的证书来验证签名结果
WxPayKit.verifySignature(Map<String, Object> map, String certPath);
WxPayKit.verifySignature(Map<String, Object> map, InputStream certInputStream)
WxPayKit.verifySignature(String signature, String body, String nonce, String timestamp, String publicKey)
WxPayKit.verifySignature(String signature, String body, String nonce, String timestamp, PublicKey publicKey)
WxPayKit.verifySignature(String signature, String body, String nonce, String timestamp, InputStream certInputStream)
:::tip
证书报文解密为例
String associatedData = "";
String nonce = "";
String ciphertext = "";
String saveCertPath = "/Users/Javen/cert/platform_cert.pem";
AesUtil aesUtil = new AesUtil(apiKey3.getBytes(StandardCharsets.UTF_8));
// 平台证书密文解密
String publicKey = aesUtil.decryptToString(
associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
ciphertext
);
System.out.println("平台证书公钥明文:" + publicKey);
// 保存证书
FileWriter writer = new FileWriter(saveCertPath);
writer.write(publicKey);
// 获取平台证书序列号
X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
System.out.println(certificate.getSerialNumber().toString(16).toUpperCase());
// 敏感信息加密
X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayV3Bean.getPlatformCertPath()));
String encrypt = PayKit.rsaEncryptOAEP("IJPay", certificate);
System.out.println(encrypt);
// 敏感信息解密
String encryptStr = "";
PrivateKey privateKey = PayKit.getPrivateKey(wxPayV3Bean.getKeyPath());
String decrypt = PayKit.rsaDecryptOAEP(encryptStr, privateKey);
System.out.println(decrypt);