diff --git a/Block/Totals/Fee.php b/Block/Totals/Fee.php index d956592..0c2e5d7 100644 --- a/Block/Totals/Fee.php +++ b/Block/Totals/Fee.php @@ -12,18 +12,20 @@ class Fee extends \Magento\Framework\View\Element\Template { protected PaymentFee $feeHelper; - protected SessionCheckout $sessionCheckout; + protected SessionCheckout $sessionCheckout; public function __construct( - Context $context, - array $data, - PaymentFee $feeHelper, + Context $context, + array $data, + PaymentFee $feeHelper, SessionCheckout $sessionCheckout - ) { + ) + { parent::__construct($context, $data); $this->feeHelper = $feeHelper; $this->sessionCheckout = $sessionCheckout; } + /** * Get title based on payment method config * @@ -33,29 +35,11 @@ public function getTitle(): string { try { $payment = $this->sessionCheckout - ->getQuote() - ->getPayment(); + ->getQuote() + ->getPayment(); return $this->feeHelper->getBuckarooPaymentFeeLabel($payment->getMethod()); } catch (\Throwable $th) { - return __('Fee'); - } - return __('Fee'); - } - - /** - * Get total from array of data - * - * @return float - */ - public function getTotal(): float - { - $totalData = $this->getSegment(); - if ( - isset($totalData['extension_attributes']['buckaroo_fee']) && - is_scalar($totalData['extension_attributes']['buckaroo_fee']) - ) { - return floatval($totalData['extension_attributes']['buckaroo_fee']); + return __('Payment Fee'); } - return 0; } } diff --git a/Magewire/Payment/Method/Giftcards.php b/Magewire/Payment/Method/Giftcards.php index 331620c..bc6ad1b 100644 --- a/Magewire/Payment/Method/Giftcards.php +++ b/Magewire/Payment/Method/Giftcards.php @@ -16,6 +16,7 @@ use Buckaroo\Magento2\Model\Giftcard\Response\Giftcard as GiftcardResponse; use Buckaroo\Magento2\Model\Giftcard\Request\GiftcardInterface as GiftcardRequest; use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards as MethodConfigProvider; +use Magento\Framework\Pricing\Helper\Data as PricingHelper; class Giftcards extends Component\Form implements EvaluationInterface { @@ -34,6 +35,7 @@ class Giftcards extends Component\Form implements EvaluationInterface protected GiftcardResponse $giftcardResponse; protected Log $logger; + protected $pricingHelper; public function __construct( UrlInterface $urlBuilder, @@ -42,7 +44,8 @@ public function __construct( MethodConfigProvider $methodConfigProvider, GiftcardRequest $giftcardRequest, GiftcardResponse $giftcardResponse, - Log $logger + Log $logger, + PricingHelper $pricingHelper ) { $this->urlBuilder = $urlBuilder; $this->sessionCheckout = $sessionCheckout; @@ -51,6 +54,7 @@ public function __construct( $this->giftcardRequest = $giftcardRequest; $this->giftcardResponse = $giftcardResponse; $this->logger = $logger; + $this->pricingHelper = $pricingHelper; } /** @@ -150,7 +154,32 @@ public function applyGiftcard( } } + /** + * Convert and format price value for current store + * + * @param float $price + * @return float|string + */ + public function getFormattedPrice($price) + { + return $this->pricingHelper->currency($price, true, false); + } + public function getRemainingAmount() + { + $quote = $this->sessionCheckout->getQuote(); + + $grandTotal = round(floatval($quote->getGrandTotal()), 2); + + // Get the amount already paid through group transactions + $alreadyPaid = $this->groupTransaction->getAlreadyPaid($quote->getReservedOrderId()); + + // Calculate the remaining amount + $remainingAmount = $grandTotal - $alreadyPaid; + + // Ensure the remaining amount is never negative + $this->emit("remainingAmount", $this->getFormattedPrice($remainingAmount)); + } protected function getGiftcardResponse(Quote $quote, $response) { $this->giftcardResponse->set($response, $quote); @@ -183,8 +212,8 @@ protected function getGiftcardResponse(Quote $quote, $response) $this->giftcardResponse->getCurrency() ); } - return [ + 'remainder_amount_currency' => $this->getFormattedPrice($remainingAmount), 'remainder_amount' => $remainingAmount, 'already_paid' => $this->giftcardResponse->getAlreadyPaid($quote), 'remaining_amount_message' => $buttonMessage, diff --git a/Magewire/Payment/Method/PayByBank.php b/Magewire/Payment/Method/PayByBank.php new file mode 100644 index 0000000..916634d --- /dev/null +++ b/Magewire/Payment/Method/PayByBank.php @@ -0,0 +1,184 @@ + 'Saving Bank issuer' + ]; + + protected $rules = [ + 'issuer' => 'required' + ]; + + protected $messages = [ + 'issuer:required' => 'The bank issuer is required' + ]; + + protected SessionCheckout $sessionCheckout; + + protected CartRepositoryInterface $quoteRepository; + + protected Repository $assetRepo; + + protected ScopeConfigInterface $scopeConfig; + + + public function __construct( + Validator $validator, + SessionCheckout $sessionCheckout, + CartRepositoryInterface $quoteRepository, + Repository $assetRepo, + ScopeConfigInterface $scopeConfig, + + ) { + parent::__construct($validator); + + $this->sessionCheckout = $sessionCheckout; + $this->quoteRepository = $quoteRepository; + $this->assetRepo = $assetRepo; + $this->scopeConfig = $scopeConfig; + + } + + /** + * @throws LocalizedException + * @throws NoSuchEntityException + */ + public function mount(): void + { + $this->issuer = $this->getLastIssuer(); + } + + /** + * Listen for bank issuer been updated. + */ + public function updatedIssuer(string $value): ?string + { + $this->validateOnly(); + $value = empty($value) ? null : $value; + + try { + $quote = $this->sessionCheckout->getQuote(); + $quote->getPayment()->setAdditionalInformation('issuer', $value); + + $this->quoteRepository->save($quote); + } catch (LocalizedException $exception) { + $this->dispatchErrorMessage($exception->getMessage()); + } + + return $value; + } + + public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResultInterface + { + if ($this->issuer === null) { + return $resultFactory->createErrorMessageEvent() + ->withCustomEvent('payment:method:error') + ->withMessage('The bank issuer is required'); + } + + return $resultFactory->createSuccess(); + } + + public function getIssuers(): array + { + return [ + [ + 'name' => 'ABN AMRO', + 'code' => 'ABNANL2A', + 'imgName' => 'abnamro' + ], + [ + 'name' => 'ASN Bank', + 'code' => 'ASNBNL21', + 'imgName' => 'asnbank' + ], + [ + 'name' => 'ING', + 'code' => 'INGBNL2A', + 'imgName' => 'ing' + ], + [ + 'name' => 'Knab Bank', + 'code' => 'KNABNL2H', + 'imgName' => 'knab' + ], + [ + 'name' => 'Rabobank', + 'code' => 'RABONL2U', + 'imgName' => 'rabobank' + ], + [ + 'name' => 'RegioBank', + 'code' => 'RBRBNL21', + 'imgName' => 'regiobank' + ], + [ + 'name' => 'SNS Bank', + 'code' => 'SNSBNL2A', + 'imgName' => 'sns' + ], + [ + 'name' => 'N26', + 'code' => 'NTSBDEB1', + 'imgName' => 'n26' + ] + ]; + } + + public function getLastIssuer() + { + + $quote = $this->sessionCheckout->getQuote(); + + $customerId = $quote->getCustomerId(); + + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $customerRepository = $objectManager->get(\Magento\Customer\Api\CustomerRepositoryInterface::class); + + $customer = $customerRepository->getById($customerId); + + $customAttributes = $customer->getCustomAttributes(); + $issuerAttribute = $customAttributes['buckaroo_last_paybybank_issuer'] ?? null; + + if ($issuerAttribute) { + return $issuerAttribute->getValue(); + } else { + return $issuerAttribute; + } + + } + + public function getImageUrl(string $issuerImage): string + { + return $this->assetRepo->getUrl("Buckaroo_Magento2::images/ideal/{$issuerImage}.svg"); + } + + public function displayAsSelect($storeId = null): bool + { + return $this->scopeConfig->getValue( + MethodPayByBank::XPATH_PAYBYBANK_SELECTION_TYPE, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $storeId + ) === '2'; + } +} diff --git a/Model/MethodMetaData.php b/Model/MethodMetaData.php deleted file mode 100644 index f4b8c6e..0000000 --- a/Model/MethodMetaData.php +++ /dev/null @@ -1,39 +0,0 @@ -assetRepository = $assetRepository; - } - public function renderIcon(): string - { - $icon = parent::getData(self::ICON); - - if (!is_array($icon)) { - return ''; - } - $logoLink = $this->assetRepository->getUrl($icon['svg']); - return ''; - } -} diff --git a/Plugin/IconRenderer.php b/Plugin/IconRenderer.php new file mode 100644 index 0000000..04a328d --- /dev/null +++ b/Plugin/IconRenderer.php @@ -0,0 +1,32 @@ +assetRepository = $assetRepository; + } + + public function aroundRender( + IconRendererHyva $subject, + callable $proceed, + array $icon + ): string { + // Check if this is a Buckaroo method and handle it + if (isset($icon['svg']) && strpos($icon['svg'], 'Buckaroo_') !== false) { + $logoLink = $this->assetRepository->getUrl($icon['svg']); + return ''; + } + + // Otherwise, proceed with the default behavior + return $proceed($icon); + } +} diff --git a/Plugin/MethodList.php b/Plugin/MethodList.php index 29992a6..3134401 100644 --- a/Plugin/MethodList.php +++ b/Plugin/MethodList.php @@ -8,7 +8,7 @@ use Magento\Payment\Model\MethodInterface as PaymentMethodInterface; use Buckaroo\Magento2\Model\ConfigProvider\Method\ConfigProviderInterface; use Hyva\Checkout\ViewModel\Checkout\Payment\MethodList as HyvaMethodList; -use Buckaroo\HyvaCheckout\Model\MethodMetaDataFactory; +use Hyva\Checkout\Model\MethodMetaDataFactory; class MethodList implements \Magento\Framework\View\Element\Block\ArgumentInterface { @@ -51,8 +51,8 @@ private function getSvgLogo(string $methodCode): string $mappings = [ "afterpay2" => "svg/afterpay.svg", "afterpay20" => "svg/afterpay.svg", - "capayablein3" => "svg/in3.svg", - "capayablepostpay" => "svg/in3.svg", + "capayablein3" => "svg/ideal-in3.svg", + "capayablepostpay" => "svg/ideal-in3.svg", "creditcard" => "svg/creditcards.svg", "creditcards" => "svg/creditcards.svg", "giftcards" => "svg/giftcards.svg", @@ -66,11 +66,12 @@ private function getSvgLogo(string $methodCode): string "emandate" => "emandate.png", "pospayment" => "pos.png", "transfer" => "svg/sepa-credittransfer.svg", - "voucher" => "svg/vouchers.svg" + "voucher" => "svg/vouchers.svg", + "paybybank" => "paybybank.gif", ]; $name = "svg/{$method}.svg"; - + if(isset($mappings[$method])) { $name = $mappings[$method]; } diff --git a/README.md b/README.md index 109912f..f394bd9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Buckaroo has developed a cutting-edge Hyvä Checkout module as an extension for
## Requirements -* [Buckaroo Magento 2 plugin](https://github.com/buckaroo-it/Magento2/releases) version 1.46 or higher +* [Buckaroo Magento 2 plugin](https://github.com/buckaroo-it/Magento2/releases) version 1.50.1 or higher * Hyvä Checkout version 1.1.8 or higher
diff --git a/composer.json b/composer.json index 6634f2e..89b8c16 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,8 @@ "name": "buckaroo/magento2-hyva-checkout", "description": "Buckaroo Magento 2 hyva checkout extension", "require": { - "php": ">=8.1" + "php": ">=8.1", + "buckaroo/magento2": ">=1.50.1" }, "type": "magento2-module", "license": "CC-BY-NC-ND-3.0", @@ -20,7 +21,7 @@ "docs": "https://support.buckaroo.nl" }, "homepage": "https://www.buckaroo.nl", - "version" : "v1.1.2", + "version" : "v1.2.0", "minimum-stability": "stable", "autoload": { "files": [ diff --git a/etc/di.xml b/etc/di.xml index cfb41fd..35ef475 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -4,4 +4,8 @@ + + + + diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml index a88943f..b8d65da 100644 --- a/etc/frontend/di.xml +++ b/etc/frontend/di.xml @@ -14,7 +14,7 @@ \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService - + \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService @@ -35,6 +35,10 @@ \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService + \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService + \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService + \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService + \Buckaroo\HyvaCheckout\Model\Magewire\Payment\PlaceOrderService @@ -48,4 +52,4 @@ - \ No newline at end of file + diff --git a/view/frontend/layout/hyva_checkout_components.xml b/view/frontend/layout/hyva_checkout_components.xml index 69f5457..a14b10f 100644 --- a/view/frontend/layout/hyva_checkout_components.xml +++ b/view/frontend/layout/hyva_checkout_components.xml @@ -105,16 +105,6 @@ - - - - \Buckaroo\HyvaCheckout\Magewire\Payment\Method\Giropay - - - - @@ -195,6 +185,16 @@ + + + + \Buckaroo\HyvaCheckout\Magewire\Payment\Method\PayByBank + + + + @@ -202,9 +202,9 @@ - - \ No newline at end of file + diff --git a/view/frontend/templates/component/payment/after.phtml b/view/frontend/templates/component/payment/after.phtml index 8992e5f..02b78de 100644 --- a/view/frontend/templates/component/payment/after.phtml +++ b/view/frontend/templates/component/payment/after.phtml @@ -373,24 +373,59 @@ }, giftcards($el) { return Object.assign(hyva.formValidation($el), { - card:'', + card: '', pin: '', cardNumber: '', - canSubmit:false, + canSubmit: false, + + async update() { + await this.$wire.getRemainingAmount(); + }, + listenToUpdate(){ + this.$wire.on('remainingAmount', async (response) => { + this.updateGrandTotal(response); + }) + }, async formValid() { - try { - await this.validate(); - } catch (error) { - return false; - } - return true; + try { + await this.validate(); + } catch (error) { + return false; + } + return true; }, + async submit() { - if(!await this.formValid()) { + if (!await this.formValid()) { return; } await this.$wire.applyGiftcard(this.card, this.cardNumber, this.pin); }, + + listenToSubmit() { + this.$wire.on('giftcard_response', async (response) => { + if (response.error) { + this.displayError(response.error); + } else if (response.remainder_amount === undefined) { + this.displayError(response.message); + } else if (response.remainder_amount == 0) { + this.canSubmit = true; + await hyvaCheckout.order.place(); + } else if (response.remainder_amount != 0) { + this.displaySuccess(response); + this.updateGrandTotal(response.remainder_amount_currency); + } + }) + }, + updateGrandTotal(remainder_amount_currency) { + const grandTotalElement = document.querySelector('.grand_total .value'); + grandTotalElement.textContent = remainder_amount_currency + + setTimeout(function () { + grandTotalElement.textContent = remainder_amount_currency + + }, 2000); + }, displaySuccess(response) { window.dispatchEvent(new CustomEvent('buckaroo-modal-show', { detail: { @@ -405,6 +440,7 @@ } })); }, + displayError(message) { window.dispatchEvent(new CustomEvent('buckaroo-modal-show', { detail: { @@ -415,30 +451,18 @@ } })); }, - listenToSubmit() { - this.$wire.on('giftcard_response', async (response) => { - if (response.error) { - this.displayError(response.error); - } else if(response.remainder_amount === undefined) { - this.displayError(response.message); - } else if (response.remainder_amount == 0) { - this.canSubmit = true; - await hyvaCheckout.order.place(); - } else if (response.remainder_amount != 0) { - this.displaySuccess(response); - } - }) - }, + register() { this.listenToSubmit(); + this.update(); + this.listenToUpdate(); window.buckarooTask = async () => { - if(!this.canSubmit) { + if (!this.canSubmit) { await this.submit(); } }; }, - - }) + }); }, mrCash($el) { return Object.assign(hyva.formValidation($el), { @@ -566,4 +590,4 @@ } } - \ No newline at end of file + diff --git a/view/frontend/templates/component/payment/method/giropay.phtml b/view/frontend/templates/component/payment/method/giropay.phtml deleted file mode 100644 index 5bcd288..0000000 --- a/view/frontend/templates/component/payment/method/giropay.phtml +++ /dev/null @@ -1,28 +0,0 @@ -getGenderList(); - -?> -
-
- - - hasError('bic')) : ?> -
escapeHtmlAttr($magewire->getError('bic')) ?>
- -
-
diff --git a/view/frontend/templates/component/payment/method/paybybank.phtml b/view/frontend/templates/component/payment/method/paybybank.phtml new file mode 100644 index 0000000..1ad4044 --- /dev/null +++ b/view/frontend/templates/component/payment/method/paybybank.phtml @@ -0,0 +1,47 @@ +getIssuers(); + +?> +
+
+ displayAsSelect()) { ?> + + + + +

escapeHtml(__('Select a bank:')); ?>

+ +
+ issuer ? 'checked' : '' ?> + /> + +
+ + +
+
diff --git a/view/frontend/templates/total-segments/fee.phtml b/view/frontend/templates/total-segments/fee.phtml index 77923b8..b00a1fa 100644 --- a/view/frontend/templates/total-segments/fee.phtml +++ b/view/frontend/templates/total-segments/fee.phtml @@ -14,14 +14,16 @@ use Hyva\Checkout\ViewModel\Checkout\Formatter as FormatterViewModel; use Hyva\Theme\Model\ViewModelRegistry; $formatterViewModel = $viewModels->require(FormatterViewModel::class); -$total = $block->getTotal(); -if ($total != 0) { +$segment = $block->getSegment(); +if ($segment['value'] != 0) { ?>
- + escapeHtml($block->getTitle()) ?> - currency($total ?? 0) ?> + + currency($segment['value'] ?? 0) ?> +