* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ namespace PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Refund\EventSubscriber; use PrestaShop\Module\PrestashopCheckout\CommandBus\CommandBusInterface; use PrestaShop\Module\PrestashopCheckout\Order\Command\UpdateOrderStatusCommand; use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentRefundedQuery; use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentRefundedQueryResult; use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper; use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Refund\Event\PayPalCaptureRefundedEvent; use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Refund\Event\PayPalRefundEvent; use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalOrderProvider; use Ps_checkout; use Psr\SimpleCache\CacheInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class PayPalRefundEventSubscriber implements EventSubscriberInterface { /** * @var Ps_checkout */ private $module; /** * @var CommandBusInterface */ private $commandBus; /** * @var CacheInterface */ private $orderPayPalCache; /** * @var OrderStateMapper */ private $orderStateMapper; /** * @var PayPalOrderProvider */ private $orderProvider; public function __construct( Ps_checkout $module, CacheInterface $orderPayPalCache, OrderStateMapper $orderStateMapper, PayPalOrderProvider $orderProvider ) { $this->module = $module; $this->commandBus = $this->module->getService('ps_checkout.bus.command'); $this->orderPayPalCache = $orderPayPalCache; $this->orderStateMapper = $orderStateMapper; $this->orderProvider = $orderProvider; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ PayPalCaptureRefundedEvent::class => [ ['setPaymentRefundedOrderStatus'], ['updateCache'], ], ]; } public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) { try { /** @var GetOrderForPaymentRefundedQueryResult $order */ $order = $this->commandBus->handle(new GetOrderForPaymentRefundedQuery($event->getPayPalOrderId()->getValue())); } catch (OrderNotFoundException $exception) { return; } if ($this->orderPayPalCache->has($event->getPayPalOrderId()->getValue())) { $this->orderPayPalCache->delete($event->getPayPalOrderId()->getValue()); } if (!$order->hasBeenPaid() || $order->hasBeenTotallyRefund()) { return; } $orderPayPal = $this->orderProvider->getById($event->getPayPalOrderId()->getValue()); if (empty($orderPayPal['purchase_units'][0]['payments']['refunds'])) { return; } $totalRefunded = array_reduce($orderPayPal['purchase_units'][0]['payments']['refunds'], function ($totalRefunded, $refund) { return $totalRefunded + (float) $refund['amount']['value']; }); $orderFullyRefunded = (float) $order->getTotalAmount() <= (float) $totalRefunded; $orderStateRefunded = $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED); $orderStatePartiallyRefunded = $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED); $newOrderState = $orderFullyRefunded ? $orderStateRefunded : $orderStatePartiallyRefunded; if ($order->hasBeenPartiallyRefund() && $newOrderState === $orderStatePartiallyRefunded) { return; } if ($order->getCurrentStateId()->getValue() === $newOrderState) { return; } $this->commandBus->handle( new UpdateOrderStatusCommand( $order->getOrderId()->getValue(), $newOrderState ) ); } public function updateCache(PayPalRefundEvent $event) { if ($this->orderPayPalCache->has($event->getPayPalOrderId()->getValue())) { $this->orderPayPalCache->delete($event->getPayPalOrderId()->getValue()); } } }