fix(payment): skip Shaparak IP allowlist for browser-redirect gateways (mellat/sep)

Mellat/SEP return the result via a user-browser redirect (POST/GET), so the
received IP is the user's, not Shaparak's. The IP allowlist therefore rejected
every real callback — including user cancel — with 'forbidden'. Security is
provided by the tamper check (RefId/SaleOrderId) and server-side verify.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-02 20:33:35 +03:30
co-authored by Claude Opus 4.8
parent 27b2d66afa
commit 10be1728ff
2 changed files with 8 additions and 5 deletions
+6 -3
View File
@@ -285,9 +285,12 @@ class PaymentController extends BaseController
public function callback(string $gateway, Request $request): \Symfony\Component\HttpFoundation\Response
{
$clientIp = $request->getClientIp() ?? '';
// در حالت تست یا sandbox ملت، callback از IPی خارج از رنج شاپرک می‌آید؛ IP-check رد می‌شود.
$bypassIp = $this->gateways->isTestMode()
|| ($gateway === 'mellat' && $this->gateways->isMellatSandbox());
// درگاه‌های ملت و سپ نتیجه را با ریدایرکتِ مرورگرِ کاربر (POST/GET) برمی‌گردانند،
// نه server-to-server؛ پس IP دریافتی، IPِ کاربر است و allowlist شاپرک اعمال نمی‌شود
// (در غیر این صورت هر callback واقعی — از جمله «لغو» — رد می‌شد). امنیت از طریق چک
// ضد-دستکاری (RefId/SaleOrderId) و verify سمت بانک در PaymentManager تأمین می‌شود.
$browserRedirectGateways = ['mellat', 'sep'];
$bypassIp = $this->gateways->isTestMode() || in_array($gateway, $browserRedirectGateways, true);
if (!$bypassIp && !$this->isAllowedCallbackIp($clientIp)) {
return $this->renderPaymentResult('forbidden');
}