feat(payment): implement PaymentManager for handling payment logic and callbacks

- Refactor PaymentController to delegate payment processing to PaymentManager.
- Add findByOrderIdForUpdate method in PaymentRepository for pessimistic locking.
- Create PaymentLog entity and repository for auditing payment actions.
- Implement startGatewayHandoff and processCallback methods in PaymentManager.
- Introduce transaction handling and logging for payment verification.
- Update payment flow to ensure idempotency and prevent race conditions.
- Enhance security by logging sensitive actions without exposing credentials.
- Update database schema with migration for payment_logs table.
- Document changes in payment flow architecture.
This commit is contained in:
hamed
2026-07-02 15:36:08 +03:30
parent ca71c49451
commit c247ac2c80
12 changed files with 761 additions and 378 deletions
@@ -59,6 +59,19 @@ class PaymentRepository extends ServiceEntityRepository
return $this->findOneBy(['referenceId' => $referenceId]);
}
/**
* قفل بدبینانه روی ردیف پرداخت (باید داخل یک transaction فعال صدا زده شود).
* برای جلوگیری از verify هم‌زمانِ دو callback (race / double-verify).
*/
public function findByOrderIdForUpdate(string $orderId): ?Payment
{
return $this->createQueryBuilder('p')
->where('p.orderId = :o')->setParameter('o', $orderId)
->getQuery()
->setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)
->getOneOrNullResult();
}
public function findPendingByAppointment(Appointment $appointment): ?Payment
{
return $this->findOneBy([