doge преди 22 часа
родител
ревизия
27d47c9ac1
променени са 3 файла, в които са добавени 49 реда и са изтрити 2 реда
  1. 46 2
      app/Services/Payment/NoPayService.php
  2. 2 0
      app/Services/PaymentOrderService.php
  3. 1 0
      tests/Unit/NoPayServiceTest.php

+ 46 - 2
app/Services/Payment/NoPayService.php

@@ -76,7 +76,6 @@ class NoPayService extends BaseService
     public static function signature(array $params, string $key): string
     {
         unset($params['sign']);
-        $params['version'] = $params['version'] ?? 'v1';
         $params = array_filter($params, static function ($value) {
             return $value !== null && $value !== '';
         });
@@ -147,6 +146,16 @@ class NoPayService extends BaseService
         return self::verifyNotify($params, self::getWithdrawMerchantId(), (string)config('app.no_pay_withdraw_key'));
     }
 
+    public static function depositNotifySignatureDiagnostics(array $params): array
+    {
+        return self::signatureDiagnostics($params, (string)config('app.no_pay_deposit_key'));
+    }
+
+    public static function withdrawNotifySignatureDiagnostics(array $params): array
+    {
+        return self::signatureDiagnostics($params, (string)config('app.no_pay_withdraw_key'));
+    }
+
     private static function signedData(array $data, string $key): array
     {
         $data['sign'] = self::signature($data, $key);
@@ -159,7 +168,42 @@ class NoPayService extends BaseService
             return false;
         }
 
-        return hash_equals(self::signature($params, $key), strtolower((string)$params['sign']));
+        $receivedSign = strtolower((string)$params['sign']);
+        foreach (self::signatureCandidates($params, $key) as $candidate) {
+            if (hash_equals($candidate, $receivedSign)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static function signatureCandidates(array $params, string $key): array
+    {
+        $candidates = [self::signature($params, $key)];
+
+        // Some NO environments sign callbacks with the implicit default version
+        // without including the version field in the callback payload.
+        if (!isset($params['version'])) {
+            $params['version'] = 'v1';
+            $candidates[] = self::signature($params, $key);
+        }
+
+        return array_values(array_unique($candidates));
+    }
+
+    private static function signatureDiagnostics(array $params, string $key): array
+    {
+        $fields = $params;
+        unset($fields['sign']);
+
+        return [
+            'received_sign' => strtolower((string)($params['sign'] ?? '')),
+            'calculated_signs' => self::signatureCandidates($params, $key),
+            'signing_fields' => array_keys(array_filter($fields, static function ($value) {
+                return $value !== null && $value !== '';
+            })),
+        ];
     }
 
     private static function post(string $url, array $data, string $merchantId): array

+ 2 - 0
app/Services/PaymentOrderService.php

@@ -409,6 +409,7 @@ class PaymentOrderService extends BaseService
                 Log::error('NO钱包充值回调验签失败', [
                     'merchant_order_no' => $params['merchantOrderNo'] ?? '',
                     'app_id' => $params['appId'] ?? '',
+                    'signature' => NoPayService::depositNotifySignatureDiagnostics($params),
                 ]);
                 return false;
             }
@@ -963,6 +964,7 @@ class PaymentOrderService extends BaseService
                 Log::error('NO钱包提现回调验签失败', [
                     'merchant_order_no' => $params['merchantOrderNo'] ?? '',
                     'app_id' => $params['appId'] ?? '',
+                    'signature' => NoPayService::withdrawNotifySignatureDiagnostics($params),
                 ]);
                 return false;
             }

+ 1 - 0
tests/Unit/NoPayServiceTest.php

@@ -17,6 +17,7 @@ class NoPayServiceTest extends TestCase
             'notifyUrl' => 'www.http://weihao.com',
             'paymentMethod' => 12,
             'timestamp' => 1698043692,
+            'version' => 'v1',
         ], 'CZKb4DB0WNHx5K3ajvcVCeH3ykBCuDIS');
 
         $this->assertSame(