Ver Fonte

fix(wechatpay): 修复微信支付通知验签失败问题

- 调整代码格式,增加空行提高可读性
- 修复签名验证逻辑中的条件判断错误
- 启用签名无效时的异常抛出机制
- 更新测试用例,使用真实请求数据进行验证
- 移除支付查询中的临时处理逻辑
- 完善日志记录,确保签名验证失败时能准确追踪问题
runphp há 3 meses atrás
pai
commit
b338d8e219

+ 0 - 1
src/PaymentProvider.php

@@ -118,7 +118,6 @@ class PaymentProvider implements PaymentProviderInterface
             if ($payment->isEmpty()) {
                 throw new \RuntimeException('订单不存在或已结束');
             }
-            // 验签有问题,暂时叫个支付查询处理 todo 待完善
             $queryResult = $this->query($payment['id']);
             return new PaymentNotifyResult(
                 orderNo: $queryResult->orderNo,

+ 5 - 6
src/Service/NotifyService.php

@@ -1,5 +1,6 @@
 <?php
 declare(strict_types=1);
+
 namespace SixShop\WechatPay\Service;
 
 use SixShop\WechatPay\Config;
@@ -19,28 +20,26 @@ class NotifyService
      * @param array $headers 请求头
      * @param string $inBody 请求体
      */
-    public function transactionSuccess(array $headers, string $inBody):array
+    public function transactionSuccess(array $headers, string $inBody): array
     {
         $signature = $headers['Wechatpay-Signature'] ?? '';// 请根据实际情况获取
         $timestamp = $headers['Wechatpay-Timestamp'] ?? '';// 请根据实际情况获取
         $serial = $headers['Wechatpay-Serial'] ?? ''; // 请根据实际情况获取
         $nonce = $headers['Wechatpay-Nonce'] ?? ''; // 请根据实际情况获取
-        
+
         $apiv3Key = $this->config->api_v3_key;
-        $platformPublicKeyInstance = str_starts_with($serial,'PUB_KEY_ID_')?$this->config->public_key:$this->config->platform_cert;
+        $platformPublicKeyInstance = str_starts_with($serial, 'PUB_KEY_ID_') ? $this->config->public_key : $this->config->platform_cert;
 
         $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$timestamp);
         if (!$timeOffsetStatus) {
             throw new \RuntimeException('The timestamp is out of range.');
         }
         $verifiedStatus = Rsa::verify(
-        // 构造验签名串
             Formatter::joinedByLineFeed($timestamp, $nonce, $inBody),
             $signature,
             $platformPublicKeyInstance
         );
         if (!$verifiedStatus) {
-            // TODO
             Log::warning('The signature is invalid. timestamp={timestamp} nonce={nonce} inBody={inBody} signature={signature} serial={serial}', [
                 'timestamp' => $timestamp,
                 'nonce' => $nonce,
@@ -48,7 +47,7 @@ class NotifyService
                 'signature' => $signature,
                 'serial' => $serial,
             ]);
-            //throw new \RuntimeException('The signature is invalid.');
+            throw new \RuntimeException('The signature is invalid.');
         }
         // 转换通知的JSON文本消息为PHP Array数组
         $inBodyArray = (array)json_decode($inBody, true);

+ 4 - 7
tests/Service/NotifyServiceTest.php

@@ -16,12 +16,9 @@ class NotifyServiceTest extends TestCase
     #[Test]
     public function transactionSuccess()
     {
-        $result = $this->notifyService->transactionSuccess([
-            'Wechatpay-Signature' => 'VmF2yqkm1dscjE/6M6KcQCG27HnRC7v+DQ4LXFTszRTR/q+0uEVso1D113QmUROcH5ATIgYwHii7IHWDXt4nk49IrYJ2PY/7g1bdt5HnXEI8IZeTyBHvaJzntH42rMvK+W0B1Lo0/VoHz9RXGbwCtBR4rmsYItyey/NTT0Q4EYLVSIWvQML9noLPUTwGm5y+YSAeK3vfDgVCMhTK01GB7UjJGm5ZA0XYidTSqD776ZRyTtEetkcPlTDcnagQjBa1w6KpRVjqo5jrdH2ShCqHewsbfC4wl+Mni1C39eDJ8Rsy6eKUh069cLIgFNWAb3rD694NFcNko5fJKglkRfQ6iw==',
-            'Wechatpay-Timestamp' => '1766159859',
-            'Wechatpay-Nonce' => 'f02OdZsxJPJ8IckupX0Z2j5dXqKyjBRC',
-            'Wechatpay-Serial' => 'PUB_KEY_ID_',
-        ],inBody: '{"id":"7afdf385-ce06-5d4d-a249-8a29e67cfd5d","create_time":"2025-12-19T20:57:16+08:00","resource_type":"encrypt-resource","event_type":"REFUND.SUCCESS","summary":"\u9000\u6b3e\u6210\u529f","resource":{"original_type":"refund","algorithm":"AEAD_AES_256_GCM","ciphertext":"\/ZfT5bua\/5qfyMktCV0s+Bq4yRF7XaNpLxaYxkPC6YAOF6VxJKiNpiNsvyvrGfm7Cpf2ApC3M3BoRIsELrGCzUggfybuopxiReMOE0o6UhaC0feZNwPhhgmIG8TgxcC58P5KPG75mHt5AlAfrnxFS88nxFgFW1B3PsSwIuSSxdXQGPv1oocC08FEAIj4bJ9ruXLTURJNvr+KVC+PlzBtGR8EKbAS20OytUx9JRZNs0ugccZvurc1lSdEvLc8O0uVA5f8MYFCx5gGHDt8KYjMknUnZSS5uI\/ObwQshfpD5jk77IMOBAAVXHpd0Il1IzGEi9i88BRWTdH2Ekl4JjyNWT0QqoeWsPw0DXyoRRDkBocpy8YOj4BK9SHgLc7R2Vn11UmlYKLzpVpXPWjBcEFLhHxFggjwuw68R4PWKZNVQrgvsZGT3hPQYbMJBH1o2iMY22y\/UBED03QlE0seNf1RMsSREs3rNVjotPHUdIBtHoae6YrfQ1sWKVhKMoingYpF5RZd4gXVhumQD\/OzdYkSysqM","associated_data":"refund","nonce":"2zDGvTscnbA2"}}');
-        dump($result);
+        $header = '{"Wechatpay-Timestamp":"1766164013","Wechatpay-Signature":"J+PdOHvlcocaZMig0oaLrQluQ2Rn176+VDKsjqS8C8E+v\/lEH2UhowO1IyasGvb934LBeXyDWtsbDlY7W8JuztdXKtmJi\/0yhhW1L3raqbjISvNEAQiW\/a1O3w8YLsB3\/znlYATFkTR6Pi1GwF8jmlHs7vvadIlkPrtA8OXT189PBu3mMDZWPhUXkoCy\/6gKcL35BHOI0MAU79cdO6C4fqRL+YoMo+ETHkhnTm4R5kFLQIh9qrtmv2bBCNcgk5yBqPKzDMNnLYZnT6tO0W9KbXG038Zd7cAAECkAgDnlixbLeTfeVzeft4HeStCl0klB1aD\/9sLbsEU7JwOAQpwDlA==","Wechatpay-Serial":"PUB_KEY_ID_0117289218142025100700211947000800","Content-Type":"application\/json","Wechatpay-Nonce":"7H8olXNudQOnwtMhZDbEaXXWZe13CSp1"}';
+        $inBody = '{"id":"25279e63-c260-5eaa-b55d-2141f4454dce","create_time":"2025-12-19T19:32:27+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"支付成功","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"zNt4q12Jw2kF/8yb9JwggYtHBNLtCZaFmGMQpRHCAc73rnp90ygZSoghgxCffYoMGgqgAt7QXanINMDIFkk8EfGbKaAZn0QGrtUdcdbjlhWcRpgKylRITjsq9slvTPR/S5Wk+eup1QDp/MMRBHPSncuv2kV7Vp4PVSj/jdn3KKutk8so0VzQQMIMa08GPlPasu2A5sngsXlernPGxYfyNdwVqPeL5Yi1QiNuzZqPqXSbMeNqed5fE8wIBHOzyh4i4i57Zg5Gsf9sPL/nqHy8nY7mqmlr90leTA8wunbKVPoDvU/Rk0lC8lunzkrMiL+X0PtZZKe7lO1BLzcbJxC4GGYaxbhkcP7iTRlJwUmjPxvV0ZgMHV2I+dDccMWG6MKq1Onp00lzUMB/VUHtJVNcSTSHid4I5Wc7RkFZFJzYXseqhKqbGSs8EkIRcI4H2VoF4njDnlrBOb1hlzmtDJd7DhaxHjBsD84enVAZ0V3OQVvFnC3VqErki/mJhU60Q5QoAhr1ap3RZ6xMWEgDXMTIr/9FtM8jYKHUBu8FURY8Kxf9P1/xuUTDcds74ktWeGHXrhVcJdduHOzVvGJPyXYjhQ==","associated_data":"transaction","nonce":"Tp6yg5SshjL3"}}';
+        $result = $this->notifyService->transactionSuccess(json_decode($header,true), inBody: $inBody);
+        dump(json_decode($inBody));
     }
 }