diff --git a/commerce_vipps.services.yml b/commerce_vipps.services.yml index ab22dc0..1bc5c1a 100644 --- a/commerce_vipps.services.yml +++ b/commerce_vipps.services.yml @@ -2,6 +2,10 @@ services: commerce_vipps.manager: class: Drupal\commerce_vipps\VippsManager arguments: ['@http_client'] + logger.channel.commerce_vipps: + class: Drupal\Core\Logger\LoggerChannel + factory: logger.factory:get + arguments: ['commerce_vipps'] commerce_vipps.chain_order_id_resolver: class: Drupal\commerce_vipps\Resolver\ChainOrderIdResolver tags: @@ -30,10 +34,15 @@ services: - { name: event_subscriber } commerce_vipps.commerce_shipping_subscriber: class: Drupal\commerce_vipps\EventSubscriber\CommerceShippingSubscriber - arguments: ['@entity_type.manager', '@commerce_shipping.packer_manager'] + arguments: ['@entity_type.manager', '@commerce_shipping.packer_manager', '@commerce_shipping.shipment_order_processor'] abstract: true tags: - { name: event_subscriber } + commerce_vipps.commerce_order_subscriber: + class: Drupal\commerce_vipps\EventSubscriber\CommerceOrderSubscriber + arguments: ['@entity_type.manager', '@commerce_vipps.manager', '@event_dispatcher', '@logger.channel.commerce_vipps'] + tags: + - { name: event_subscriber } commerce_vipps.return_from_vipps_express_subscriber: class: Drupal\commerce_vipps\EventSubscriber\ReturnFromVippsExpressSubscriber arguments: ['@entity_type.manager'] diff --git a/src/EventSubscriber/CommerceOrderSubscriber.php b/src/EventSubscriber/CommerceOrderSubscriber.php new file mode 100644 index 0000000..5dd8f4f --- /dev/null +++ b/src/EventSubscriber/CommerceOrderSubscriber.php @@ -0,0 +1,94 @@ +entityTypeManager = $entityTypeManager; + $this->vippsManager = $vippsManager; + $this->eventDispatcher = $eventDispatcher; + $this->logger = $logger; + } + + /** + * Sets the data collected by VippsExpress back on Order. + * + * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event + * The transition event. + */ + public function updateOrder(WorkflowTransitionEvent $event) { + /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ + $order = $event->getEntity(); + $remote_id = $order->getData('vipps_current_transaction'); + if (!$remote_id) { + // Could be for example another payment method? + return; + } + $payment_storage = $this->entityTypeManager->getStorage('commerce_payment'); + $matching_payments = $payment_storage->loadByProperties(['remote_id' => $remote_id, 'order_id' => $order->id()]); + if (count($matching_payments) !== 1) { + $this->logger->critical('More than one payment found. Data sync from Vipps to Commerce aborted.'); + return; + } + /** @var \Drupal\commerce_payment\Entity\PaymentInterface $matching_payment */ + $matching_payment = reset($matching_payments); + $payment_manager = $this->vippsManager->getPaymentManager($matching_payment->getPaymentGateway()->getPlugin()); + + // Get payment details. + $details = $payment_manager->getPaymentDetails($remote_id); + + // Dispatch the event. + $e = new ReturnFromVippsExpressEvent($matching_payment, $order, $details); + $this->eventDispatcher->dispatch(VippsEvents::RETURN_FROM_VIPPS_EXPRESS, $e); + + // Save the payment in case it was modified. + $matching_payment->save(); + } + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + return [ + 'commerce_order.place.pre_transition' => ['updateOrder', 50], + ]; + } + +} diff --git a/src/EventSubscriber/CommerceShippingSubscriber.php b/src/EventSubscriber/CommerceShippingSubscriber.php index f31d94b..99e26c0 100644 --- a/src/EventSubscriber/CommerceShippingSubscriber.php +++ b/src/EventSubscriber/CommerceShippingSubscriber.php @@ -5,6 +5,7 @@ namespace Drupal\commerce_vipps\EventSubscriber; use Drupal\commerce_order\Adjustment; use Drupal\commerce_price\Price; use Drupal\commerce_shipping\PackerManagerInterface; +use Drupal\commerce_shipping\ShipmentOrderProcessor; use Drupal\commerce_vipps\Event\ReturnFromVippsExpressEvent; use Drupal\commerce_vipps\Event\VippsEvents; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -25,15 +26,22 @@ class CommerceShippingSubscriber implements EventSubscriberInterface { */ protected $packerManager; + /** + * @var \Drupal\commerce_shipping\ShipmentOrderProcessor + */ + protected $shipmentOrderProcessor; + /** * CommerceShippingSubscriber constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * @param \Drupal\commerce_shipping\PackerManagerInterface $packerManager + * @param \Drupal\commerce_shipping\ShipmentOrderProcessor */ - public function __construct(EntityTypeManagerInterface $entityTypeManager, PackerManagerInterface $packerManager) { + public function __construct(EntityTypeManagerInterface $entityTypeManager, PackerManagerInterface $packerManager, ShipmentOrderProcessor $shipmentOrderProcessor) { $this->entityTypeManager = $entityTypeManager; $this->packerManager = $packerManager; + $this->shipmentOrderProcessor = $shipmentOrderProcessor; } /** @@ -77,8 +85,11 @@ class CommerceShippingSubscriber implements EventSubscriberInterface { $shipment->setShippingMethodId($shipping_method_id); $shipment->setShippingProfile($profile); $shipment->setShippingService($shipping_service_id); + $shipment->setData('owned_by_packer', FALSE); $shipment->save(); $order->set('shipments', [$shipment]); + + $this->shipmentOrderProcessor->process($order); } /** diff --git a/src/EventSubscriber/ReturnFromVippsExpressSubscriber.php b/src/EventSubscriber/ReturnFromVippsExpressSubscriber.php index fa7198a..bdeaa64 100644 --- a/src/EventSubscriber/ReturnFromVippsExpressSubscriber.php +++ b/src/EventSubscriber/ReturnFromVippsExpressSubscriber.php @@ -65,7 +65,6 @@ class ReturnFromVippsExpressSubscriber implements EventSubscriberInterface { $details = $event->getDetails(); $payment = $event->getPayment(); $payment->setAmount($this->getAmendedPrice($details, $payment->getAmount())); - $event->setPayment($payment); } /** diff --git a/src/Plugin/Commerce/PaymentGateway/VippsExpress.php b/src/Plugin/Commerce/PaymentGateway/VippsExpress.php index 9b563a0..6f0470a 100644 --- a/src/Plugin/Commerce/PaymentGateway/VippsExpress.php +++ b/src/Plugin/Commerce/PaymentGateway/VippsExpress.php @@ -234,17 +234,22 @@ class VippsExpress extends Vipps implements SupportsAuthorizationsInterface, Sup $status = $payment_manager->getOrderStatus($remote_id); switch ($status->getTransactionInfo()->getStatus()) { case 'RESERVE': + $matching_payment->setAmount(new Price((string) ($status->getTransactionInfo()->getAmount() / 100), $matching_payment->getAmount()->getCurrencyCode())); $matching_payment->setState('authorization'); + $matching_payment->save(); break; case 'SALE': + $matching_payment->setAmount(new Price((string) ($status->getTransactionInfo()->getAmount() / 100), $matching_payment->getAmount()->getCurrencyCode())); $matching_payment->setState('completed'); + $matching_payment->save(); break; case 'RESERVE_FAILED': case 'SALE_FAILED': case 'CANCEL': case 'REJECTED': + case 'INITIATE': // @todo: There is no corresponding state in payment workflow but it's // still better to keep the payment with invalid state than delete it // entirely. @@ -260,31 +265,6 @@ class VippsExpress extends Vipps implements SupportsAuthorizationsInterface, Sup default: throw new NeedsRedirectException('/cart'); } - - // Get payment details. - $details = $payment_manager->getPaymentDetails($remote_id); - $address = $details->getShippingDetails()->getAddress(); - - // Only Norway is supported by Vipps. - if ($address->getCountry() !== 'Norway') { - $matching_payment->setState('failed'); - $matching_payment->setRemoteState(Xss::filter($status->getTransactionInfo()->getStatus())); - $matching_payment->save(); - $order->set('payment_gateway', NULL); - $order->set('payment_method', NULL); - $order->set('checkout_step', NULL); - $order->unlock(); - $order->save(); - throw new NeedsRedirectException('/cart'); - } - - // Dispatch the event. - $event = new ReturnFromVippsExpressEvent($matching_payment, $order, $details); - $this->eventDispatcher->dispatch(VippsEvents::RETURN_FROM_VIPPS_EXPRESS, $event); - - // Save data on order and payment. - $order->save(); - $matching_payment->save(); } }