diff --git a/app/Http/Controllers/pay/WalletPaymentController.php b/app/Http/Controllers/pay/WalletPaymentController.php index dcd7994..8d6150d 100644 --- a/app/Http/Controllers/pay/WalletPaymentController.php +++ b/app/Http/Controllers/pay/WalletPaymentController.php @@ -105,15 +105,33 @@ class WalletPaymentController extends Controller throw new UnprocessableEntityHttpException('پرداخت آنلاین فعال نیست'); } - $payload = array_filter([ - 'status' => $request->input('status'), - 'reference_id' => $request->input('reference_id'), - 'session_id' => $request->input('session_id'), - 'amount' => $request->input('amount'), - 'track_number' => $request->input('track_number'), - 'timestamp' => $request->input('timestamp'), - 'signature' => $request->input('signature'), - ], static fn ($v) => $v !== null && $v !== ''); + $payload = []; + foreach ([ + 'status', + 'reference_id', + 'session_id', + 'amount', + 'track_number', + 'timestamp', + 'signature', + ] as $key) { + if (!$request->has($key)) { + continue; + } + $value = $request->input($key); + if ($value === null || is_array($value)) { + continue; + } + // track_number خالی هم ممکن است در امضا باشد + $payload[$key] = (string) $value; + } + + if (($payload['signature'] ?? '') === '' || ($payload['reference_id'] ?? '') === '') { + return response()->json([ + 'ok' => false, + 'message' => 'پارامترهای بازگشت ناقص است', + ], 422); + } $synthetic = Request::create('/', 'GET', $payload); $result = $gateway->handleReturn($synthetic); diff --git a/app/Services/Payment/Gateways/MontifyPartnerGateway.php b/app/Services/Payment/Gateways/MontifyPartnerGateway.php index 33b85b6..1b3df54 100644 --- a/app/Services/Payment/Gateways/MontifyPartnerGateway.php +++ b/app/Services/Payment/Gateways/MontifyPartnerGateway.php @@ -157,10 +157,16 @@ class MontifyPartnerGateway implements WalletPaymentGatewayInterface public function handleReturn(Request $request): array { - $query = $request->query(); + // query() آبجکت ParameterBag است؛ برای HMAC باید آرایهٔ string باشد + $query = $this->normalizeReturnQuery($request->query()->all()); $signer = $this->signer(); if (!$signer->verifyReturnSignature($query)) { + \Log::warning('montify.return_invalid_signature', [ + 'keys' => array_keys($query), + 'reference_id' => $query['reference_id'] ?? null, + ]); + return ['ok' => false, 'withdraw' => null, 'http_status' => 401, 'message' => 'امضای نامعتبر']; } @@ -200,6 +206,31 @@ class MontifyPartnerGateway implements WalletPaymentGatewayInterface ]; } + /** + * پارامترهای برگشت Montify باید همگی string باشند (طبق مستند). + * + * @param array $query + * @return array + */ + private function normalizeReturnQuery(array $query): array + { + $normalized = []; + foreach ($query as $key => $value) { + if (!is_string($key) || $key === '') { + continue; + } + if (is_array($value)) { + continue; + } + if ($value === null) { + continue; + } + $normalized[$key] = (string) $value; + } + + return $normalized; + } + public function handleWebhook(Request $request): array { $body = $request->all(); diff --git a/app/Services/Payment/Support/MontifyHmacSigner.php b/app/Services/Payment/Support/MontifyHmacSigner.php index a7ffbd0..4236eb9 100644 --- a/app/Services/Payment/Support/MontifyHmacSigner.php +++ b/app/Services/Payment/Support/MontifyHmacSigner.php @@ -49,12 +49,22 @@ class MontifyHmacSigner public function verifyReturnSignature(array $query): bool { $signature = (string) ($query['signature'] ?? ''); - if ($signature === '') { + if ($signature === '' || !ctype_xdigit($signature)) { return false; } unset($query['signature']); - $expected = hash_hmac('sha256', $this->stableStringify($query), $this->clientSecret); + + // فقط اسکالرها — همه string طبق مستند پارتنر + $payload = []; + foreach ($query as $key => $value) { + if (!is_string($key) || is_array($value) || $value === null) { + continue; + } + $payload[$key] = (string) $value; + } + + $expected = hash_hmac('sha256', $this->stableStringify($payload), $this->clientSecret); return $this->hashEqualsHex($signature, $expected); }