Skip to content

Commit bd57d37

Browse files
Release version 5.1.0
1 parent dc1044b commit bd57d37

33 files changed

Lines changed: 722 additions & 135 deletions

File tree

Block/Adminhtml/System/Config/Form/Field/CBTAvailableCurrencies.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,47 @@
22

33
namespace Afterpay\Afterpay\Block\Adminhtml\System\Config\Form\Field;
44

5+
use Magento\Backend\Block\Template\Context;
6+
use Magento\Framework\Serialize\SerializerInterface;
7+
use Psr\Log\LoggerInterface;
8+
59
class CBTAvailableCurrencies extends \Magento\Config\Block\System\Config\Form\Field
610
{
11+
private SerializerInterface $serializer;
12+
private LoggerInterface $logger;
13+
14+
public function __construct(
15+
LoggerInterface $logger,
16+
SerializerInterface $serializer,
17+
Context $context,
18+
array $data = []
19+
) {
20+
$this->serializer = $serializer;
21+
$this->logger = $logger;
22+
parent::__construct($context, $data);
23+
}
24+
25+
protected function _renderValue(\Magento\Framework\Data\Form\Element\AbstractElement $element)
26+
{
27+
try {
28+
$CbtAvailableCurrencies = $this->serializer->unserialize($element->getValue());
29+
$newValue = '';
30+
if (!$CbtAvailableCurrencies) {
31+
return parent::_renderValue($element);
32+
}
33+
34+
foreach ($CbtAvailableCurrencies as $currencyCode => $currency) {
35+
$newValue .= $currencyCode . '(min:' . $currency['minimumAmount']['amount']
36+
. ',max:' . $currency['maximumAmount']['amount'] . ') ';
37+
}
38+
$element->setValue($newValue);
39+
} catch (\Exception $e) {
40+
$this->logger->critical($e);
41+
}
42+
43+
return parent::_renderValue($element);
44+
}
45+
746
public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
847
{
948
/** @phpstan-ignore-next-line */

Controller/Express/PlaceOrder.php

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,36 @@
22

33
namespace Afterpay\Afterpay\Controller\Express;
44

5-
class PlaceOrder implements \Magento\Framework\App\Action\HttpPostActionInterface
6-
{
7-
const CANCELLED_STATUS = 'CANCELLED';
5+
use Afterpay\Afterpay\Controller\Payment\Capture;
6+
use Afterpay\Afterpay\Gateway\Config\Config;
7+
use Afterpay\Afterpay\Model\Payment\Capture\PlaceOrderProcessor;
8+
use Magento\Checkout\Model\Session;
9+
use Magento\Framework\App\Action\HttpPostActionInterface;
10+
use Magento\Framework\App\RequestInterface;
11+
use Magento\Framework\Controller\Result\JsonFactory;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Message\ManagerInterface;
14+
use Magento\Framework\UrlInterface;
15+
use Magento\Payment\Gateway\CommandInterface;
816

9-
private \Magento\Framework\App\RequestInterface $request;
10-
private \Magento\Framework\Message\ManagerInterface $messageManager;
11-
private \Magento\Checkout\Model\Session $checkoutSession;
12-
private \Magento\Framework\Controller\Result\JsonFactory $jsonFactory;
13-
private \Magento\Framework\UrlInterface $url;
14-
private \Afterpay\Afterpay\Model\Payment\Capture\PlaceOrderProcessor $placeOrderProcessor;
15-
private \Magento\Payment\Gateway\CommandInterface $syncCheckoutDataCommand;
17+
class PlaceOrder implements HttpPostActionInterface
18+
{
19+
private RequestInterface $request;
20+
private ManagerInterface $messageManager;
21+
private Session $checkoutSession;
22+
private JsonFactory $jsonFactory;
23+
private UrlInterface $url;
24+
private PlaceOrderProcessor $placeOrderProcessor;
25+
private CommandInterface $syncCheckoutDataCommand;
1626

1727
public function __construct(
18-
\Magento\Framework\App\RequestInterface $request,
19-
\Magento\Framework\Message\ManagerInterface $messageManager,
20-
\Magento\Checkout\Model\Session $checkoutSession,
21-
\Magento\Framework\Controller\Result\JsonFactory $jsonFactory,
22-
\Magento\Framework\UrlInterface $url,
23-
\Afterpay\Afterpay\Model\Payment\Capture\PlaceOrderProcessor $placeOrderProcessor,
24-
\Magento\Payment\Gateway\CommandInterface $syncCheckoutDataCommand
28+
RequestInterface $request,
29+
ManagerInterface $messageManager,
30+
Session $checkoutSession,
31+
JsonFactory $jsonFactory,
32+
UrlInterface $url,
33+
PlaceOrderProcessor $placeOrderProcessor,
34+
CommandInterface $syncCheckoutDataCommand
2535
) {
2636
$this->request = $request;
2737
$this->messageManager = $messageManager;
@@ -39,21 +49,29 @@ public function execute()
3949

4050
$afterpayOrderToken = $this->request->getParam('orderToken');
4151
$status = $this->request->getParam('status');
42-
43-
if ($status === static::CANCELLED_STATUS) {
52+
if ($status === Capture::CHECKOUT_STATUS_CANCELLED) {
4453
return $jsonResult;
4554
}
4655

56+
if ($status !== Capture::CHECKOUT_STATUS_SUCCESS) {
57+
$errorMessage = (string)__('Afterpay payment is declined. Please select an alternative payment method.');
58+
$this->messageManager->addErrorMessage($errorMessage);
59+
60+
return $jsonResult->setData(['redirectUrl' => $this->url->getUrl('checkout/cart')]);
61+
}
62+
4763
try {
4864
$quote->getPayment()
49-
->setMethod(\Afterpay\Afterpay\Gateway\Config\Config::CODE)
65+
->setMethod(Config::CODE)
5066
->setAdditionalInformation('afterpay_express', true);
5167
$this->placeOrderProcessor->execute($quote, $this->syncCheckoutDataCommand, $afterpayOrderToken);
5268
} catch (\Throwable $e) {
53-
$errorMessage = $e instanceof \Magento\Framework\Exception\LocalizedException
69+
$errorMessage = $e instanceof LocalizedException
5470
? $e->getMessage()
5571
: (string)__('Afterpay payment is declined. Please select an alternative payment method.');
56-
return $jsonResult->setData(['error' => $errorMessage, 'redirectUrl' => $this->url->getUrl('checkout/cart')]);
72+
$this->messageManager->addErrorMessage($errorMessage);
73+
74+
return $jsonResult->setData(['redirectUrl' => $this->url->getUrl('checkout/cart')]);
5775
}
5876

5977
return $jsonResult->setData(['redirectUrl' => $this->url->getUrl('checkout/onepage/success')]);

Gateway/Request/Checkout/CheckoutDataBuilder.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,19 @@ protected function getItems(\Magento\Quote\Model\Quote $quote): array
103103
$productId = $item->getProduct()->getId();
104104
$amount = $isCBTCurrencyAvailable ? $item->getPriceInclTax() : $item->getBasePriceInclTax();
105105
$currencyCode = $isCBTCurrencyAvailable ? $quote->getQuoteCurrencyCode() : $quote->getBaseCurrencyCode();
106+
$qty = $item->getQty();
107+
$isIntQty = floor($qty) == $qty;
108+
if ($isIntQty) {
109+
$qty = (int)$item->getQty();
110+
} else {
111+
$amount *= $item->getQty();
112+
$qty = 1;
113+
}
106114

107115
$formattedItem = [
108116
'name' => $item->getName(),
109117
'sku' => $item->getSku(),
110-
'quantity' => $item->getQty(),
118+
'quantity' => $qty,
111119
'pageUrl' => $item->getProduct()->getProductUrl(),
112120
'categories' => [array_values($this->getQuoteItemCategoriesNames($item))],
113121
'price' => [

Gateway/Response/Checkout/CheckoutItemsAmountValidationHandler.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ public function handle(array $handlingSubject, array $response)
3535
throw new \Magento\Framework\Exception\LocalizedException($invalidCartItemsExceptionMessage);
3636
}
3737
if ($item->getQty() != $responseItems[$itemIndex]['quantity']) {
38+
$qty = $item->getQty();
39+
$isIntQty = floor($qty) == $qty;
40+
if (!$isIntQty && $responseItems[$itemIndex]['quantity'] == 1) {
41+
$amount = $isCBTCurrency ? $item->getPriceInclTax() : $item->getBasePriceInclTax();
42+
if ($amount * $qty == $responseItems[$itemIndex]['price']['amount']) {
43+
continue;
44+
}
45+
}
3846
throw new \Magento\Framework\Exception\LocalizedException($invalidCartItemsExceptionMessage);
3947
}
4048
}

Gateway/Response/MerchantConfiguration/CBTAvailableCurrenciesConfigurationHandler.php

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,35 @@
22

33
namespace Afterpay\Afterpay\Gateway\Response\MerchantConfiguration;
44

5-
class CBTAvailableCurrenciesConfigurationHandler implements \Magento\Payment\Gateway\Response\HandlerInterface
5+
use Afterpay\Afterpay\Model\Config;
6+
use Magento\Framework\Serialize\SerializerInterface;
7+
use Magento\Payment\Gateway\Response\HandlerInterface;
8+
9+
class CBTAvailableCurrenciesConfigurationHandler implements HandlerInterface
610
{
7-
private \Afterpay\Afterpay\Model\Config $config;
11+
private Config $config;
12+
private SerializerInterface $serializer;
813

914
public function __construct(
10-
\Afterpay\Afterpay\Model\Config $config
15+
Config $config,
16+
SerializerInterface $serializer
1117
) {
1218
$this->config = $config;
19+
$this->serializer = $serializer;
1320
}
1421

1522
public function handle(array $handlingSubject, array $response): void
1623
{
1724
$websiteId = (int)$handlingSubject['websiteId'];
18-
$cbtAvailableCurrencies = [];
25+
$cbtAvailableCurrencies = '';
26+
1927
if (isset($response['CBT']['enabled']) &&
2028
isset($response['CBT']['limits']) &&
2129
is_array($response['CBT']['limits'])
2230
) {
23-
foreach ($response['CBT']['limits'] as $limit) {
24-
if (isset($limit['maximumAmount']['currency']) && isset($limit['maximumAmount']['amount'])) {
25-
$cbtAvailableCurrencies[] = $limit['maximumAmount']['currency'] . ':' . $limit['maximumAmount']['amount'];
26-
}
27-
}
31+
$cbtAvailableCurrencies = $this->serializer->serialize($response['CBT']['limits']);
2832
}
29-
$this->config->setCbtCurrencyLimits(implode(",", $cbtAvailableCurrencies), $websiteId);
33+
34+
$this->config->setCbtCurrencyLimits($cbtAvailableCurrencies, $websiteId);
3035
}
3136
}

Gateway/Validator/Method/CurrencyValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function __construct(
2020
public function validate(array $validationSubject): \Magento\Payment\Gateway\Validator\ResultInterface
2121
{
2222
$quote = $this->checkoutSession->getQuote();
23-
$currentCurrency = $quote->getQuoteCurrencyCode();
23+
$currentCurrency = $quote->getStore()->getCurrentCurrencyCode();
2424
$allowedCurrencies = $this->config->getAllowedCurrencies();
2525
$cbtCurrencies = array_keys($this->config->getCbtCurrencyLimits());
2626

Model/Checks/IsCBTAvailable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function checkByQuote(\Magento\Quote\Model\Quote $quote): bool
3030
return $this->canUseCurrentCurrency;
3131
}
3232

33-
$currentCurrencyCode = $quote->getQuoteCurrencyCode();
33+
$currentCurrencyCode = $quote->getQuoteCurrencyCode() ?? $quote->getStore()->getCurrentCurrencyCode();
3434
$amount = (float) $quote->getGrandTotal();
3535
$this->canUseCurrentCurrency = $this->check($currentCurrencyCode, $amount);
3636

Model/Config.php

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
<?php
2-
3-
declare(strict_types=1);
1+
<?php declare(strict_types=1);
42

53
namespace Afterpay\Afterpay\Model;
64

5+
use Magento\Framework\App\Config\ScopeConfigInterface;
6+
use Magento\Framework\App\Config\Storage\WriterInterface;
7+
use Magento\Framework\App\ResourceConnection;
8+
use Magento\Framework\Serialize\SerializerInterface;
79
use Magento\Store\Model\ScopeInterface;
810

911
class Config
@@ -21,27 +23,31 @@ class Config
2123
const XML_PATH_MERCHANT_KEY = 'payment/afterpay/merchant_key';
2224
const XML_PATH_PAYMENT_FLOW = 'payment/afterpay/payment_flow';
2325
const XML_PATH_MIN_LIMIT = 'payment/afterpay/min_order_total';
24-
const XML_PATH_MAX_LIMIT = 'payment/afterpay/max_order_total';
25-
const XML_PATH_CBT_CURRENCY_LIMITS = 'payment/afterpay/cbt_currency_limits';
26-
const XML_PATH_EXCLUDE_CATEGORIES = 'payment/afterpay/exclude_categories';
27-
const XML_PATH_ALLOW_SPECIFIC_COUNTRIES = 'payment/afterpay/allowspecific';
28-
const XML_PATH_SPECIFIC_COUNTRIES = 'payment/afterpay/specificcountry';
29-
const XML_PATH_ALLOWED_MERCHANT_COUNTRIES = 'payment/afterpay/allowed_merchant_countries';
30-
const XML_PATH_ALLOWED_MERCHANT_CURRENCIES = 'payment/afterpay/allowed_merchant_currencies';
31-
const XML_PATH_PAYPAL_MERCHANT_COUNTRY = 'paypal/general/merchant_country';
32-
33-
private \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig;
34-
private \Magento\Framework\App\Config\Storage\WriterInterface $writer;
35-
private \Magento\Framework\App\ResourceConnection $resourceConnection;
26+
const XML_PATH_MAX_LIMIT = 'payment/afterpay/max_order_total';
27+
const XML_PATH_CBT_CURRENCY_LIMITS = 'payment/afterpay/cbt_currency_limits';
28+
const XML_PATH_EXCLUDE_CATEGORIES = 'payment/afterpay/exclude_categories';
29+
const XML_PATH_ALLOW_SPECIFIC_COUNTRIES = 'payment/afterpay/allowspecific';
30+
const XML_PATH_SPECIFIC_COUNTRIES = 'payment/afterpay/specificcountry';
31+
const XML_PATH_ALLOWED_MERCHANT_COUNTRIES = 'payment/afterpay/allowed_merchant_countries';
32+
const XML_PATH_ALLOWED_MERCHANT_CURRENCIES = 'payment/afterpay/allowed_merchant_currencies';
33+
const XML_PATH_PAYPAL_MERCHANT_COUNTRY = 'paypal/general/merchant_country';
34+
const XML_PATH_ENABLE_REVERSAL = 'payment/afterpay/enable_reversal';
35+
36+
private ScopeConfigInterface $scopeConfig;
37+
private WriterInterface $writer;
38+
private ResourceConnection $resourceConnection;
39+
private SerializerInterface $serializer;
3640

3741
public function __construct(
38-
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
39-
\Magento\Framework\App\Config\Storage\WriterInterface $writer,
40-
\Magento\Framework\App\ResourceConnection $resourceConnection
42+
ScopeConfigInterface $scopeConfig,
43+
WriterInterface $writer,
44+
ResourceConnection $resourceConnection,
45+
SerializerInterface $serializer
4146
) {
4247
$this->scopeConfig = $scopeConfig;
4348
$this->writer = $writer;
4449
$this->resourceConnection = $resourceConnection;
50+
$this->serializer = $serializer;
4551
}
4652

4753
public function getIsPaymentActive(?int $scopeCode = null): bool
@@ -172,7 +178,6 @@ public function getMinOrderTotal(?int $scopeCode = null): ?string
172178

173179
public function getCbtCurrencyLimits(?int $scopeCode = null): array
174180
{
175-
$data = [];
176181
$value = $this->scopeConfig->getValue(
177182
self::XML_PATH_CBT_CURRENCY_LIMITS,
178183
ScopeInterface::SCOPE_WEBSITE,
@@ -183,15 +188,7 @@ public function getCbtCurrencyLimits(?int $scopeCode = null): array
183188
return [];
184189
}
185190

186-
$list = explode(',', $value);
187-
foreach ($list as $item) {
188-
$currencyLimit = explode(':', $item);
189-
if (isset($currencyLimit[0]) && isset($currencyLimit[1])) {
190-
$data[$currencyLimit[0]] = (float) $currencyLimit[1];
191-
}
192-
}
193-
194-
return $data;
191+
return $this->serializer->unserialize($value);
195192
}
196193

197194
public function getExcludeCategories(?int $scopeCode = null): array
@@ -205,6 +202,15 @@ public function getExcludeCategories(?int $scopeCode = null): array
205202
return $excludeCategories ? explode(',', $excludeCategories) : [];
206203
}
207204

205+
public function getIsReversalEnabled(?int $scopeCode = null): bool
206+
{
207+
return $this->scopeConfig->isSetFlag(
208+
self::XML_PATH_ENABLE_REVERSAL,
209+
ScopeInterface::SCOPE_WEBSITE,
210+
$scopeCode
211+
);
212+
}
213+
208214
public function setMaxOrderTotal(string $value, int $scopeId = 0): self
209215
{
210216
if ($scopeId) {
@@ -347,7 +353,7 @@ public function setSpecificCountries(string $value, int $scopeId = 0): self
347353

348354
public function getMerchantCountry(
349355
string $scope = ScopeInterface::SCOPE_WEBSITES,
350-
?int $scopeCode = null
356+
?int $scopeCode = null
351357
): ?string {
352358
if ($countryCode = $this->scopeConfig->getValue(
353359
self::XML_PATH_PAYPAL_MERCHANT_COUNTRY,
@@ -368,7 +374,7 @@ public function getMerchantCountry(
368374

369375
public function getMerchantCurrency(
370376
string $scope = ScopeInterface::SCOPE_WEBSITES,
371-
?int $scopeCode = null
377+
?int $scopeCode = null
372378
): ?string {
373379
return $this->scopeConfig->getValue(
374380
\Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE,
@@ -401,7 +407,7 @@ public function websiteHasOwnConfig(int $websiteId): bool
401407
\Afterpay\Afterpay\Observer\Adminhtml\ConfigSaveAfter::AFTERPAY_CONFIGS,
402408
\Afterpay\Afterpay\Observer\Adminhtml\ConfigSaveAfter::CONFIGS_PATHS_TO_TRACK
403409
);
404-
$selectQuery = $connection->select()->from($coreConfigData, ['path','value'])
410+
$selectQuery = $connection->select()->from($coreConfigData, ['path', 'value'])
405411
->where("scope = ?", \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES)
406412
->where("scope_id = ?", $websiteId)
407413
->where("path in (?)", $configsExistToCheck);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Afterpay\Afterpay\Model\Config;
4+
5+
class CategorySourceRegistry
6+
{
7+
private bool $showAllCategories = false;
8+
9+
public function getShowAllCategories(): bool
10+
{
11+
return $this->showAllCategories;
12+
}
13+
14+
public function setShowAllCategories(bool $value): void
15+
{
16+
$this->showAllCategories = $value;
17+
}
18+
}

0 commit comments

Comments
 (0)