src/EventSubscriber/Payment/OrderPaymentCompletedSubscriber.php line 38

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\EventSubscriber\Payment;
  4. use App\Entity\Geographical\Address;
  5. use App\Entity\Payment\Payment;
  6. use App\Message\CompleteOrderRequest;
  7. use App\OrderStates;
  8. use App\Processor\Order\CompleteOrderProcessorInterface;
  9. use App\Repository\CustomerRepository;
  10. use App\Repository\Order\OrderRepository;
  11. use ApiPlatform\Api\IriConverterInterface;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Symfony\Component\Workflow\Event\Event;
  15. use Symfony\Component\Workflow\Registry;
  16. use Webmozart\Assert\Assert;
  17. /**
  18.  * When a Stripe payment completes for an order (direct or complement),
  19.  * transition the order to in_production and debit credits for complement.
  20.  * If the payment was created via direct-intent (no order yet), create the order from payload first.
  21.  */
  22. final class OrderPaymentCompletedSubscriber implements EventSubscriberInterface
  23. {
  24.     public function __construct(
  25.         private Registry $workflowRegistry,
  26.         private OrderRepository $orderRepository,
  27.         private CustomerRepository $customerRepository,
  28.         private CompleteOrderProcessorInterface $completeOrderProcessor,
  29.         private IriConverterInterface $iriConverter,
  30.         private EntityManagerInterface $entityManager,
  31.     ) {
  32.     }
  33.     public function onPaymentCompleted(Event $event): void
  34.     {
  35.         /** @var Payment $payment */
  36.         $payment $event->getSubject();
  37.         Assert::isInstanceOf($paymentPayment::class);
  38.         if (!$payment->isOrderPayment()) {
  39.             return;
  40.         }
  41.         $order $payment->getOrder();
  42.         if ($order === null) {
  43.             $details $payment->getDetails();
  44.             $payload $details['order_payload'] ?? null;
  45.             if (!\is_array($payload)) {
  46.                 return;
  47.             }
  48.             $address $this->iriConverter->getResourceFromIri((string) $payload['address']);
  49.             Assert::isInstanceOf($addressAddress::class);
  50.             $completeOrderRequest = new CompleteOrderRequest(
  51.                 name$payload['name'] ?? '',
  52.                 address$address,
  53.                 quantity$payload['quantity'] ?? 1,
  54.                 photosCount$payload['photosCount'] ?? 0,
  55.                 mattePaper$payload['mattePaper'] ?? false,
  56.                 withFrame$payload['withFrame'] ?? false,
  57.                 isFromCode$payload['isFromCode'] ?? false,
  58.                 paymentMode$payload['paymentMode'] ?? 'direct',
  59.                 sharedEventCode: isset($payload['sharedEventCode']) ? (string) $payload['sharedEventCode'] : null,
  60.             );
  61.             $order $this->completeOrderProcessor->processOrderAfterPayment($completeOrderRequest);
  62.             $payment->setOrder($order);
  63.             $this->entityManager->flush();
  64.         }
  65.         if ($payment->getPaymentType() === 'order_complement' && $payment->getCreditsToDebit() > 0) {
  66.             $customer $order->getCustomer();
  67.             if ($customer !== null) {
  68.                 $customer->setCredits($customer->getCredits() - $payment->getCreditsToDebit());
  69.                 $this->customerRepository->add($customer);
  70.             }
  71.         }
  72.         $orderWorkflow $this->workflowRegistry->get($order'order');
  73.         if ($orderWorkflow->can($orderOrderStates::TRANSITION_PAYMENT_CONFIRMED)) {
  74.             $orderWorkflow->apply($orderOrderStates::TRANSITION_PAYMENT_CONFIRMED);
  75.             $this->orderRepository->add($order);
  76.         }
  77.     }
  78.     public static function getSubscribedEvents(): array
  79.     {
  80.         return [
  81.             'workflow.payment.enter.completed' => ['onPaymentCompleted', -10], // after PaymentAddCreditsSubscriber
  82.         ];
  83.     }
  84. }