微信小微商户下载平台证书接口(PHP SHA256 with RSA 签名,AEAD_AES_256_GCM解密方法)
/**
* verifyHashSign 校验签名
* @param $data
* @param $signature
* @return int
*/
protected function verifySign($responseHeader, $responseBody)
{
$last_data = $this->newResponseData();
$new_data = json_decode($responseBody, true);
$one = false;
if (empty($last_data)) {
// 没有获取到上一次保存在本地的数据视为第一请求下载证书接口
$serial_no = $this->getNewCertificates($new_data['data']);
$one = true;
} else {
$serial_no = $last_data['serial_no'];
}
// 注 1:微信支付平台证书序列号位于 HTTP 头`Wechatpay-Serial`,验证签名前请先检查序列号是否跟商户所持有的微信支付平台证书序列号一致。(第一次从 1.1.5.中回包字段 serial_no 获取,非第一次时使用上次本地保存的平台证书序列号)
if ($serial_no != $responseHeader['Wechatpay-Serial']) {
if ($one)
$this->clearFile('newResponseData');
return 0;
}
$publicKey = $this->getPublicKey();
if ($publicKey) {
// 用微信支付平台证书公钥(第一次下载平台证书时从 1.1.5.中 “加密后的证书内容”进行解密获得。非第一次时使用上次本地保存的公钥)对“签名串”进行 SHA256 with RSA 签名验证
$data = $this->signatureValidation($responseHeader, $responseBody);
$signature = base64_decode($responseHeader['Wechatpay-Signature']);
$publicKeyResource = openssl_get_publickey($publicKey);
$f = openssl_verify($data, $signature, $publicKeyResource, "SHA256");
openssl_free_key($publicKeyResource);
if ($f == 1 && !empty($last_data)) {
// 获取弃用日期最长证书
return $this->getNewCertificates($new_data['data'], $last_data);
}
return $f;
} else {
return 0;
}
}
/**
* decryptCiphertext AEAD_AES_256_GCM 解密加密后的证书内容得到平台证书的明文
* @param $ciphertext
* @param $ad
* @param $nonce
* @return string
*/
protected function decryptCiphertext($data)
{
$encryptCertificate = $data['encrypt_certificate'];
$ciphertext = base64_decode($encryptCertificate['ciphertext']);
$associated_data = $encryptCertificate['associated_data'];
$nonce = $encryptCertificate['nonce'];
// sodium_crypto_aead_aes256gcm_decrypt >=7.2版本,去里面开启下libsodium扩展就可以,之前版本需要安装libsodium扩展,具体查看(ps.使用这个函数对扩展的版本也有要求哦,扩展版本 >=1.08)
$plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associated_data, $nonce, $this->aes_key);
$this->savePublicKey($plaintext);
$this->newResponseData($data);
return true;
}