feat(payment): update Mellat gateway implementation and enhance security checks

This commit is contained in:
hamed
2026-07-02 17:51:50 +03:30
parent e487f7437a
commit 6bb47d343d
3 changed files with 51 additions and 18 deletions
+18 -2
View File
@@ -3,7 +3,6 @@
namespace App\Payment\Service;
use App\Appointment\Entity\Appointment;
use App\Appointment\Repository\AppointmentRepository;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Repository\DoctorRepository;
use App\Payment\Entity\Payment;
@@ -61,8 +60,10 @@ final class PaymentManager
return false;
}
// درگاه ملت orderId عددی (long) می‌خواهد؛ id عددیِ Payment را می‌فرستیم.
// جستجوی پرداخت در callback از طریق query `order_id` (رشتهٔ ORD-…) انجام می‌شود.
$callbackUrl = $this->callbackUrl($payment);
$result = $gateway->initiate($payment->getAmountRials(), $payment->getOrderId(), $callbackUrl);
$result = $gateway->initiate($payment->getAmountRials(), (string) $payment->getId(), $callbackUrl);
if (!$result->success) {
if (!$testMode) {
@@ -102,6 +103,21 @@ final class PaymentManager
$payment->setCallbackIp($clientIp);
// چک امنیتی اجباری مستند: مقادیر بازگشتی باید با مقادیر مرحلهٔ Pay همین
// پرداخت بخوانند (ضد parameter tampering). فقط وقتی درگاه این فیلدها را
// برمی‌گرداند اعمال می‌شود (ملت: RefId + SaleOrderId؛ سپ آن‌ها را ندارد).
$token = $payment->getGatewayToken();
$refIdMismatch = $token !== null && isset($callbackData['RefId'])
&& !hash_equals($token, (string) $callbackData['RefId']);
$orderMismatch = isset($callbackData['SaleOrderId'])
&& (string) $callbackData['SaleOrderId'] !== (string) $payment->getId();
if ($refIdMismatch || $orderMismatch) {
$payment->setStatus(Payment::STATUS_FAILED);
$this->em->persist($payment);
$this->log($payment, PaymentLog::ACTION_VERIFY, 'failed', null, $clientIp, ['reason' => 'tampering']);
return $payment;
}
$gateway = $this->gateways->resolve($gatewayName);
$result = $gateway?->verify($callbackData);