Преглед изворни кода

更新wechatpay/wechatpay扩展v1.4.6->1.4.11

萤火科技 пре 1 година
родитељ
комит
ddee5860d9

+ 7 - 8
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "6a7996d88fd82c5b30b1a2ce37fdcce9",
+    "content-hash": "8207fe9341ea69e087b7ad94ad40eb1f",
     "packages": [
         {
             "name": "adbario/php-dot-notation",
@@ -4372,16 +4372,16 @@
         },
         {
             "name": "wechatpay/wechatpay",
-            "version": "1.4.6",
+            "version": "1.4.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/wechatpay-apiv3/wechatpay-php.git",
-                "reference": "edbdb6bb19e0818b0576043b265ff1b1e188d668"
+                "reference": "6f2994f04412c909d3561585ba437b50b894306f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/wechatpay-apiv3/wechatpay-php/zipball/edbdb6bb19e0818b0576043b265ff1b1e188d668",
-                "reference": "edbdb6bb19e0818b0576043b265ff1b1e188d668",
+                "url": "https://api.github.com/repos/wechatpay-apiv3/wechatpay-php/zipball/6f2994f04412c909d3561585ba437b50b894306f",
+                "reference": "6f2994f04412c909d3561585ba437b50b894306f",
                 "shasum": ""
             },
             "require": {
@@ -4433,9 +4433,9 @@
             ],
             "support": {
                 "issues": "https://github.com/wechatpay-apiv3/wechatpay-php/issues",
-                "source": "https://github.com/wechatpay-apiv3/wechatpay-php/tree/v1.4.6"
+                "source": "https://github.com/wechatpay-apiv3/wechatpay-php/tree/v1.4.11"
             },
-            "time": "2022-08-19T09:14:39+00:00"
+            "time": "2024-12-27T15:22:15+00:00"
         },
         {
             "name": "workerman/gateway-worker",
@@ -4893,7 +4893,6 @@
         "ext-simplexml": "*",
         "ext-zlib": "*",
         "ext-zip": "*",
-        "ext-redis": "*",
         "ext-fileinfo": "*"
     },
     "platform-dev": [],

+ 27 - 14
vendor/composer/ClassLoader.php

@@ -42,6 +42,9 @@ namespace Composer\Autoload;
  */
 class ClassLoader
 {
+    /** @var \Closure(string):void */
+    private static $includeFile;
+
     /** @var ?string */
     private $vendorDir;
 
@@ -106,6 +109,7 @@ class ClassLoader
     public function __construct($vendorDir = null)
     {
         $this->vendorDir = $vendorDir;
+        self::initializeIncludeClosure();
     }
 
     /**
@@ -425,7 +429,8 @@ class ClassLoader
     public function loadClass($class)
     {
         if ($file = $this->findFile($class)) {
-            includeFile($file);
+            $includeFile = self::$includeFile;
+            $includeFile($file);
 
             return true;
         }
@@ -555,18 +560,26 @@ class ClassLoader
 
         return false;
     }
-}
 
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param  string $file
- * @return void
- * @private
- */
-function includeFile($file)
-{
-    include $file;
+    /**
+     * @return void
+     */
+    private static function initializeIncludeClosure()
+    {
+        if (self::$includeFile !== null) {
+            return;
+        }
+
+        /**
+         * Scope isolated include.
+         *
+         * Prevents access to $this/self from included files.
+         *
+         * @param  string $file
+         * @return void
+         */
+        self::$includeFile = \Closure::bind(static function($file) {
+            include $file;
+        }, null, null);
+    }
 }

+ 12 - 5
vendor/composer/InstalledVersions.php

@@ -98,7 +98,7 @@ class InstalledVersions
     {
         foreach (self::getInstalled() as $installed) {
             if (isset($installed['versions'][$packageName])) {
-                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
             }
         }
 
@@ -119,7 +119,7 @@ class InstalledVersions
      */
     public static function satisfies(VersionParser $parser, $packageName, $constraint)
     {
-        $constraint = $parser->parseConstraints($constraint);
+        $constraint = $parser->parseConstraints((string) $constraint);
         $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
 
         return $provided->matches($constraint);
@@ -328,7 +328,9 @@ class InstalledVersions
                 if (isset(self::$installedByVendor[$vendorDir])) {
                     $installed[] = self::$installedByVendor[$vendorDir];
                 } elseif (is_file($vendorDir.'/composer/installed.php')) {
-                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+                    $required = require $vendorDir.'/composer/installed.php';
+                    $installed[] = self::$installedByVendor[$vendorDir] = $required;
                     if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
                         self::$installed = $installed[count($installed) - 1];
                     }
@@ -340,12 +342,17 @@ class InstalledVersions
             // only require the installed.php file if this file is loaded from its dumped location,
             // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
             if (substr(__DIR__, -8, 1) !== 'C') {
-                self::$installed = require __DIR__ . '/installed.php';
+                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+                $required = require __DIR__ . '/installed.php';
+                self::$installed = $required;
             } else {
                 self::$installed = array();
             }
         }
-        $installed[] = self::$installed;
+
+        if (self::$installed !== array()) {
+            $installed[] = self::$installed;
+        }
 
         return $installed;
     }

+ 10 - 17
vendor/composer/autoload_real.php

@@ -33,25 +33,18 @@ class ComposerAutoloaderInitb17d9cf9df517c3dd2f492a1c933c315
 
         $loader->register(true);
 
-        $includeFiles = \Composer\Autoload\ComposerStaticInitb17d9cf9df517c3dd2f492a1c933c315::$files;
-        foreach ($includeFiles as $fileIdentifier => $file) {
-            composerRequireb17d9cf9df517c3dd2f492a1c933c315($fileIdentifier, $file);
+        $filesToLoad = \Composer\Autoload\ComposerStaticInitb17d9cf9df517c3dd2f492a1c933c315::$files;
+        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+                require $file;
+            }
+        }, null, null);
+        foreach ($filesToLoad as $fileIdentifier => $file) {
+            $requireFile($fileIdentifier, $file);
         }
 
         return $loader;
     }
 }
-
-/**
- * @param string $fileIdentifier
- * @param string $file
- * @return void
- */
-function composerRequireb17d9cf9df517c3dd2f492a1c933c315($fileIdentifier, $file)
-{
-    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
-        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
-
-        require $file;
-    }
-}

