|
@@ -76,7 +76,6 @@ class NoPayService extends BaseService
|
|
|
public static function signature(array $params, string $key): string
|
|
public static function signature(array $params, string $key): string
|
|
|
{
|
|
{
|
|
|
unset($params['sign']);
|
|
unset($params['sign']);
|
|
|
- $params['version'] = $params['version'] ?? 'v1';
|
|
|
|
|
$params = array_filter($params, static function ($value) {
|
|
$params = array_filter($params, static function ($value) {
|
|
|
return $value !== null && $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'));
|
|
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
|
|
private static function signedData(array $data, string $key): array
|
|
|
{
|
|
{
|
|
|
$data['sign'] = self::signature($data, $key);
|
|
$data['sign'] = self::signature($data, $key);
|
|
@@ -159,7 +168,42 @@ class NoPayService extends BaseService
|
|
|
return false;
|
|
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
|
|
private static function post(string $url, array $data, string $merchantId): array
|