diff --git a/Controller/Payment/Capture.php b/Controller/Payment/Capture.php index a241421..30cab2b 100644 --- a/Controller/Payment/Capture.php +++ b/Controller/Payment/Capture.php @@ -10,6 +10,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Message\ManagerInterface; use Magento\Payment\Gateway\CommandInterface; +use Psr\Log\LoggerInterface; class Capture implements HttpGetActionInterface { @@ -21,6 +22,7 @@ class Capture implements HttpGetActionInterface private ManagerInterface $messageManager; private PlaceOrderProcessor $placeOrderProcessor; private CommandInterface $validateCheckoutDataCommand; + private LoggerInterface $logger; public function __construct( RequestInterface $request, @@ -28,7 +30,8 @@ public function __construct( RedirectFactory $redirectFactory, ManagerInterface $messageManager, PlaceOrderProcessor $placeOrderProcessor, - CommandInterface $validateCheckoutDataCommand + CommandInterface $validateCheckoutDataCommand, + LoggerInterface $logger ) { $this->request = $request; $this->session = $session; @@ -36,10 +39,12 @@ public function __construct( $this->messageManager = $messageManager; $this->placeOrderProcessor = $placeOrderProcessor; $this->validateCheckoutDataCommand = $validateCheckoutDataCommand; + $this->logger = $logger; } public function execute() { + $afterpayOrderToken = $this->request->getParam('orderToken'); if ($this->request->getParam('status') == self::CHECKOUT_STATUS_CANCELLED) { $this->messageManager->addErrorMessage( (string)__('You have cancelled your Afterpay payment. Please select an alternative payment method.') @@ -51,13 +56,16 @@ public function execute() $this->messageManager->addErrorMessage( (string)__('Afterpay payment is declined. Please select an alternative payment method.') ); + $this->logger->info( + 'Afterpay payment(' . $afterpayOrderToken . ') response status is "' . $this->request->getParam('status') + . '".' . 'Customer has been redirected to the cart page.' + ); return $this->redirectFactory->create()->setPath('checkout/cart'); } try { $quote = $this->session->getQuote(); - $afterpayOrderToken = $this->request->getParam('orderToken'); $this->placeOrderProcessor->execute($quote, $this->validateCheckoutDataCommand, $afterpayOrderToken); } catch (\Throwable $e) { $errorMessage = $e instanceof LocalizedException diff --git a/Gateway/Response/Checkout/CheckoutItemsAmountValidationHandler.php b/Gateway/Response/Checkout/CheckoutItemsAmountValidationHandler.php index 464ed67..4aad650 100644 --- a/Gateway/Response/Checkout/CheckoutItemsAmountValidationHandler.php +++ b/Gateway/Response/Checkout/CheckoutItemsAmountValidationHandler.php @@ -15,14 +15,14 @@ public function handle(array $handlingSubject, array $response) if (round(1 * $grandTotal, 2) != round(1 * $response['amount']['amount'], 2)) { throw new \Magento\Framework\Exception\LocalizedException( - __('There are issues when processing your payment. Invalid Amount') + __('There was a issue with the processing of your payment. Invalid amount.') ); } $quoteItems = $quote->getAllVisibleItems(); $responseItems = $response['items']; - $invalidCartItemsExceptionMessage = __('There are issues when processing your payment. Invalid Cart Items'); + $invalidCartItemsExceptionMessage = __('There was a issue with the processing of your payment. Invalid cart items.'); if (count($quoteItems) != count($responseItems)) { throw new \Magento\Framework\Exception\LocalizedException($invalidCartItemsExceptionMessage); diff --git a/Model/Payment/Capture/CancelOrderProcessor.php b/Model/Payment/Capture/CancelOrderProcessor.php index 7a975e1..7a69cde 100644 --- a/Model/Payment/Capture/CancelOrderProcessor.php +++ b/Model/Payment/Capture/CancelOrderProcessor.php @@ -2,6 +2,10 @@ namespace Afterpay\Afterpay\Model\Payment\Capture; +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Gateway\Command\CommandException; +use Magento\Quote\Model\Quote\Payment; + class CancelOrderProcessor { private \Magento\Payment\Gateway\Data\PaymentDataObjectFactoryInterface $paymentDataObjectFactory; @@ -27,7 +31,17 @@ public function __construct( $this->quotePaidStorage = $quotePaidStorage; } - public function execute(\Magento\Quote\Model\Quote\Payment $payment, int $quoteId): void + /** + * @param Payment $payment + * @param int $quoteId + * @param \Throwable|null $e + * + * @return void + * @throws CommandException + * @throws LocalizedException + * @throws \Throwable + */ + public function execute(\Magento\Quote\Model\Quote\Payment $payment, int $quoteId, \Throwable $e = null): void { if (!$this->config->getIsReversalEnabled()) { return; @@ -48,6 +62,10 @@ public function execute(\Magento\Quote\Model\Quote\Payment $payment, int $quoteI $afterpayPayment = $this->quotePaidStorage->getAfterpayPaymentIfQuoteIsPaid($quoteId); if (!$afterpayPayment) { + if ($e instanceof LocalizedException) { + throw $e; + } + throw new \Magento\Framework\Exception\LocalizedException( __( 'Afterpay payment is declined. Please select an alternative payment method.' diff --git a/Model/Payment/Capture/PlaceOrderProcessor.php b/Model/Payment/Capture/PlaceOrderProcessor.php index be9709f..42cab1f 100644 --- a/Model/Payment/Capture/PlaceOrderProcessor.php +++ b/Model/Payment/Capture/PlaceOrderProcessor.php @@ -55,21 +55,21 @@ public function execute(Quote $quote, CommandInterface $checkoutDataCommand, str $payment = $quote->getPayment(); try { - $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_TOKEN, $afterpayOrderToken); - $isCBTCurrencyAvailable = $this->checkCBTCurrencyAvailability->checkByQuote($quote); - $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_IS_CBT_CURRENCY, $isCBTCurrencyAvailable); - $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_CBT_CURRENCY, $quote->getQuoteCurrencyCode()); + $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_TOKEN, $afterpayOrderToken); + $isCBTCurrencyAvailable = $this->checkCBTCurrencyAvailability->checkByQuote($quote); + $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_IS_CBT_CURRENCY, $isCBTCurrencyAvailable); + $payment->setAdditionalInformation(CheckoutInterface::AFTERPAY_CBT_CURRENCY, $quote->getQuoteCurrencyCode()); - if (!$quote->getCustomerId()) { - $quote->setCustomerEmail($quote->getBillingAddress()->getEmail()) - ->setCustomerIsGuest(true) - ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID); - } + if (!$quote->getCustomerId()) { + $quote->setCustomerEmail($quote->getBillingAddress()->getEmail()) + ->setCustomerIsGuest(true) + ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID); + } - $checkoutDataCommand->execute(['payment' => $this->paymentDataObjectFactory->create($payment)]); - $this->checkoutSession->setAfterpayRedirect(true); + $checkoutDataCommand->execute(['payment' => $this->paymentDataObjectFactory->create($payment)]); + $this->checkoutSession->setAfterpayRedirect(true); - $orderId = (int)$this->cartManagement->placeOrder($quote->getId()); + $orderId = (int)$this->cartManagement->placeOrder($quote->getId()); } catch (\Throwable $e) { $orderId = $this->paymentErrorProcessor->execute($quote, $e, $payment); } diff --git a/Model/Payment/PaymentErrorProcessor.php b/Model/Payment/PaymentErrorProcessor.php index d3043df..a0fd026 100644 --- a/Model/Payment/PaymentErrorProcessor.php +++ b/Model/Payment/PaymentErrorProcessor.php @@ -48,7 +48,7 @@ public function execute(Quote $quote, \Throwable $e, Payment $payment): int $this->orderRepository->save($order); return (int)$order->getEntityId(); - } catch (NoSuchEntityException $e) { + } catch (NoSuchEntityException $exception) { throw $e; } } @@ -57,7 +57,7 @@ public function execute(Quote $quote, \Throwable $e, Payment $payment): int throw $e; } - $this->cancelOrderProcessor->execute($payment, (int)$quote->getId()); + $this->cancelOrderProcessor->execute($payment, (int)$quote->getId(), $e); if ($e instanceof LocalizedException) { throw $e; diff --git a/Model/Shipment/Express/CreateShippingOption.php b/Model/Shipment/Express/CreateShippingOption.php index a0827c5..b238b5b 100644 --- a/Model/Shipment/Express/CreateShippingOption.php +++ b/Model/Shipment/Express/CreateShippingOption.php @@ -63,8 +63,8 @@ private function createShippingOptionByMethod( return [ 'id' => implode('_', [$shippingMethod->getCarrierCode(), $shippingMethod->getMethodCode()]), - 'name' => $shippingMethod->getCarrierTitle(), - 'description' => $shippingMethod->getCarrierTitle(), + 'name' => !empty($shippingMethod->getCarrierTitle()) ? $shippingMethod->getCarrierTitle() : $shippingMethod->getMethodTitle(), + 'description' => !empty($shippingMethod->getCarrierTitle()) ? $shippingMethod->getCarrierTitle() : $shippingMethod->getMethodTitle(), 'shippingAmount' => [ 'amount' => $this->formatPrice($shippingAmount), 'currency' => $currency diff --git a/Model/StockItemsValidator/StockItemsValidatorProxy.php b/Model/StockItemsValidator/StockItemsValidatorProxy.php index a454f03..12f4b55 100644 --- a/Model/StockItemsValidator/StockItemsValidatorProxy.php +++ b/Model/StockItemsValidator/StockItemsValidatorProxy.php @@ -2,19 +2,35 @@ namespace Afterpay\Afterpay\Model\StockItemsValidator; +use Afterpay\Afterpay\Gateway\Validator\StockItemsValidatorFactory; +use Afterpay\Afterpay\Model\SourceValidatorServiceFactory; +use Afterpay\Afterpay\Model\Spi\StockItemsValidatorInterface; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Module\Manager; +use Magento\Framework\ObjectManager\NoninterceptableInterface; +use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface; +use Magento\InventoryCatalogApi\Model\IsSingleSourceModeInterface; +use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; +use Magento\InventoryConfigurationApi\Exception\SkuIsNotAssignedToStockException; +use Magento\InventorySalesApi\Api\GetStockBySalesChannelInterface; +use Magento\InventoryShipping\Model\GetItemsToDeductFromShipment; +use Magento\InventoryShipping\Model\SourceDeductionRequestFromShipmentFactory as SourceDeductionRequestFactory; +use Magento\InventorySourceDeductionApi\Model\GetSourceItemBySourceCodeAndSku; +use Magento\Sales\Model\Order\Shipment; -class StockItemsValidatorProxy implements \Afterpay\Afterpay\Model\Spi\StockItemsValidatorInterface, \Magento\Framework\ObjectManager\NoninterceptableInterface // @codingStandardsIgnoreLine +class StockItemsValidatorProxy implements StockItemsValidatorInterface, NoninterceptableInterface { - private ?\Afterpay\Afterpay\Model\Spi\StockItemsValidatorInterface $subject = null; - private \Afterpay\Afterpay\Gateway\Validator\StockItemsValidatorFactory $stockItemValidatorFactory; - private \Afterpay\Afterpay\Model\SourceValidatorServiceFactory $sourceValidatorServiceFactory; - private \Magento\Framework\Module\Manager $moduleManager; + private ?StockItemsValidatorInterface $subject = null; + private StockItemsValidatorFactory $stockItemValidatorFactory; + private SourceValidatorServiceFactory $sourceValidatorServiceFactory; + private Manager $moduleManager; public function __construct( - \Afterpay\Afterpay\Gateway\Validator\StockItemsValidatorFactory $stockItemsValidatorFactory, - \Afterpay\Afterpay\Model\SourceValidatorServiceFactory $sourceValidatorServiceFactory, - \Magento\Framework\Module\Manager $moduleManager + StockItemsValidatorFactory $stockItemsValidatorFactory, + SourceValidatorServiceFactory $sourceValidatorServiceFactory, + Manager $moduleManager ) { $this->stockItemValidatorFactory = $stockItemsValidatorFactory; $this->sourceValidatorServiceFactory = $sourceValidatorServiceFactory; @@ -23,11 +39,11 @@ public function __construct( /** * Check msi functionality existing if no then skip validation - * @throws \Magento\Framework\Exception\LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\InventoryConfigurationApi\Exception\SkuIsNotAssignedToStockException + * @throws LocalizedException + * @throws NoSuchEntityException + * @throws SkuIsNotAssignedToStockException */ - public function validate(\Magento\Sales\Model\Order\Shipment $shipment): void + public function validate(Shipment $shipment): void { if (!$this->moduleManager->isEnabled('Magento_InventoryCatalogApi') || !$this->moduleManager->isEnabled('Magento_InventoryShipping') || @@ -35,29 +51,30 @@ public function validate(\Magento\Sales\Model\Order\Shipment $shipment): void !$this->moduleManager->isEnabled('Magento_InventoryConfigurationApi') || !$this->moduleManager->isEnabled('Magento_InventorySalesApi') ) { - return ; + return; } $stockItemsValidator = $this->getStockItemValidator(); $stockItemsValidator->validate($shipment); } - private function getStockItemValidator(): \Afterpay\Afterpay\Model\Spi\StockItemsValidatorInterface + private function getStockItemValidator(): StockItemsValidatorInterface { if ($this->subject == null) { $objectManager = ObjectManager::getInstance(); $sourceValidatorService = $this->sourceValidatorServiceFactory->create([ - 'getSourceItemBySourceCodeAndSku' => $objectManager->create('\\Magento\\InventorySourceDeductionApi\\Model\\GetSourceItemBySourceCodeAndSku'), // @codingStandardsIgnoreLine - 'getStockItemConfiguration' => $objectManager->create('\\Magento\\InventoryConfigurationApi\\Api\\GetStockItemConfigurationInterface'), // @codingStandardsIgnoreLine - 'getStockBySalesChannel' => $objectManager->create('\\Magento\\InventorySalesApi\\Api\\GetStockBySalesChannelInterface'), + 'getSourceItemBySourceCodeAndSku' => $objectManager->create(GetSourceItemBySourceCodeAndSku::class), + 'getStockItemConfiguration' => $objectManager->create(GetStockItemConfigurationInterface::class), + 'getStockBySalesChannel' => $objectManager->create(GetStockBySalesChannelInterface::class), ]); $this->subject = $this->stockItemValidatorFactory->create([ - 'isSingleSourceMode' => $objectManager->create('\\Magento\\InventoryCatalogApi\\Model\\IsSingleSourceModeInterface'), // @codingStandardsIgnoreLine - 'defaultSourceProvider' => $objectManager->create('\\Magento\\InventoryCatalogApi\\Api\\DefaultSourceProviderInterface'), // @codingStandardsIgnoreLine - 'getItemsToDeductFromShipment' => $objectManager->create('\\Magento\\InventoryShipping\\Model\\GetItemsToDeductFromShipment'), // @codingStandardsIgnoreLine - 'sourceDeductionRequestFromShipmentFactory' => $objectManager->create('\\Magento\\InventoryShipping\\Model\\SourceDeductionRequestFromShipmentFactory'), // @codingStandardsIgnoreLine - 'sourceValidatorService' => $sourceValidatorService, + 'isSingleSourceMode' => $objectManager->create(IsSingleSourceModeInterface::class), + 'defaultSourceProvider' => $objectManager->create(DefaultSourceProviderInterface::class), + 'getItemsToDeductFromShipment' => $objectManager->create(GetItemsToDeductFromShipment::class), + 'sourceDeductionRequestFromShipmentFactory' => $objectManager->create(SourceDeductionRequestFactory::class), + 'sourceValidatorService' => $sourceValidatorService, ]); } + return $this->subject; } } diff --git a/composer.json b/composer.json index 90d4f1c..c4e85ac 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "license": "Apache-2.0", "type": "magento2-module", "description": "Magento 2 Afterpay Payment Module", - "version": "5.3.0", + "version": "5.3.1", "require": { "php": ">=7.4.0", "magento/framework": "^103.0", diff --git a/etc/csp_whitelist.xml b/etc/csp_whitelist.xml index 23877f8..66d4372 100644 --- a/etc/csp_whitelist.xml +++ b/etc/csp_whitelist.xml @@ -3,8 +3,6 @@ - https://portal.sandbox.clearpay.co.uk - https://portal.clearpay.co.uk https://portal.sandbox.afterpay.com https://portal.afterpay.com https://static.afterpay.com @@ -14,20 +12,16 @@ - static.afterpay.com - static.sandbox.afterpay.com + *.afterpay.com *.squarecdn.com https://hbiq.net https://iq.afterpay-beta.com https://iq.afterpay.com - *.clearpay.co.uk - widgets.sandbox.afterpay.com - widgets.sandbox.clearpay.co.uk @@ -38,8 +32,12 @@ - https://static.afterpay.com - https://site-assets.afterpay.com/ + *.afterpay.com/ + + + + + *.squarecdn.com diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml index 3c945cd..d4c517a 100644 --- a/etc/frontend/di.xml +++ b/etc/frontend/di.xml @@ -9,6 +9,7 @@ Afterpay\Afterpay\Gateway\Command\ValidateCheckoutDataCommand + Afterpay\Afterpay\Logger @@ -22,7 +23,9 @@ Afterpay\Afterpay\Model\Url\Lib\ExpressCheckoutLibUrlProvider - Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_PRODUCT + + Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_PRODUCT + @@ -33,13 +36,17 @@ Afterpay\Afterpay\Model\Url\Lib\ExpressCheckoutLibUrlProvider - Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_CART_PAGE + + Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_CART_PAGE + Afterpay\Afterpay\Model\Url\Lib\ExpressCheckoutLibUrlProvider - Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_MINI_CART + + Afterpay\Afterpay\Model\Config::XML_PATH_ENABLE_EXPRESS_CHECKOUT_ACTION_MINI_CART + @@ -62,7 +69,7 @@ - + diff --git a/etc/module.xml b/etc/module.xml index 72e4ea0..c6220c0 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,7 +1,7 @@ - + diff --git a/view/frontend/web/js/service/container/pricebox-widget-mixin.js b/view/frontend/web/js/service/container/pricebox-widget-mixin.js index 3ea1da2..ad96ac0 100644 --- a/view/frontend/web/js/service/container/pricebox-widget-mixin.js +++ b/view/frontend/web/js/service/container/pricebox-widget-mixin.js @@ -10,7 +10,7 @@ define([ }, updatePrice: function (newPrices) { const res = this._super(newPrices); - if (this._checkIsFinalPriceDefined() && this.element.closest('product-info-main')) { + if (this._checkIsFinalPriceDefined() && this.element.closest('.product-info-main').length > 0) { containerModel.setCurrentProductId(this.element.data('productId')); containerModel.setPrice(this.cache.displayPrices.finalPrice.amount); } diff --git a/view/frontend/web/js/view/payment/method-renderer/afterpay.js b/view/frontend/web/js/view/payment/method-renderer/afterpay.js index f4c9ea9..0f1d681 100644 --- a/view/frontend/web/js/view/payment/method-renderer/afterpay.js +++ b/view/frontend/web/js/view/payment/method-renderer/afterpay.js @@ -36,6 +36,12 @@ define([ getMPID: function () { return window.checkoutConfig.payment.afterpay.mpid; }, + getAmount: function() { + let amount = window.checkoutConfig.payment.afterpay.isCBTCurrency + ? quote.totals().grand_total : quote.totals().base_grand_total; + + return amount; + }, continueToAfterpay: function (data, event) { const self = this; diff --git a/view/frontend/web/template/payment/afterpay.html b/view/frontend/web/template/payment/afterpay.html index 15268dd..5ab67bc 100644 --- a/view/frontend/web/template/payment/afterpay.html +++ b/view/frontend/web/template/payment/afterpay.html @@ -11,7 +11,8 @@ 'data-mpid':getMPID(), 'data-platform': 'Magento', 'data-page-type': 'checkout', - 'data-type':'logo'} + 'data-type':'logo', + 'data-amount':getAmount()} ">