+ 7 - 7
vendor/composer/installed.json

@@ -4753,17 +4753,17 @@
         },
         {
             "name": "wechatpay/wechatpay",
-            "version": "1.4.6",
-            "version_normalized": "1.4.6.0",
+            "version": "1.4.11",
+            "version_normalized": "1.4.11.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/wechatpay-apiv3/wechatpay-php.git",
-                "reference": "edbdb6bb19e0818b0576043b265ff1b1e188d668"
+                "reference": "6f2994f04412c909d3561585ba437b50b894306f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/wechatpay-apiv3/wechatpay-php/zipball/edbdb6bb19e0818b0576043b265ff1b1e188d668",
-                "reference": "edbdb6bb19e0818b0576043b265ff1b1e188d668",
+                "url": "https://api.github.com/repos/wechatpay-apiv3/wechatpay-php/zipball/6f2994f04412c909d3561585ba437b50b894306f",
+                "reference": "6f2994f04412c909d3561585ba437b50b894306f",
                 "shasum": ""
             },
             "require": {
@@ -4779,7 +4779,7 @@
                 "phpstan/phpstan": "^0.12.89 || ^1.0",
                 "phpunit/phpunit": "^7.5 || ^8.5.16 || ^9.3.5"
             },
-            "time": "2022-08-19T09:14:39+00:00",
+            "time": "2024-12-27T15:22:15+00:00",
             "bin": [
                 "bin/CertificateDownloader.php"
             ],
@@ -4817,7 +4817,7 @@
             ],
             "support": {
                 "issues": "https://github.com/wechatpay-apiv3/wechatpay-php/issues",
-                "source": "https://github.com/wechatpay-apiv3/wechatpay-php/tree/v1.4.6"
+                "source": "https://github.com/wechatpay-apiv3/wechatpay-php/tree/v1.4.11"
             },
             "install-path": "../wechatpay/wechatpay"
         },

+ 9 - 9
vendor/composer/installed.php

