mirror of
https://gitee.com/zoujingli/WeChatDeveloper.git
synced 2025-11-07 04:02:14 +08:00
fix: 增加自定义批量证书配置,支持平台证书及支付证书
This commit is contained in:
parent
d0955ea5c7
commit
fc62209e64
@ -39,7 +39,7 @@ abstract class BasicWePay
|
||||
* 实例对象静态缓存
|
||||
* @var array
|
||||
*/
|
||||
static $cache = [];
|
||||
protected static $cache = [];
|
||||
|
||||
/**
|
||||
* 自动配置平台证书
|
||||
@ -58,8 +58,9 @@ abstract class BasicWePay
|
||||
'cert_serial' => '', // 商户证书序号,无需配置
|
||||
'cert_public' => '', // 商户公钥内容,需要配置
|
||||
'cert_private' => '', // 商户密钥内容,需要配置
|
||||
'mp_cert_serial' => '', // 平台证书序号,无需配置 ( 新平台,当做微信支付证书用 )
|
||||
'mp_cert_content' => '', // 平台证书内容,无需配置 ( 新平台,当做微信支付证书用 )
|
||||
'cert_package' => [], // 平台证书或支付证书配置
|
||||
'mp_cert_serial' => '', // 平台证书序号,无需配置 ( 指定平台证书或支付公钥 )
|
||||
'mp_cert_content' => '', // 平台证书内容,无需配置 ( 指定平台证书或支付公钥 )
|
||||
];
|
||||
|
||||
/**
|
||||
@ -117,10 +118,19 @@ abstract class BasicWePay
|
||||
Tools::$cache_path = $options['cache_path'];
|
||||
}
|
||||
|
||||
// 自动配置平台证书
|
||||
// 批量设置自定义证书
|
||||
if (isset($options['cert_package']) && is_array($options['cert_package'])) {
|
||||
foreach ($options['cert_package'] as $key => $cert) {
|
||||
$this->withCertContent($key, $cert);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动配置平台证书或支付公钥
|
||||
if (empty($options['mp_cert_serial']) || empty($options['mp_cert_content'])) {
|
||||
if ($this->autoCert) $this->_autoCert();
|
||||
} else {
|
||||
if ($this->autoCert && !$this->withCertPayment()) {
|
||||
$this->_autoCert();
|
||||
}
|
||||
} elseif ($this->withCertContent($options['mp_cert_serial'], $options['mp_cert_content'])) {
|
||||
$this->config['mp_cert_serial'] = $options['mp_cert_serial'];
|
||||
$this->config['mp_cert_content'] = $options['mp_cert_content'];
|
||||
}
|
||||
@ -340,10 +350,10 @@ abstract class BasicWePay
|
||||
*/
|
||||
protected function signVerify($data, $sign, $serial)
|
||||
{
|
||||
if (stripos($this->config['mp_cert_serial'], 'PUB_KEY_ID_') !== false) {
|
||||
return @openssl_verify($data, base64_decode($sign), $this->config['mp_cert_content'], OPENSSL_ALGO_SHA256);
|
||||
if (stripos($serial, 'PUB_KEY_ID_') !== false && !empty($this->config['cert_package'][$serial])) {
|
||||
return openssl_verify($data, base64_decode($sign), $this->config['cert_package'][$serial], OPENSSL_ALGO_SHA256);
|
||||
} else {
|
||||
return @openssl_verify($data, base64_decode($sign), openssl_x509_read($this->_getCert($serial)), 'sha256WithRSAEncryption');
|
||||
return openssl_verify($data, base64_decode($sign), openssl_x509_read($this->_getCert($serial)), 'sha256WithRSAEncryption');
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,11 +371,31 @@ abstract class BasicWePay
|
||||
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'];
|
||||
foreach ($certs as $cert) {
|
||||
if ($certs[$serial]['expire'] > time()) {
|
||||
$this->config['cert_package'][$cert['serial']] = $cert['content'];
|
||||
if (empty($this->config['mp_cert_serial'])) {
|
||||
$this->config['mp_cert_serial'] = $cert['serial'];
|
||||
$this->config['mp_cert_content'] = $cert['content'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// 未设置序号时,直接返回默认证书内容
|
||||
if (empty($serial) && !empty($this->config['mp_cert_content'])) {
|
||||
return $this->config['mp_cert_content'];
|
||||
}
|
||||
|
||||
// 遍历证书数组,找到匹配的证书
|
||||
if ($cert = $this->withCertPayment()) {
|
||||
return $cert;
|
||||
}
|
||||
|
||||
// 检查指定序号的证书是否存在
|
||||
if (!isset($this->config['cert_package'][$serial])) {
|
||||
throw new InvalidResponseException("读取平台证书失败!");
|
||||
}
|
||||
|
||||
return $this->config['cert_package'][$serial];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -388,11 +418,13 @@ abstract class BasicWePay
|
||||
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;
|
||||
$this->config['cert_package'][$k] = $v['content'];
|
||||
if (empty($this->config['mp_cert_serial'])) {
|
||||
$this->config['mp_cert_serial'] = $k;
|
||||
$this->config['mp_cert_content'] = $v['content'];
|
||||
}
|
||||
}
|
||||
if (empty($this->config['mp_cert_serial']) || empty($this->config['mp_cert_content'])) {
|
||||
if (empty($this->config['cert_package'])) {
|
||||
throw new InvalidResponseException("自动配置平台证书失败!");
|
||||
}
|
||||
}
|
||||
@ -432,4 +464,41 @@ abstract class BasicWePay
|
||||
throw new InvalidDecryptException('Rsa Encrypt Error.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置证书内容
|
||||
* @param string $key 证书ID或序号
|
||||
* @param string $cert 证书文本内容
|
||||
* @return string
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
*/
|
||||
private function withCertContent($key, $cert)
|
||||
{
|
||||
if (substr(trim($cert), 0, 5) == '-----') {
|
||||
$this->config['cert_package'][$key] = $cert;
|
||||
} elseif (file_exists($cert)) {
|
||||
$this->config['cert_package'][$key] = file_get_contents($cert);
|
||||
} else {
|
||||
throw new InvalidResponseException("证书设置失败!");
|
||||
}
|
||||
return $cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付证书
|
||||
* @return mixed|string
|
||||
*/
|
||||
private function withCertPayment()
|
||||
{
|
||||
foreach ($this->config['cert_package'] as $key => $cert) {
|
||||
if (strpos($key, 'PUB_KEY_ID_') === 0) {
|
||||
if (empty($this->config['mp_cert_serial']) || empty($this->config['mp_cert_content'])) {
|
||||
$this->config['mp_cert_serial'] = $key;
|
||||
$this->config['mp_cert_content'] = $cert;
|
||||
}
|
||||
return $cert;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@ -1,82 +1,86 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | WeChatDeveloper
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/WeChatDeveloper
|
||||
// | github 代码仓库:https://github.com/zoujingli/WeChatDeveloper
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
$certPublic = <<<CERT
|
||||
-----BEGIN CERTIFICATE-----
|
||||
文件文本内容
|
||||
-----END CERTIFICATE-----
|
||||
CERT;
|
||||
|
||||
$certPrivate = <<<CERT
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
文件文本内容
|
||||
-----END PRIVATE KEY-----
|
||||
CERT;
|
||||
|
||||
// 支付证书内容
|
||||
$certPayment = <<<CERT
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
文件文本内容
|
||||
-----END PUBLIC KEY-----
|
||||
CERT;
|
||||
|
||||
|
||||
// =====================================================
|
||||
// 配置缓存处理函数 ( 适配其他环境 )
|
||||
// -----------------------------------------------------
|
||||
// 数据缓存 (set|get|del) 操作可以将缓存写到任意位置或Redis
|
||||
// 文件缓存 (put) 只能写在本地服务器,还需要返回可读的文件路径
|
||||
// 未配置自定义缓存处理机制时,默认在 cache_path 写入文件缓存
|
||||
// // =====================================================
|
||||
// \WeChat\Contracts\Tools::$cache_callable = [
|
||||
// 'set' => function ($name, $value, $expired = 360) {
|
||||
// var_dump(func_get_args());
|
||||
// return $value;
|
||||
// },
|
||||
// 'get' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return $value;
|
||||
// },
|
||||
// 'del' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return true;
|
||||
// },
|
||||
// 'put' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return $filePath;
|
||||
// },
|
||||
// ];
|
||||
|
||||
return [
|
||||
// 可选,公众号APPID
|
||||
'appid' => 'wx3760axxxxxxxxxxx',
|
||||
// 必填,微信商户编号ID
|
||||
'mch_id' => '152xxxxxxxx',
|
||||
// 必填,微信商户V3接口密钥,不影响发起支付但无法验证支付通知
|
||||
'mch_v3_key' => '98b7f45xxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
// 可选,微信商户证书序列号,可从公钥中提取,请求签名使用
|
||||
'cert_serial' => '49055xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
// 必填,微信商户证书公钥,支持证书内容或文件路径,仅用于提取序号
|
||||
'cert_public' => $certPublic,
|
||||
// 必填,微信商户证书私钥,支持证书内容或文件路径,用于请求数据签名
|
||||
'cert_private' => $certPrivate,
|
||||
// 可选,微信平台证书序号或支付证书序号,用于接口请求序号
|
||||
'mp_cert_serial' => 'PUB_KEY_ID_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
// 可选,微信平台证书内容或支付证书内容
|
||||
'mp_cert_content' => $certPayment,
|
||||
// 可选,运行时的文件缓存路径
|
||||
'cache_path' => ''
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | WeChatDeveloper
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/WeChatDeveloper
|
||||
// | github 代码仓库:https://github.com/zoujingli/WeChatDeveloper
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
$certPublic = <<<CERT
|
||||
-----BEGIN CERTIFICATE-----
|
||||
文件文本内容
|
||||
-----END CERTIFICATE-----
|
||||
CERT;
|
||||
|
||||
$certPrivate = <<<CERT
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
文件文本内容
|
||||
-----END PRIVATE KEY-----
|
||||
CERT;
|
||||
|
||||
// 支付证书内容
|
||||
$certPayment = <<<CERT
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
文件文本内容
|
||||
-----END PUBLIC KEY-----
|
||||
CERT;
|
||||
|
||||
|
||||
// =====================================================
|
||||
// 配置缓存处理函数 ( 适配其他环境 )
|
||||
// -----------------------------------------------------
|
||||
// 数据缓存 (set|get|del) 操作可以将缓存写到任意位置或Redis
|
||||
// 文件缓存 (put) 只能写在本地服务器,还需要返回可读的文件路径
|
||||
// 未配置自定义缓存处理机制时,默认在 cache_path 写入文件缓存
|
||||
// // =====================================================
|
||||
// \WeChat\Contracts\Tools::$cache_callable = [
|
||||
// 'set' => function ($name, $value, $expired = 360) {
|
||||
// var_dump(func_get_args());
|
||||
// return $value;
|
||||
// },
|
||||
// 'get' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return $value;
|
||||
// },
|
||||
// 'del' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return true;
|
||||
// },
|
||||
// 'put' => function ($name) {
|
||||
// var_dump(func_get_args());
|
||||
// return $filePath;
|
||||
// },
|
||||
// ];
|
||||
|
||||
return [
|
||||
// 可选,公众号APPID
|
||||
'appid' => 'wx3760xxxxxxxxxxxx',
|
||||
// 必填,微信商户编号ID
|
||||
'mch_id' => '15293xxxxxx',
|
||||
// 必填,微信商户V3接口密钥
|
||||
'mch_v3_key' => '98b7fxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
// 可选,微信商户证书序列号,可从公钥中提取,请求签名使用
|
||||
'cert_serial' => '49055D67B2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||
// 必填,微信商户证书公钥,支持证书内容或文件路径,仅用于提取序号
|
||||
'cert_public' => $certPublic,
|
||||
// 必填,微信商户证书私钥,支持证书内容或文件路径,用于请求数据签名
|
||||
'cert_private' => $certPrivate,
|
||||
// 批量设置自定义证书内容,支持平台证书或支付公钥,可填写文件路径及内容
|
||||
'cert_package' => [
|
||||
'PUB_KEY_ID_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' => $certPayment
|
||||
],
|
||||
// 可选,微信平台证书序号或支付证书序号,直接支持平台证书或支付公钥
|
||||
// 'mp_cert_serial' => 'PUB_KEY_ID_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
// 可选,微信平台证书内容或支付证书内容,直接支持平台证书或支付公钥
|
||||
// 'mp_cert_content' => $certPayment,
|
||||
// 可选,运行时的文件缓存路径
|
||||
'cache_path' => ''
|
||||
];
|
||||
Loading…
x
Reference in New Issue
Block a user