diff --git a/Block/Info/AbstractBlock.php b/Block/Info/AbstractBlock.php index dc8e12b785a..7a49f7a47f0 100755 --- a/Block/Info/AbstractBlock.php +++ b/Block/Info/AbstractBlock.php @@ -160,7 +160,14 @@ public function printAdditionalInformationHtml() } if (! empty($this->transactionInfo->getJsonResponse())) { - return $this->getMethod()->additionalPaymentInformation($this->transactionInfo->getJsonResponse()); + $methodInstance = $this->getMethod(); + if (\is_callable([$methodInstance, 'additionalPaymentInformation'])) { + return $methodInstance->additionalPaymentInformation( + $this->transactionInfo->getJsonResponse() + ); + } + + $this->_logger->debug('heidelpay: Could not retrieve additionalPaymentInformation for class: \"' . \get_class($methodInstance) . '\".'); } return ''; diff --git a/CHANGELOG.md b/CHANGELOG.md index c77a3eda6dd..9bf0687b626 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project does not follow a versioning standard. Versions are crafted after t for secured payment methods and PayPal. - Disable caching for dynamic blocks. - An issue creating orders from Reservations. +- Problem when switching from an unknown payment method to a heidelpay gateway method. - Invoice Payment methods : An issue not always setting the expected state after shipment. ## 20.2.24 diff --git a/Controller/Index/Push.php b/Controller/Index/Push.php index 498e0da81cd..d142b6c0e11 100755 --- a/Controller/Index/Push.php +++ b/Controller/Index/Push.php @@ -192,7 +192,7 @@ public function execute() $quote = $this->quoteRepository->get($transactionId); // create order if it doesn't exists already. - $order = $this->orderHelper->fetchOrder($transactionId); + $order = $this->orderHelper->fetchOrderByQuoteId($transactionId); if ($order === null || $order->isEmpty()) { $transactionData = $this->_paymentHelper->getDataFromResponse($pushResponse); $this->_paymentHelper->saveHeidelpayTransaction($pushResponse, $transactionData, 'PUSH'); diff --git a/Controller/Index/Redirect.php b/Controller/Index/Redirect.php index 5ca9f253271..6663a4ec36d 100755 --- a/Controller/Index/Redirect.php +++ b/Controller/Index/Redirect.php @@ -4,6 +4,7 @@ use Exception; use Heidelpay\Gateway\Controller\HgwAbstract; +use Heidelpay\Gateway\Helper\Order as OrderHelper; use Heidelpay\Gateway\Helper\Payment as HeidelpayHelper; use Heidelpay\Gateway\Model\ResourceModel\Transaction\CollectionFactory; use Heidelpay\Gateway\Model\Transaction as HeidelpayTransaction; @@ -50,6 +51,9 @@ class Redirect extends HgwAbstract /** @var CollectionFactory */ private $transactionCollectionFactory; + /** @var OrderHelper */ + private $orderHelper; + /** * heidelpay Redirect constructor. * @@ -69,6 +73,7 @@ class Redirect extends HgwAbstract * @param Encryptor $encryptor * @param Url $customerUrl * @param CollectionFactory $transactionCollectionFactory + * @param OrderHelper $orderHelper */ public function __construct( Context $context, @@ -86,7 +91,8 @@ public function __construct( OrderCommentSender $orderCommentSender, Encryptor $encryptor, Url $customerUrl, - CollectionFactory $transactionCollectionFactory + CollectionFactory $transactionCollectionFactory, + OrderHelper $orderHelper ) { parent::__construct( $context, @@ -107,6 +113,7 @@ public function __construct( ); $this->transactionCollectionFactory = $transactionCollectionFactory; + $this->orderHelper = $orderHelper; } /** @@ -156,7 +163,8 @@ public function execute() /** @var Order $order */ $order = null; try { - $order = $this->_orderFactory->create()->loadByAttribute('quote_id', $quoteId); + $this->_logger->debug('Load order by QuoteId: ' . $quoteId); + $order = $this->orderHelper->fetchOrderByQuoteId($quoteId); } catch (Exception $e) { $this->_logger->error( 'Heidelpay - Redirect: Cannot receive order.' . $e->getMessage() @@ -164,7 +172,8 @@ public function execute() } // Check whether order was loaded correctly - if($order === null || $order->isEmpty()) { + $hasHeidelpayPayment = $this->orderHelper->hasHeidelpayPayment($order); + if($order === null || $order->isEmpty() || $order->isCanceled() || !$hasHeidelpayPayment) { $this->_logger->error( 'Heidelpay - Redirect: Cannot receive order. Order creation might have failed.' ); @@ -206,17 +215,20 @@ protected function updateSessionData($quoteId, Order $order, array $data) $checkoutSession->clearHelperData(); // set QuoteIds - $checkoutSession->setLastQuoteId($quoteId) - ->setLastSuccessQuoteId($quoteId); + $checkoutSession->setLastQuoteId($quoteId)->setLastSuccessQuoteId($quoteId); // set OrderIds $checkoutSession->setLastOrderId($order->getId()) ->setLastRealOrderId($order->getIncrementId()) ->setLastOrderStatus($order->getStatus()); - $additionalPaymentInformation = $order->getPayment() - ->getMethodInstance() - ->additionalPaymentInformation($data); + $methodInstance = $order->getPayment()->getMethodInstance(); + $additionalPaymentInformation = ''; + if (\is_callable([$methodInstance, 'additionalPaymentInformation'])) { + $additionalPaymentInformation = $methodInstance->additionalPaymentInformation($data); + } else { + $this->_logger->error('heidelpay - The payment method seems to be from a different plugin.'); + } $checkoutSession->setHeidelpayInfo($additionalPaymentInformation); } diff --git a/Helper/Order.php b/Helper/Order.php index a3966665f3d..c572cd38bd8 100644 --- a/Helper/Order.php +++ b/Helper/Order.php @@ -2,9 +2,11 @@ namespace Heidelpay\Gateway\Helper; - +use Heidelpay\Gateway\PaymentMethods\HeidelpayAbstractPaymentMethod; use Magento\Framework\App\Helper\AbstractHelper; use Magento\Framework\App\Helper\Context; +use Magento\Framework\Data\Collection; +use Magento\Framework\DataObject; use Magento\Sales\Helper\Data as SalesHelper; use Magento\Sales\Model\Order as MagentoOrder; use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; @@ -117,16 +119,50 @@ public function handleOrderMail($order) } /** - * @param $transactionId - * @return MagentoOrder + * Returns the last Order to the quote with the given quoteId or an empty order object. + * + * @param $quoteId + * @return MagentoOrder|DataObject + */ + public function fetchOrderByQuoteId($quoteId) + { + $orderList = $this->fetchOrdersByQuoteId($quoteId); + + return $orderList->getLastItem(); + } + + /** + * @param $quoteId + * @return Collection */ - public function fetchOrder($transactionId) + protected function fetchOrdersByQuoteId($quoteId): Collection { - $criteria = $this->searchCriteriaBuilder->addFilter('quote_id', $transactionId)->create(); + $criteria = $this->searchCriteriaBuilder->addFilter('quote_id', $quoteId)->create(); /** @var Collection $orderList */ $orderList = $this->orderRepository->getList($criteria); + return $orderList; + } + + /** + * Returns true if the payment of the order is part of this payment module. + * + * @param MagentoOrder $order + * @return bool + */ + public function hasHeidelpayPayment(MagentoOrder $order): bool + { + $payment = $order->getPayment(); + $returnVal = true; + + if ($payment === null) { + $this->_logger->error('heidelpay - Empty payment.'); + $returnVal = false; + } elseif (!$payment->getMethodInstance() instanceof HeidelpayAbstractPaymentMethod) { + $this->_logger->error('heidelpay - Not heidelpay payment.'); + $returnVal = false; + } - return $orderList->getFirstItem(); + return $returnVal; } -} \ No newline at end of file +} diff --git a/Helper/Payment.php b/Helper/Payment.php index 3c5b6c159a8..910aa9d26ee 100755 --- a/Helper/Payment.php +++ b/Helper/Payment.php @@ -176,7 +176,7 @@ public function getDataFromResponse(Response $response) $data = []; foreach ($response->toArray() as $parameterKey => $value) { - $data[str_replace('.', '_', $parameterKey)] = $value; + $data[str_replace('.', '_', (string)$parameterKey)] = $value; } return $data; @@ -377,10 +377,11 @@ public function saveHeidelpayTransaction(Response $response, array $data, $sourc } /** - * Create an order by submitting the quote. If Order for that qoute already exist this order will be returned. + * Create an order by submitting the quote. If Order for that quote already exist this order will be returned. * @param Quote $quote * @return AbstractExtensibleModel|OrderInterface|Order|object|null * @throws LocalizedException + * @throws Exception */ public function handleOrderCreation($quote, $context = null) { @@ -389,9 +390,10 @@ public function handleOrderCreation($quote, $context = null) $this->lockManager->lock($lockName); try{ /** @var Order $order */ - $order = $this->orderHelper->fetchOrder($quote->getId()); - // Ensure to use the currency of the quote. - if ($order === null || $order->isEmpty()) { + $order = $this->orderHelper->fetchOrderByQuoteId($quote->getId()); + + if ($order === null || $order->isEmpty() || $order->isCanceled()) { + // Ensure to use the currency of the quote. $quote->getStore()->setCurrentCurrencyCode($quote->getQuoteCurrencyCode()); $quote->collectTotals(); // in case of guest checkout, set some customer related data. @@ -402,10 +404,15 @@ public function handleOrderCreation($quote, $context = null) ->setCustomerGroupId(Group::NOT_LOGGED_IN_ID); } $order = $this->_cartManagement->submit($quote); - if($context) { - $order->addStatusHistoryComment('heidelpay - Order created via ' . $context); + + if ($context) { + $order->addCommentToStatusHistory('heidelpay - Order created via ' . $context); } + } elseif (!$this->orderHelper->hasHeidelpayPayment($order)) { + $quote->setIsActive(false)->save(); + throw new Exception('The basket has been reset because an order already exists.'); } + } finally { $this->lockManager->unlock($lockName); } @@ -433,7 +440,7 @@ public function getPaymentMethodAndType(Response $response) public function isNewOrderType($paymentMethod, $paymentType) { // Order should be created for incoming payments - if(in_array($paymentType, self::NEW_ORDER_TRANSACTION_TYPE_ARRAY, true)){ + if(\in_array($paymentType, self::NEW_ORDER_TRANSACTION_TYPE_ARRAY, true)){ return true; } // Reservation should only create order if its not online transfer payment method. diff --git a/Test/Integration/Controller/Index/PushHandlingTest.php b/Test/Integration/Controller/Index/PushHandlingTest.php index 937ed4fef18..eaa4f755ace 100644 --- a/Test/Integration/Controller/Index/PushHandlingTest.php +++ b/Test/Integration/Controller/Index/PushHandlingTest.php @@ -114,7 +114,7 @@ public function PushCreatesNewTransaction($paymentCode, $paymentMethod) $this->assertQuoteActive($quote->getId(), false); /** @var Order $order */ - $fetchedOrder = $this->orderHelper->fetchOrder($quote->getId()); + $fetchedOrder = $this->orderHelper->fetchOrderByQuoteId($quote->getId()); $this->assertFalse($fetchedOrder->isEmpty(), 'Order creation failed: Order is empty'); $uniqueId = $xml->Transaction->Identification->UniqueID; @@ -200,7 +200,7 @@ public function CreateNoOrderFromInvalidTransactionTypes($paymentCode, $paymentM $this->assertQuoteActive($quote->getId(), true); /** @var Order $order */ - $fetchedOrder = $this->orderHelper->fetchOrder($quote->getId()); + $fetchedOrder = $this->orderHelper->fetchOrderByQuoteId($quote->getId()); $this->assertTrue($fetchedOrder->isEmpty(), 'No Order should be created here'); // Check Transaction @@ -322,7 +322,7 @@ private function assertMagentoTransactionExists($uniqueId) private function assertQuoteHasNoOrder(Quote $quote) { /** @var Order $fetchedOrder */ - $fetchedOrder = $this->orderHelper->fetchOrder($quote->getId()); + $fetchedOrder = $this->orderHelper->fetchOrderByQuoteId($quote->getId()); $this->assertTrue($fetchedOrder->isEmpty()); $this->assertNotNull($quote); }