@@ -1,9 +1,9 @@
 <?php return array(
     'root' => array(
         'name' => 'topthink/think',
-        'pretty_version' => 'dev-dev未加密',
-        'version' => 'dev-dev未加密',
-        'reference' => '7f93d97be14576b7507983c17a67048737a63359',
+        'pretty_version' => 'dev-master',
+        'version' => 'dev-master',
+        'reference' => '47b656fb5a821b897ca05c28dbd4da47ab8c12e7',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -622,9 +622,9 @@
             'dev_requirement' => false,
         ),
         'topthink/think' => array(
-            'pretty_version' => 'dev-dev未加密',
-            'version' => 'dev-dev未加密',
-            'reference' => '7f93d97be14576b7507983c17a67048737a63359',
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'reference' => '47b656fb5a821b897ca05c28dbd4da47ab8c12e7',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
@@ -685,9 +685,9 @@
             'dev_requirement' => false,
         ),
         'wechatpay/wechatpay' => array(
-            'pretty_version' => '1.4.6',
-            'version' => '1.4.6.0',
-            'reference' => 'edbdb6bb19e0818b0576043b265ff1b1e188d668',
+            'pretty_version' => '1.4.11',
+            'version' => '1.4.11.0',
+            'reference' => '6f2994f04412c909d3561585ba437b50b894306f',
             'type' => 'library',
             'install_path' => __DIR__ . '/../wechatpay/wechatpay',
             'aliases' => array(),

+ 1 - 1
vendor/services.php

@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2023-02-22 11:45:22
+// This file is automatically generated at:2024-12-28 16:50:02
 declare (strict_types = 1);
 return array (
   0 => 'think\\app\\Service',

+ 24 - 0
vendor/wechatpay/wechatpay/CHANGELOG.md

@@ -1,5 +1,29 @@
 # 变更历史
 
+## [1.4.11](../../compare/v1.4.9...v1.4.10) - 2024-12-23
+
+- 对`APIv2`服务端返回值做精细判断,对于`return_code`(返回状态码)及/或`result_code`(业务结果)有key且值不为`SUCCESS`的情形,抛出客户端`RejectionException`异常,并加入[AuthcodetoopenidTest.php](./tests/OpenAPI/V2/Tools/AuthcodetoopenidTest.php)异常处理示例。
+
+## [1.4.10](../../compare/v1.4.9...v1.4.10) - 2024-09-19
+
+- 客户端在`RSA`非对称加解密方案上,不再支持`OPENSSL_PKCS1_PADDING`填充模式,相关记录见[这里](https://github.com/wechatpay-apiv3/wechatpay-php/issues/133);
+- 增加[`#[\SensitiveParameter]`](https://www.php.net/manual/zh/class.sensitiveparameter.php)参数注解,加强信息安全;
+- 支持PHP8.4运行时;
+
+## [1.4.9](../../compare/v1.4.8...v1.4.9) - 2023-11-21
+
+- 支持PHP8.3运行时
+
+## [1.4.8](../../compare/v1.4.7...v1.4.8) - 2023-01-05
+
+- 新增海外账单下载`/v3/global/statements`应答特殊处理逻辑;
+
+## [1.4.7](../../compare/v1.4.6...v1.4.7) - 2022-12-06
+
+- 对PHP8.2的官方支持,如下PHP8.2的特性需要被提及:
+  - ext-openssl 有若干调整,已知在 `OpenSSL3.0` 上,常量 `RSA_SSLV23_PADDING` 被删除(详细可阅读 openssl/openssl#14216, openssl/openssl#14283),PHP做了兼容处理,如果扩展依赖的是`OpenSSL3.0`,则对应的`OPENSSL_SSLV23_PADDING`常量将不存在,进而影响到了「非对称加解密混合填充模式的测试用例」的覆盖(详情可阅读 shivammathur/setup-php#658)。本类库并不支持此填充模式,删除对`OPENSSL_SSLV23_PADDING`的测试断言,向前兼容;
+  - 对象动态属性的废弃提示([Deprecate dynamic properties](https://wiki.php.net/rfc/deprecate_dynamic_properties)),本类库实例构造的是`ArrayIterator`的一个“伪”动态属性结构体,对象属性访问实则访问的是`ArrayObject`内置`__storage`属性,形似动态属性实则不是;此废弃提示对本类库本身无影响;
+
 ## [1.4.6](../../compare/v1.4.5...v1.4.6) - 2022-08-19
 
 - 取消 `APIv2` 上的`trigger_error`提醒,以消除不必要的恐慌;

+ 79 - 38
vendor/wechatpay/wechatpay/README.md

@@ -15,7 +15,7 @@
 
 ### 功能介绍
 
-1. 微信支付 APIv2 和 APIv3 的 Guzzle HTTP 客户端,支持 [同步](#同步请求) 或[异步](#异步请求) 发送请求,并自动进行请求签名和应答验签
+1. 微信支付 APIv2 和 APIv3 的 Guzzle HTTP 客户端,支持 [同步](#同步请求) 或 [异步](#异步请求) 发送请求,并自动进行请求签名和应答验签
 
 1. [链式实现的 URI Template](#链式-uri-template)
 
@@ -25,7 +25,7 @@
 
 ## 项目状态
 
-当前版本为 `1.4.6` 测试版本。
+当前版本为 `1.4.11` 版。
 项目版本遵循 [语义化版本号](https://semver.org/lang/zh-CN/)。
 如果你使用的版本 `<=v1.3.2`,升级前请参考 [升级指南](UPGRADING.md)。
 
@@ -36,7 +36,7 @@
 + Guzzle 7.0,PHP >= 7.2.5
 + Guzzle 6.5,PHP >= 7.1.2
 
-项目已支持 PHP 8。我们推荐使用目前处于 [Active Support](https://www.php.net/supported-versions.php) 阶段的 PHP 8.0 和 Guzzle 7。
+我们推荐使用目前处于 [Active Support](https://www.php.net/supported-versions.php) 阶段的 PHP 8 和 Guzzle 7。
 
 ## 安装
 
@@ -48,7 +48,7 @@ composer require wechatpay/wechatpay
 
 ## 开始
 
-ℹ️ 以下是 [微信支付 API v3](https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml) 的指引。如果你是 API v2 的使用者,请看 [README_APIv2](README_APIv2.md)。
+:information_source: 以下是 [微信支付 API v3](https://pay.weixin.qq.com/docs/merchant/development/interface-rules/introduction.html) 的指引。如果你是 API v2 的使用者,请看 [README_APIv2](README_APIv2.md)。
 
 ### 概念
 
@@ -56,15 +56,19 @@ composer require wechatpay/wechatpay
 
 + **商户 API 私钥**。你申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。为了证明 API 请求是由你发送的,你应使用商户 API 私钥对请求进行签名。
 
-> :warning: 不要把私钥文件暴露在公共场合,如上传到 Github,写在 App 代码中等。
+  > :key: 不要把私钥文件暴露在公共场合,如上传到 Github,写在 App 代码中等。
 
 + **微信支付平台证书**。微信支付平台证书是指:由微信支付负责申请,包含微信支付平台标识、公钥信息的证书。你需使用微信支付平台证书中的公钥验证 API 应答和回调通知的签名。
 
-> ℹ️ 你需要先手工 [下载平台证书](#如何下载平台证书) 才能使用 SDK 发起请求。
+  > :bookmark: 通用的 composer 命令,像安装依赖包一样 [下载平台证书](#如何下载平台证书) 文件,供SDK初始化使用。
 
 + **证书序列号**。每个证书都有一个由 CA 颁发的唯一编号,即证书序列号。
 
-### 示例程序:微信支付平台证书下载
++ **微信支付公钥**,用于应答及回调通知的数据签名,可在 [微信支付商户平台](https://pay.weixin.qq.com) -> 账户中心 -> API安全 直接下载。
+
++ **微信支付公钥ID**,是微信支付公钥的唯一标识,可在 [微信支付商户平台](https://pay.weixin.qq.com) -> 账户中心 -> API安全 直接查看。
+
+### 初始化一个APIv3客户端
 
 ```php
 <?php
@@ -73,7 +77,6 @@ require_once('vendor/autoload.php');
 
 use WeChatPay\Builder;
 use WeChatPay\Crypto\Rsa;
-use WeChatPay\Util\PemUtil;
 
 // 设置参数
 
@@ -87,12 +90,21 @@ $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TY
 // 「商户API证书」的「证书序列号」
 $merchantCertificateSerial = '3775B6A45ACD588826D15E583A95F5DD********';
 
-// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
-$platformCertificateFilePath = 'file:///path/to/wechatpay/cert.pem';
-$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
+// 从本地文件中加载「微信支付平台证书」,可由内置CLI工具下载到,用来验证微信支付应答的签名
+$platformCertificateFilePath  = 'file:///path/to/wechatpay/certificate.pem';
+$onePlatformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
+
+// 「微信支付平台证书」的「平台证书序列号」
+// 可以从「微信支付平台证书」文件解析,也可以在 商户平台 -> 账户中心 -> API安全 查询到
+$platformCertificateSerial = '7132D72A03E93CDDF8C03BBD1F37EEDF********';
+
+// 从本地文件中加载「微信支付公钥」,用来验证微信支付应答的签名
+$platformPublicKeyFilePath    = 'file:///path/to/wechatpay/publickey.pem';
+$twoPlatformPublicKeyInstance = Rsa::from($platformPublicKeyFilePath, Rsa::KEY_TYPE_PUBLIC);
 
-// 从「微信支付平台证书」中获取「证书序列号」
-$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
+// 「微信支付公钥」的「微信支付公钥ID」
+// 需要在 商户平台 -> 账户中心 -> API安全 查询
+$platformPublicKeyId = 'PUB_KEY_ID_01142321349124100000000000********';
 
 // 构造一个 APIv3 客户端实例
 $instance = Builder::factory([
@@ -100,22 +112,50 @@ $instance = Builder::factory([
     'serial'     => $merchantCertificateSerial,
     'privateKey' => $merchantPrivateKeyInstance,
     'certs'      => [
-        $platformCertificateSerial => $platformPublicKeyInstance,
+        $platformCertificateSerial => $onePlatformPublicKeyInstance,
+        $platformPublicKeyId       => $twoPlatformPublicKeyInstance,
     ],
 ]);
+```
+
+### 示例,第一个请求:查询「微信支付平台证书」
 
+```php
 // 发送请求
-$resp = $instance->chain('v3/certificates')->get(
-    ['debug' => true] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug
-);
-echo $resp->getBody(), PHP_EOL;
+try {
+    $resp = $instance->chain('v3/certificates')->get(
+        /** @see https://docs.guzzlephp.org/en/stable/request-options.html#debug */
+        // ['debug' => true] // 调试模式
+    );
+    echo (string) $resp->getBody(), PHP_EOL;
+} catch(\Exception $e) {
+    // 进行异常捕获并进行错误判断处理
+    echo $e->getMessage(), PHP_EOL;
+    if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
+        $r = $e->getResponse();
+        echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
+        echo (string) $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
+    }
+    echo $e->getTraceAsString(), PHP_EOL;
+}
+```
+
+当程序进入「异常捕获」逻辑,输出形如:
+
+```json
+{
+    "code": "RESOURCE_NOT_EXISTS",
+    "message": "无可用的平台证书,请在商户平台-API安全申请使用微信支付公钥。可查看指引https://pay.weixin.qq.com/docs/merchant/products/platform-certificate/wxp-pub-key-guide.html"
+}
 ```
 
+即表示商户仅能运行在「微信支付公钥」模式,初始化即无需读取及配置`$platformCertificateSerial`及`$onePlatformPublicKeyInstance`等信息。
+
 ## 文档
 
 ### 同步请求
 
-使用客户端提供的 `get`、`put`、`post`、`patch` 或 `delete` 方法发送同步请求。以 [Native支付下单](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml) 为例。
+使用客户端提供的 `get`、`put`、`post`、`patch` 或 `delete` 方法发送同步请求。以 [Native支付下单](https://pay.weixin.qq.com/docs/merchant/apis/native-payment/direct-jsons/native-prepay.html) 为例。
 
 ```php
 try {
@@ -134,14 +174,14 @@ try {
     ]]);
 
     echo $resp->getStatusCode(), PHP_EOL;
-    echo $resp->getBody(), PHP_EOL;
+    echo (string) $resp->getBody(), PHP_EOL;
 } catch (\Exception $e) {
     // 进行错误处理
     echo $e->getMessage(), PHP_EOL;
     if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
         $r = $e->getResponse();
         echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
-        echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
+        echo (string) $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
     }
     echo $e->getTraceAsString(), PHP_EOL;
 }
@@ -152,7 +192,7 @@ try {
 
 ### 异步请求
 
-使用客户端提供的 `getAsync`、`putAsync`、`postAsync`、`patchAsync` 或 `deleteAsync` 方法发送异步请求。以 [退款](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_9.shtml) 为例。
+使用客户端提供的 `getAsync`、`putAsync`、`postAsync`、`patchAsync` 或 `deleteAsync` 方法发送异步请求。以 [退款申请](https://pay.weixin.qq.com/docs/merchant/apis/native-payment/create.html) 为例。
 
 ```php
 $promise = $instance
@@ -170,7 +210,7 @@ $promise = $instance
 ])
 ->then(static function($response) {
     // 正常逻辑回调处理
-    echo $response->getBody(), PHP_EOL;
+    echo (string) $response->getBody(), PHP_EOL;
     return $response;
 })
 ->otherwise(static function($e) {
@@ -179,7 +219,7 @@ $promise = $instance
     if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
         $r = $e->getResponse();
         echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
-        echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
+        echo (string) $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
     }
     echo $e->getTraceAsString(), PHP_EOL;
 });
@@ -199,7 +239,7 @@ $promise->wait();
 
 对于大部分开发者,我们建议使用同步的模式,因为它更加易于理解。
 
-如果你是具有异步编程基础的开发者,在某些连续调用 API 的场景,将多个操作通过 `then()` 流式串联起来会是一种优雅的实现方式。例如, [以函数链的形式流式下载交易帐单](https://developers.weixin.qq.com/community/pay/article/doc/000ec4521086b85fb81d6472a51013)。
+如果你是具有异步编程基础的开发者,在某些连续调用 API 的场景,将多个操作通过 `then()` 流式串联起来会是一种优雅的实现方式。例如 [以函数链的形式流式下载交易帐单](https://developers.weixin.qq.com/community/pay/article/doc/000ec4521086b85fb81d6472a51013)。
 
 ## 链式 URI Template
 
@@ -230,7 +270,7 @@ GET /v3/pay/transactions/out-trade-no/{out_trade_no}
 + Path 变量的值,以同名参数传入执行方法
 + Query 参数,以名为 `query` 的参数传入执行方法
 
-以[查询订单](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml) `GET` 方法为例:
+以 [查询订单](https://pay.weixin.qq.com/docs/merchant/apis/native-payment/query-by-wx-trade-no.html) `GET` 方法为例:
 
 ```php
 $promise = $instance
@@ -243,7 +283,7 @@ $promise = $instance
 ]);
 ```
 
-以 [关闭订单](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_3.shtml) `POST` 方法为例:
+以 [关闭订单](https://pay.weixin.qq.com/docs/merchant/apis/native-payment/close-order.html) `POST` 方法为例:
 
 ```php
 $promise = $instance
@@ -258,9 +298,7 @@ $promise = $instance
 
 ## 更多例子
 
-### 视频文件上传
-
-[官方开发文档地址](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter2_1_2.shtml)
+### [视频文件上传](https://pay.weixin.qq.com/docs/partner/apis/contracted-merchant-application/video-upload.html)
 
 ```php
 // 参考上述指引说明,并引入 `MediaUtil` 正常初始化,无额外条件
@@ -278,9 +316,7 @@ $resp = $instance-
 ]);
 ```
 
-### 营销图片上传
-
-[官方开发文档地址](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_0_1.shtml)
+### [营销图片上传](https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/upload-image.html)
 
 ```php
 use WeChatPay\Util\MediaUtil;
@@ -302,7 +338,7 @@ $resp = $instance
 + 微信支付要求加密上送的敏感信息
 + 微信支付会加密下行的敏感信息
 
-下面以 [特约商户进件](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter11_1_1.shtml) 为例,演示如何进行 [敏感信息加解密](https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/min-gan-xin-xi-jia-mi)。
+下面以 [特约商户进件](https://pay.weixin.qq.com/docs/partner/apis/contracted-merchant-application/applyment/submit.html) 为例,演示如何进行 [敏感信息加解密](https://pay.weixin.qq.com/docs/partner/development/interface-rules/sensitive-data-encryption.html)。
 
 ```php
 use WeChatPay\Crypto\Rsa;
@@ -325,15 +361,15 @@ $resp = $instance
         //...
     ],
     'headers' => [
-        // $platformCertificateSerial 见初始化章节
-        'Wechatpay-Serial' => $platformCertificateSerial,
+        // $platformCertificateSerialOrPublicKeyId 见初始化章节
+        'Wechatpay-Serial' => $platformCertificateSerialOrPublicKeyId,
     ],
 ]);
 ```
 
 ## 签名
 
-你可以使用 `Rsa::sign()` 计算调起支付时所需参数签名。以 [JSAPI支付](https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml) 为例。
+你可以使用 `Rsa::sign()` 计算调起支付时所需参数签名。以 [JSAPI支付](https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/jsapi-transfer-payment.html) 为例。
 
 ```php
 use WeChatPay\Formatter;
@@ -363,7 +399,7 @@ echo json_encode($params);
 1. 从请求头部`Headers`,拿到`Wechatpay-Signature`、`Wechatpay-Nonce`、`Wechatpay-Timestamp`、`Wechatpay-Serial`及`Request-ID`,商户侧`Web`解决方案可能有差异,请求头可能大小写不敏感,请根据自身应用来定;
 2. 获取请求`body`体的`JSON`纯文本;
 3. 检查通知消息头标记的`Wechatpay-Timestamp`偏移量是否在5分钟之内;
-4. 调用`SDK`内置方法,[构造验签名串](https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml)然后经`Rsa::verfify`验签;
+4. 调用`SDK`内置方法,[构造验签名串](https://pay.weixin.qq.com/docs/merchant/development/verify-signature-overview/overview-signature-and-verification.html) 然后经`Rsa::verfify`验签;
 5. 消息体需要解密的,调用`SDK`内置方法解密;
 6. 如遇到问题,请拿`Request-ID`点击[这里](https://support.pay.weixin.qq.com/online-service?utm_source=github&utm_medium=wechatpay-php&utm_content=apiv3),联系官方在线技术支持;
 
@@ -431,6 +467,9 @@ if ($timeOffsetStatus && $verifiedStatus) {
 当默认的本地签名和验签方式不适合你的系统时,你可以通过实现`signer`或者`verifier`中间件来定制签名和验签,比如,你的系统把商户私钥集中存储,业务系统需通过远程调用进行签名。
 以下示例用来演示如何替换SDK内置中间件,来实现远程`请求签名`及`结果验签`,供商户参考实现。
 
+<details>
+<summary>例:内网集中签名/验签解决方案</summary>
+
 ```php
 use GuzzleHttp\Client;
 use GuzzleHttp\Middleware;
@@ -502,6 +541,8 @@ $stack->before('http_errors', static function (callable $handler) use ($remoteVe
 $instance->v3->certificates->getAsync()->then(static function($res) { return $res->getBody(); })->wait();
 ```
 
+</details>
+
 ## 常见问题
 
 ### 如何下载平台证书?

+ 30 - 0
vendor/wechatpay/wechatpay/SECURITY.md

@@ -0,0 +1,30 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported          |
+| ------- | ------------------ |
+| 1.x     | :white_check_mark: |
+
+## Reporting a Vulnerability
+
+Please do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors.
+
+Security issues in this open source project can be safely reported to [TSRC](https://security.tencent.com).
+
+## 报告漏洞
+
+请不要使用 GitHub issues 或 pull request —— 这会让漏洞立即暴露给所有人,包括恶意人员。
+
+请将本开源项目的安全问题报告给 [腾讯安全应急响应中心](https://security.tencent.com).
+
+---
+
+另外,你可能需要关注影响本SDK运行时行为的主要的PHP扩展缺陷列表:
+
++ [OpenSSL](https://www.openssl.org/news/vulnerabilities.html)
++ [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/NEWS)
++ [curl](https://curl.se/docs/security.html)
+
+当你准备在报告安全问题时,请先对照如上列表,确认是否存在已知运行时环境安全问题。
+当你尝试升级主要扩展至最新版本之后,如若问题依旧存在,请将本开源项目的安全问题报告给 [TSRC腾讯安全应急响应中心](https://security.tencent.com),致谢。

+ 0 - 2
vendor/wechatpay/wechatpay/bin/CertificateDownloader.php

@@ -57,7 +57,6 @@ class CertificateDownloader
     private static function certsInjector(string $apiv3Key, array &$certs): callable {
         return static function(ResponseInterface $response) use ($apiv3Key, &$certs): ResponseInterface {
             $body = (string) $response->getBody();
-            /** @var object{data:array<object{encrypt_certificate:object{serial_no:string,nonce:string,associated_data:string}}>} $json */
             $json = \json_decode($body);
             $data = \is_object($json) && isset($json->data) && \is_array($json->data) ? $json->data : [];
             \array_map(static function($row) use ($apiv3Key, &$certs) {
@@ -119,7 +118,6 @@ class CertificateDownloader
     private static function certsRecorder(string $outputDir, array &$certs): callable {
         return static function(ResponseInterface $response) use ($outputDir, &$certs): ResponseInterface {
             $body = (string) $response->getBody();
-            /** @var object{data:array<object{effective_time:string,expire_time:string:serial_no:string}>} $json */
             $json = \json_decode($body);
             $data = \is_object($json) && isset($json->data) && \is_array($json->data) ? $json->data : [];
             \array_walk($data, static function($row, $index, $certs) use ($outputDir) {

+ 1 - 1
vendor/wechatpay/wechatpay/composer.json

@@ -1,6 +1,6 @@
 {
     "name": "wechatpay/wechatpay",
-    "version": "1.4.6",
+    "version": "1.4.11",
     "description": "[A]Sync Chainable WeChatPay v2&v3's OpenAPI SDK for PHP",
     "type": "library",
     "keywords": [

+ 7 - 0
vendor/wechatpay/wechatpay/phpstan.v8.4.neon

@@ -0,0 +1,7 @@
+includes:
+	- phpstan.v8.2.neon
+parameters:
+	ignoreErrors:
+		-
+			message: "#^(?:Left|Right) side of && is always true#"
+			path: src/Crypto/Hash.php

+ 1 - 1
vendor/wechatpay/wechatpay/src/ClientDecoratorInterface.php

@@ -14,7 +14,7 @@ interface ClientDecoratorInterface
     /**
      * @var string - This library version
      */
-    public const VERSION = '1.4.6';
+    public const VERSION = '1.4.11';
 
     /**
      * @var string - The HTTP transfer `xml` based protocol

+ 9 - 2
vendor/wechatpay/wechatpay/src/ClientJsonTrait.php

@@ -63,7 +63,12 @@ trait ClientJsonTrait
      *
      * @return callable(RequestInterface)
      */
-    public static function signer(string $mchid, string $serial, $privateKey): callable
+    public static function signer(
+        string $mchid,
+        string $serial,
+        #[\SensitiveParameter]
+        $privateKey
+    ): callable
     {
         return static function (RequestInterface $request) use ($mchid, $serial, $privateKey): RequestInterface {
             $nonce = Formatter::nonce();
@@ -127,7 +132,7 @@ trait ClientJsonTrait
                 ), $request, $response);
             }
 
-            $isOverseas = 0 === strcasecmp($url, '/hk/v3/statements') && $response->hasHeader(WechatpayStatementSha1);
+            $isOverseas = (0 === strcasecmp($url, '/hk/v3/statements') || 0 === strcasecmp($url, '/v3/global/statements')) && $response->hasHeader(WechatpayStatementSha1);
 
             $verified = false;
             try {
@@ -161,6 +166,8 @@ trait ClientJsonTrait
      *
      * @see https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/fusion_wallet_ch/QuickPay/chapter8_5.shtml
      * @see https://pay.weixin.qq.com/wiki/doc/api/wxpay/en/fusion_wallet/QuickPay/chapter8_5.shtml
+     * @see https://pay.weixin.qq.com/wiki/doc/api_external/ch/apis/chapter3_1_6.shtml
+     * @see https://pay.weixin.qq.com/wiki/doc/api_external/en/apis/chapter3_1_6.shtml
      *
      * @param ResponseInterface $response - The response instance
      *

+ 19 - 4
vendor/wechatpay/wechatpay/src/ClientXmlTrait.php

@@ -5,6 +5,7 @@ namespace WeChatPay;
 use function strlen;
 use function sprintf;
 use function in_array;
+use function array_key_exists;
 
 use GuzzleHttp\Client;
 use GuzzleHttp\HandlerStack;
@@ -54,8 +55,6 @@ trait ClientXmlTrait
         '/payitil/report',
         '/risk/getpublickey',
         '/risk/getviolation',
-        '/sandboxnew/pay/downloadbill',
-        '/sandboxnew/pay/getsignkey',
         '/secapi/mch/submchmanage',
         '/xdc/apiv2getsignkey/sign/getsignkey',
     ];
@@ -74,7 +73,12 @@ trait ClientXmlTrait
      * @return callable(callable(RequestInterface, array))
      * @throws \WeChatPay\Exception\InvalidArgumentException
      */
-    public static function transformRequest(?string $mchid = null, string $secret = '', ?array $merchant = null): callable
+    public static function transformRequest(
+        ?string $mchid = null,
+        #[\SensitiveParameter]
+        string $secret = '',
+        ?array $merchant = null
+    ): callable
     {
         return static function (callable $handler) use ($mchid, $secret, $merchant): callable {
             return static function (RequestInterface $request, array $options = []) use ($handler, $mchid, $secret, $merchant): PromiseInterface {
@@ -112,7 +116,10 @@ trait ClientXmlTrait
      *
      * @return callable(callable(RequestInterface, array))
      */
-    public static function transformResponse(string $secret = ''): callable
+    public static function transformResponse(
+        #[\SensitiveParameter]
+        string $secret = ''
+    ): callable
     {
         return static function (callable $handler) use ($secret): callable {
             return static function (RequestInterface $request, array $options = []) use ($secret, $handler): PromiseInterface {
@@ -123,6 +130,14 @@ trait ClientXmlTrait
                 return $handler($request, $options)->then(static function(ResponseInterface $response) use ($secret) {
                     $result = Transformer::toArray(static::body($response));
 
+                    if (!(array_key_exists('return_code', $result) && Crypto\Hash::equals('SUCCESS', $result['return_code']))) {
+                        return Create::rejectionFor($response);
+                    }
+
+                    if (array_key_exists('result_code', $result) && !Crypto\Hash::equals('SUCCESS', $result['result_code'])) {
+                        return Create::rejectionFor($response);
+                    }
+
                     /** @var ?string $sign */
                     $sign = $result['sign'] ?? null;
                     $type = $sign && strlen($sign) === 64 ? Crypto\Hash::ALGO_HMAC_SHA256 : Crypto\Hash::ALGO_MD5;

+ 14 - 2
vendor/wechatpay/wechatpay/src/Crypto/AesEcb.php

@@ -19,7 +19,13 @@ class AesEcb implements AesInterface
     /**
      * @inheritDoc
      */
-    public static function encrypt(string $plaintext, string $key, string $iv = ''): string
+    public static function encrypt(
+        #[\SensitiveParameter]
+        string $plaintext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = ''
+    ): string
     {
         $ciphertext = openssl_encrypt($plaintext, static::ALGO_AES_256_ECB, $key, OPENSSL_RAW_DATA, $iv = '');
 
@@ -33,7 +39,13 @@ class AesEcb implements AesInterface
     /**
      * @inheritDoc
      */
-    public static function decrypt(string $ciphertext, string $key, string $iv = ''): string
+    public static function decrypt(
+        #[\SensitiveParameter]
+        string $ciphertext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = ''
+    ): string
     {
         $plaintext = openssl_decrypt(base64_decode($ciphertext), static::ALGO_AES_256_ECB, $key, OPENSSL_RAW_DATA, $iv = '');
 

+ 16 - 2
vendor/wechatpay/wechatpay/src/Crypto/AesGcm.php

@@ -43,7 +43,14 @@ class AesGcm implements AesInterface
      *
      * @return string - The base64-encoded ciphertext.
      */
-    public static function encrypt(string $plaintext, string $key, string $iv = '', string $aad = ''): string
+    public static function encrypt(
+        #[\SensitiveParameter]
+        string $plaintext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = '',
+        string $aad = ''
+    ): string
     {
         self::preCondition();
 
@@ -66,7 +73,14 @@ class AesGcm implements AesInterface
      *
      * @return string - The utf-8 plaintext.
      */
-    public static function decrypt(string $ciphertext, string $key, string $iv = '', string $aad = ''): string
+    public static function decrypt(
+        #[\SensitiveParameter]
+        string $ciphertext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = '',
+        string $aad = ''
+    ): string
     {
         self::preCondition();
 

+ 14 - 2
vendor/wechatpay/wechatpay/src/Crypto/AesInterface.php

@@ -43,7 +43,13 @@ interface AesInterface
      *
      * @return string - The base64-encoded ciphertext.
      */
-    public static function encrypt(string $plaintext, string $key, string $iv = ''): string;
+    public static function encrypt(
+        #[\SensitiveParameter]
+        string $plaintext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = ''
+    ): string;
 
     /**
      * Takes a base64 encoded string and decrypts it using a given key and iv.
@@ -54,5 +60,11 @@ interface AesInterface
      *
      * @return string - The utf-8 plaintext.
      */
-    public static function decrypt(string $ciphertext, string $key, string $iv = ''): string;
+    public static function decrypt(
+        #[\SensitiveParameter]
+        string $ciphertext,
+        #[\SensitiveParameter]
+        string $key,
+        string $iv = ''
+    ): string;
 }

+ 24 - 4
vendor/wechatpay/wechatpay/src/Crypto/Hash.php

@@ -40,7 +40,12 @@ class Hash
      *
      * @return string - The data signature
      */
-    public static function md5(string $thing, string $key = '', $agency = false): string
+    public static function md5(
+        string $thing,
+        #[\SensitiveParameter]
+        string $key = '',
+        $agency = false
+    ): string
     {
         $ctx = hash_init(ALGO_MD5);
 
@@ -58,7 +63,12 @@ class Hash
      *
      * @return string - The data signature
      */
-    public static function hmac(string $thing, string $key, string $algorithm = 'sha256'): string
+    public static function hmac(
+        string $thing,
+        #[\SensitiveParameter]
+        string $key,
+        string $algorithm = 'sha256'
+    ): string
     {
         $ctx = hash_init($algorithm, HASH_HMAC, $key);
 
@@ -75,7 +85,12 @@ class Hash
      *
      * @return bool - Returns true when the two are equal, false otherwise.
      */
-    public static function equals(string $known_string, ?string $user_string = null): bool
+    public static function equals(
+        #[\SensitiveParameter]
+        string $known_string,
+        #[\SensitiveParameter]
+        ?string $user_string = null
+    ): bool
     {
         return is_null($user_string) ? false : hash_equals($known_string, $user_string);
     }
@@ -89,7 +104,12 @@ class Hash
      *
      * @return ?string - The data signature in UPPERCASE.
      */
-    public static function sign(string $type, string $data, string $key): ?string
+    public static function sign(
+        string $type,
+        string $data,
+        #[\SensitiveParameter]
+        string $key
+    ): ?string
     {
         return array_key_exists($type, ALGO_DICTONARIES) ? strtoupper(static::{ALGO_DICTONARIES[$type]}($data, $key)) : null;
     }

+ 42 - 25
vendor/wechatpay/wechatpay/src/Crypto/Rsa.php

@@ -4,7 +4,6 @@ namespace WeChatPay\Crypto;
 
 use const OPENSSL_ALGO_SHA256;
 use const OPENSSL_PKCS1_OAEP_PADDING;
-use const OPENSSL_PKCS1_PADDING;
 use const PHP_URL_SCHEME;
 
 use function array_column;
@@ -108,7 +107,10 @@ class Rsa
      * @return \OpenSSLAsymmetricKey|resource|mixed
      * @throws UnexpectedValueException
      */
-    public static function fromPkcs8(string $thing)
+    public static function fromPkcs8(
+        #[\SensitiveParameter]
+        string $thing
+    )
     {
         return static::from(sprintf('private.pkcs8://%s', $thing), static::KEY_TYPE_PRIVATE);
     }
@@ -121,7 +123,11 @@ class Rsa
      * @return \OpenSSLAsymmetricKey|resource|mixed
      * @throws UnexpectedValueException
      */
-    public static function fromPkcs1(string $thing, string $type = self::KEY_TYPE_PRIVATE)
+    public static function fromPkcs1(
+        #[\SensitiveParameter]
+        string $thing,
+        string $type = self::KEY_TYPE_PRIVATE
+    )
     {
         return static::from(sprintf('%s://%s', $type === static::KEY_TYPE_PUBLIC ? 'public.pkcs1' : 'private.pkcs1', $thing), $type);
     }
@@ -155,7 +161,11 @@ class Rsa
      * @return \OpenSSLAsymmetricKey|resource|mixed
      * @throws UnexpectedValueException
      */
-    public static function from($thing, string $type = self::KEY_TYPE_PRIVATE)
+    public static function from(
+        #[\SensitiveParameter]
+        $thing,
+        string $type = self::KEY_TYPE_PRIVATE
+    )
     {
         $pkey = ($isPublic = $type === static::KEY_TYPE_PUBLIC)
             ? openssl_pkey_get_public(self::parse($thing, $type))
@@ -206,7 +216,11 @@ class Rsa
      * @param string $type - Either `self::KEY_TYPE_PUBLIC` or `self::KEY_TYPE_PRIVATE` string, default is `self::KEY_TYPE_PRIVATE`.
      * @return \OpenSSLAsymmetricKey|\OpenSSLCertificate|resource|array{string,string}|string|mixed
      */
-    private static function parse($thing, string $type = self::KEY_TYPE_PRIVATE)
+    private static function parse(
+        #[\SensitiveParameter]
+        $thing,
+        string $type = self::KEY_TYPE_PRIVATE
+    )
     {
         $src = $thing;
 
@@ -237,39 +251,35 @@ class Rsa
     }
 
     /**
-     * Check the RSA padding mode either `OPENSSL_PKCS1_PADDING` or `OPENSSL_PKCS1_OAEP_PADDING`.
+     * Check the padding mode whether or nor supported.
      *
-     * **Warning:**
-     *
-     * Decryption failures in the `RSA_PKCS1_PADDING` mode leak information which can potentially be used to mount a Bleichenbacher padding oracle attack.
-     * This is an inherent weakness in the PKCS #1 v1.5 padding design. Prefer `RSA_PKCS1_OAEP_PADDING`.
-     *
-     * @link https://www.openssl.org/docs/man1.1.1/man3/RSA_public_encrypt.html
-     *
-     * @param int $padding - The padding mode, only support `OPENSSL_PKCS1_PADDING` or `OPENSSL_PKCS1_OAEP_PADDING`, otherwise thrown `\UnexpectedValueException`.
+     * @param int $padding - The padding mode, only support `OPENSSL_PKCS1_PADDING`, otherwise thrown `\UnexpectedValueException`.
      *
      * @throws UnexpectedValueException
      */
     private static function paddingModeLimitedCheck(int $padding): void
     {
-        if (!($padding === OPENSSL_PKCS1_OAEP_PADDING || $padding === OPENSSL_PKCS1_PADDING)) {
-            throw new UnexpectedValueException(sprintf("Doesn't supported padding mode(%d), here only support OPENSSL_PKCS1_OAEP_PADDING or OPENSSL_PKCS1_PADDING.", $padding));
+        if ($padding !== OPENSSL_PKCS1_OAEP_PADDING) {
+            throw new UnexpectedValueException(sprintf('Here\'s only support the OPENSSL_PKCS1_OAEP_PADDING(4) mode, yours(%d).', $padding));
         }
     }
 
     /**
      * Encrypts text by the given `$publicKey` in the `$padding`(default is `OPENSSL_PKCS1_OAEP_PADDING`) mode.
      *
-     * Some of APIs were required the `$padding` mode as of `RSAES-PKCS1-v1_5` which is equal to the `OPENSSL_PKCS1_PADDING` constant, exposed it for this case.
-     *
      * @param string $plaintext - Cleartext to encode.
      * @param \OpenSSLAsymmetricKey|\OpenSSLCertificate|resource|string|mixed $publicKey - The public key.
-     * @param int $padding - One of OPENSSL_PKCS1_PADDING, OPENSSL_PKCS1_OAEP_PADDING, default is `OPENSSL_PKCS1_OAEP_PADDING`.
+     * @param int $padding - default is `OPENSSL_PKCS1_OAEP_PADDING`.
      *
      * @return string - The base64-encoded ciphertext.
      * @throws UnexpectedValueException
      */
-    public static function encrypt(string $plaintext, $publicKey, int $padding = OPENSSL_PKCS1_OAEP_PADDING): string
+    public static function encrypt(
+        #[\SensitiveParameter]
+        string $plaintext,
+        $publicKey,
+        int $padding = OPENSSL_PKCS1_OAEP_PADDING
+    ): string
     {
         self::paddingModeLimitedCheck($padding);
 
@@ -308,7 +318,11 @@ class Rsa
      * @return string - The base64-encoded signature.
      * @throws UnexpectedValueException
      */
-    public static function sign(string $message, $privateKey): string
+    public static function sign(
+        string $message,
+        #[\SensitiveParameter]
+        $privateKey
+    ): string
     {
         if (!openssl_sign($message, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
             throw new UnexpectedValueException('Signing the input $message failed, please checking your $privateKey whether or nor correct.');
@@ -320,16 +334,19 @@ class Rsa
     /**
      * Decrypts base64 encoded string with `$privateKey` in the `$padding`(default is `OPENSSL_PKCS1_OAEP_PADDING`) mode.
      *
-     * Some of APIs were required the `$padding` mode as of `RSAES-PKCS1-v1_5` which is equal to the `OPENSSL_PKCS1_PADDING` constant, exposed it for this case.
-     *
      * @param string $ciphertext - Was previously encrypted string using the corresponding public key.
      * @param \OpenSSLAsymmetricKey|\OpenSSLCertificate|resource|string|array{string,string}|mixed $privateKey - The private key.
-     * @param int $padding - One of OPENSSL_PKCS1_PADDING, OPENSSL_PKCS1_OAEP_PADDING, default is `OPENSSL_PKCS1_OAEP_PADDING`.
+     * @param int $padding - default is `OPENSSL_PKCS1_OAEP_PADDING`.
      *
      * @return string - The utf-8 plaintext.
      * @throws UnexpectedValueException
      */
-    public static function decrypt(string $ciphertext, $privateKey, int $padding = OPENSSL_PKCS1_OAEP_PADDING): string
+    public static function decrypt(
+        string $ciphertext,
+        #[\SensitiveParameter]
+        $privateKey,
+        int $padding = OPENSSL_PKCS1_OAEP_PADDING
+    ): string
     {
         self::paddingModeLimitedCheck($padding);
 

+ 9 - 3
vendor/wechatpay/wechatpay/src/Util/PemUtil.php

@@ -27,7 +27,10 @@ class PemUtil
      *
      * @return \OpenSSLAsymmetricKey|resource|mixed
      */
-    public static function loadPrivateKey(string $filepath)
+    public static function loadPrivateKey(
+        #[\SensitiveParameter]
+        string $filepath
+    )
     {
         return Rsa::from((false === strpos($filepath, self::LOCAL_FILE_PROTOCOL) ? self::LOCAL_FILE_PROTOCOL : '') . $filepath);
     }
@@ -40,7 +43,10 @@ class PemUtil
      *
      * @return \OpenSSLAsymmetricKey|resource|mixed
      */
-    public static function loadPrivateKeyFromString($content)
+    public static function loadPrivateKeyFromString(
+        #[\SensitiveParameter]
+        $content
+    )
     {
         return Rsa::from($content);
     }
@@ -90,6 +96,6 @@ class PemUtil
             throw new UnexpectedValueException('Read the $certificate failed, please check it whether or nor correct');
         }
 
-        return strtoupper($info['serialNumberHex'] ?? '');
+        return strtoupper($info['serialNumberHex']);
     }
 }