mirror of
https://gitee.com/zoujingli/WeChatDeveloper.git
synced 2025-04-05 19:41:44 +08:00
修改平台证书机制
#
This commit is contained in:
parent
683eb10ebd
commit
b9c4823486
@ -27,6 +27,13 @@ use WePayV3\Contracts\DecryptAes;
|
||||
*/
|
||||
class Cert extends BasicWePay
|
||||
{
|
||||
|
||||
/**
|
||||
* 自动配置平台证书
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoCert = false;
|
||||
|
||||
/**
|
||||
* 商户平台下载证书
|
||||
* @return void
|
||||
@ -37,13 +44,18 @@ class Cert extends BasicWePay
|
||||
try {
|
||||
$aes = new DecryptAes($this->config['mch_v3_key']);
|
||||
$result = $this->doRequest('GET', '/v3/certificates');
|
||||
$certs = [];
|
||||
foreach ($result['data'] as $vo) {
|
||||
$this->tmpFile($vo['serial_no'], $aes->decryptToString(
|
||||
$certs[$vo['serial_no']] = [
|
||||
'expire' => strtotime($vo['expire_time']),
|
||||
'content' => $aes->decryptToString(
|
||||
$vo['encrypt_certificate']['associated_data'],
|
||||
$vo['encrypt_certificate']['nonce'],
|
||||
$vo['encrypt_certificate']['ciphertext']
|
||||
));
|
||||
)
|
||||
];
|
||||
}
|
||||
$this->tmpFile("{$this->config['mch_id']}_certs", $certs);
|
||||
} catch (\Exception $exception) {
|
||||
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
|
||||
}
|
||||
|
@ -41,6 +41,12 @@ abstract class BasicWePay
|
||||
*/
|
||||
static $cache = [];
|
||||
|
||||
/**
|
||||
* 自动配置平台证书
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoCert = true;
|
||||
|
||||
/**
|
||||
* 配置参数
|
||||
* @var array
|
||||
@ -52,6 +58,8 @@ abstract class BasicWePay
|
||||
'cert_serial' => '', // 商户证书序号,无需配置
|
||||
'cert_public' => '', // 商户公钥内容,需要配置
|
||||
'cert_private' => '', // 商户密钥内容,需要配置
|
||||
'mp_cert_serial' => '', // 平台证书序号,无需配置
|
||||
'mp_cert_content' => '', // 平台证书内容,无需配置
|
||||
];
|
||||
|
||||
/**
|
||||
@ -94,7 +102,6 @@ abstract class BasicWePay
|
||||
$this->config['mch_v3_key'] = $options['mch_v3_key'];
|
||||
$this->config['cert_public'] = $options['cert_public'];
|
||||
$this->config['cert_private'] = $options['cert_private'];
|
||||
|
||||
if (empty($options['cert_serial'])) {
|
||||
$this->config['cert_serial'] = openssl_x509_parse($this->config['cert_public'], true)['serialNumberHex'];
|
||||
} else {
|
||||
@ -108,6 +115,11 @@ abstract class BasicWePay
|
||||
Tools::$cache_path = $options['cache_path'];
|
||||
}
|
||||
|
||||
// 自动配置平台证书
|
||||
if ($this->autoCert) {
|
||||
$this->_autoCert();
|
||||
}
|
||||
|
||||
// 服务商参数支持
|
||||
// if (!empty($options['sp_appid'])) {
|
||||
// $this->config['sp_appid'] = $options['sp_appid'];
|
||||
@ -149,6 +161,7 @@ abstract class BasicWePay
|
||||
{
|
||||
list($time, $nonce) = [time(), uniqid() . rand(1000, 9999)];
|
||||
$signstr = join("\n", [$method, $pathinfo, $time, $nonce, $jsondata, '']);
|
||||
echo $pathinfo . PHP_EOL;
|
||||
|
||||
// 生成数据签名TOKEN
|
||||
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
|
||||
@ -161,7 +174,7 @@ abstract class BasicWePay
|
||||
'Content-Type: application/json',
|
||||
'User-Agent: https://thinkadmin.top',
|
||||
"Authorization: WECHATPAY2-SHA256-RSA2048 {$token}",
|
||||
"Wechatpay-Serial: {$this->config['cert_serial']}"
|
||||
"Wechatpay-Serial: {$this->config['mp_cert_serial']}"
|
||||
],
|
||||
]);
|
||||
|
||||
@ -242,29 +255,77 @@ abstract class BasicWePay
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
*/
|
||||
protected function signVerify($data, $sign, $serial = '')
|
||||
protected function signVerify($data, $sign, $serial)
|
||||
{
|
||||
$cert = $this->tmpFile($serial);
|
||||
if (empty($cert)) {
|
||||
Cert::instance($this->config)->download();
|
||||
$cert = $this->tmpFile($serial);
|
||||
}
|
||||
$cert = $this->_getCert($serial);
|
||||
return @openssl_verify($data, base64_decode($sign), openssl_x509_read($cert), 'sha256WithRSAEncryption');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取平台证书
|
||||
* @param string $serial
|
||||
* @return string
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
*/
|
||||
protected function _getCert($serial = '')
|
||||
{
|
||||
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
|
||||
if (empty($certs) || empty($certs[$serial]['content'])) {
|
||||
Cert::instance($this->config)->download();
|
||||
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
|
||||
}
|
||||
if (empty($certs[$serial]['content']) || $certs[$serial]['expire'] < time()) {
|
||||
throw new InvalidResponseException("读取平台证书失败!");
|
||||
} else {
|
||||
return $certs[$serial]['content'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动配置平台证书
|
||||
* @return void
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
*/
|
||||
protected function _autoCert()
|
||||
{
|
||||
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
|
||||
if (is_array($certs)) foreach ($certs as $k => $v) if ($v['expire'] < time()) unset($certs[$k]);
|
||||
if (empty($certs)) {
|
||||
Cert::instance($this->config)->download();
|
||||
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
|
||||
}
|
||||
if (empty($certs) || !is_array($certs)) {
|
||||
throw new InvalidResponseException("读取平台证书失败!");
|
||||
}
|
||||
foreach ($certs as $k => $v) if ($v['expire'] > time() + 10) {
|
||||
$this->config['mp_cert_serial'] = $k;
|
||||
$this->config['mp_cert_content'] = $v['content'];
|
||||
break;
|
||||
}
|
||||
if (empty($this->config['mp_cert_serial']) || empty($this->config['mp_cert_content'])) {
|
||||
throw new InvalidResponseException("自动配置平台证书失败!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入或读取临时文件
|
||||
* @param string $name
|
||||
* @param null|string $content
|
||||
* @return string
|
||||
* @param null|array|string $content
|
||||
* @param integer $expire
|
||||
* @return array|string
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
*/
|
||||
protected function tmpFile($name, $content = null)
|
||||
protected function tmpFile($name, $content = null, $expire = 7200)
|
||||
{
|
||||
if (is_null($content)) {
|
||||
return base64_decode(Tools::getCache($name) ?: '');
|
||||
$text = Tools::getCache($name);
|
||||
if (empty($text)) return '';
|
||||
$json = json_decode(Tools::getCache($name) ?: '', true);
|
||||
return isset($json[0]) ? $json[0] : '';
|
||||
} else {
|
||||
return Tools::setCache($name, base64_encode($content), 7200);
|
||||
return Tools::setCache($name, json_encode([$content], JSON_UNESCAPED_UNICODE), $expire);
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,27 +337,11 @@ abstract class BasicWePay
|
||||
*/
|
||||
protected function rsaEncode($string)
|
||||
{
|
||||
$publicKey = file_get_contents($this->config['cert_public']);
|
||||
$publicKey = file_get_contents($this->config['mp_cert_content']);
|
||||
if (openssl_public_encrypt($string, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING)) {
|
||||
return base64_encode($encrypted);
|
||||
} else {
|
||||
throw new InvalidDecryptException('Rsa Encrypt Error.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA 解密处理
|
||||
* @param string $string
|
||||
* @return string
|
||||
* @throws \WeChat\Exceptions\InvalidDecryptException
|
||||
*/
|
||||
protected function rsaDecode($string)
|
||||
{
|
||||
$private = file_get_contents($this->config['cert_private']);
|
||||
if (openssl_private_decrypt(base64_decode($string), $content, $private, OPENSSL_PKCS1_OAEP_PADDING)) {
|
||||
return $content;
|
||||
} else {
|
||||
throw new InvalidDecryptException('Rsa Decrypt Error.');
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user