diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c6db1c4ce..a80d56674 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,5 +13,5 @@ jobs: PHP_VERSION: 7.2 PLUGIN_MAIN_FILE: mollie-payments-for-woocommerce.php ARCHIVE_NAME: mollie-payments-for-woocommerce - PRE_SCRIPT: | - echo 'hello world!'; + POST_SCRIPT: | + mv dist/WooCommerce dist/mollie-payments-for-woocommerce diff --git a/mollie-payments-for-woocommerce.php b/mollie-payments-for-woocommerce.php index b62a5af25..e87005d15 100644 --- a/mollie-payments-for-woocommerce.php +++ b/mollie-payments-for-woocommerce.php @@ -3,16 +3,16 @@ * Plugin Name: Mollie Payments for WooCommerce * Plugin URI: https://www.mollie.com * Description: Accept payments in WooCommerce with the official Mollie plugin - * Version: 7.5.1 + * Version: 7.5.2 * Author: Mollie * Author URI: https://www.mollie.com * Requires at least: 5.0 - * Tested up to: 6.4 + * Tested up to: 6.5 * Text Domain: mollie-payments-for-woocommerce * Domain Path: /languages * License: GPLv2 or later * WC requires at least: 3.9 - * WC tested up to: 8.5 + * WC tested up to: 8.7 * Requires PHP: 7.2 */ declare(strict_types=1); diff --git a/public/images/bancomatpay.svg b/public/images/bancomatpay.svg new file mode 100644 index 000000000..6d0b5e845 --- /dev/null +++ b/public/images/bancomatpay.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/js/blocks/molliePaymentMethod.js b/resources/js/blocks/molliePaymentMethod.js index 39303c616..3eeb5bc07 100644 --- a/resources/js/blocks/molliePaymentMethod.js +++ b/resources/js/blocks/molliePaymentMethod.js @@ -214,7 +214,9 @@ const MollieComponent = (props) => { } function fieldMarkup(id, fieldType, label, action, value) { - return
+ const className = "wc-block-components-text-input wc-block-components-address-form__" + id; + return
+
} if (item.name === "mollie_wc_gateway_billie"){ @@ -231,7 +233,7 @@ const MollieComponent = (props) => { fields.push(fieldMarkup("billing-birthdate", "date", birthdateField, updateBirthdate, inputBirthdate)); if (!isPhoneFieldVisible) { const phoneField = item.phonePlaceholder ? item.phonePlaceholder : "Phone"; - fields.push(fieldMarkup("billing-phone", "tel", phoneField, updatePhone, inputPhone)); + fields.push(fieldMarkup("billing-phone-in3", "tel", phoneField, updatePhone, inputPhone)); } return <>{fields}; diff --git a/resources/js/mollieBillie.js b/resources/js/mollieBillie.js deleted file mode 100644 index ad31361e1..000000000 --- a/resources/js/mollieBillie.js +++ /dev/null @@ -1,32 +0,0 @@ -import {maybeRequireField, saveOriginalField} from "./wooCheckoutFieldsUtility"; - -( - function ({jQuery}) { - let gateway = 'mollie_wc_gateway_billie'; - let inputCompanyName = 'billing_company'; - let originalBillingCompanyField = saveOriginalField(inputCompanyName, {}); - let companyFieldId = 'billing_company_field'; - let companyField = jQuery('form[name="checkout"] p#billing_company_field'); - let positionCompanyField = 'li.wc_payment_method.payment_method_mollie_wc_gateway_billie'; - let companyMarkup = '

' - + '' - + '' - + '' - + '' - + '

' - - jQuery(function () { - jQuery('body') - .on('updated_checkout payment_method_selected', function () { - companyField = maybeRequireField(companyField, positionCompanyField, companyMarkup, inputCompanyName, companyFieldId, originalBillingCompanyField, gateway); - }); - }); - } -)( - window -) - - - diff --git a/resources/js/mollieBlockIndex.js b/resources/js/mollieBlockIndex.js index 641511e57..8f4f9e3c2 100644 --- a/resources/js/mollieBlockIndex.js +++ b/resources/js/mollieBlockIndex.js @@ -7,33 +7,30 @@ import molliePaymentMethod from './blocks/molliePaymentMethod' } window.onload = (event) => { const { registerPaymentMethod } = wc.wcBlocksRegistry; + const { checkoutData, defaultFields } = wc.wcSettings.allSettings; + const { billing_address, shipping_address } = checkoutData; const { ajaxUrl, filters, gatewayData, availableGateways } = mollieBlockData.gatewayData; const {useEffect} = wp.element; const isAppleSession = typeof window.ApplePaySession === "function" const isBlockEditor = !!wp?.blockEditor; function getCompanyField() { - let shippingCompany = document.getElementById('shipping-company'); - let billingCompany = document.getElementById('billing-company'); + let shippingCompany = shipping_address.company ?? false; + let billingCompany = billing_address.company ?? false; return shippingCompany ? shippingCompany : billingCompany; } function getPhoneField() { - const shippingPhone = document.getElementById('shipping-phone'); - const billingPhone = document.getElementById('billing-phone'); + const shippingPhone = shipping_address.phone ?? false; + const billingPhone = billing_address.phone ?? false return billingPhone || shippingPhone; } - function isFieldVisible(field) - { - return field && field.style.display !== 'none'; - } - let companyField = getCompanyField(); - const isCompanyFieldVisible = companyField && isFieldVisible(companyField); - const companyNameString = companyField && companyField.parentNode.querySelector('label') ? companyField.parentNode.querySelector('label').innerHTML : false; - let phoneField = getPhoneField(); - const isPhoneFieldVisible = phoneField && isFieldVisible(phoneField); - const phoneString = phoneField && phoneField.parentNode.querySelector('label') ? phoneField.parentNode.querySelector('label').innerHTML : false; + + const isCompanyFieldVisible = getCompanyField(); + const companyNameString = defaultFields.company.label + const isPhoneFieldVisible = getPhoneField(); + const phoneString = defaultFields.phone.label let requiredFields = { 'companyNameString': companyNameString, 'phoneString': phoneString, diff --git a/src/Assets/AssetsModule.php b/src/Assets/AssetsModule.php index 5a97e4e73..da8c7a6e4 100644 --- a/src/Assets/AssetsModule.php +++ b/src/Assets/AssetsModule.php @@ -276,13 +276,6 @@ protected function registerFrontendScripts(string $pluginUrl, string $pluginPath (string) filemtime($this->getPluginPath($pluginPath, '/public/js/gatewaySurcharge.min.js')), true ); - wp_register_script( - 'mollie-billie-classic-handles', - $this->getPluginUrl($pluginUrl, '/public/js/mollieBillie.min.js'), - ['underscore', 'jquery'], - (string) filemtime($this->getPluginPath($pluginPath, '/public/js/mollieBillie.min.js')), - true - ); } public function registerBlockScripts(string $pluginUrl, string $pluginPath): void diff --git a/src/Buttons/ApplePayButton/AppleAjaxRequests.php b/src/Buttons/ApplePayButton/AppleAjaxRequests.php index ef8d2d603..6643cffe1 100644 --- a/src/Buttons/ApplePayButton/AppleAjaxRequests.php +++ b/src/Buttons/ApplePayButton/AppleAjaxRequests.php @@ -568,7 +568,7 @@ protected function calculateTotalsCartPage( $cart, $customerAddress, $shippingMethodId, - $shippingMethodId['identifier'] + $shippingMethodId['identifier'] ?? null ); } $cart->calculate_shipping(); diff --git a/src/Gateway/GatewayModule.php b/src/Gateway/GatewayModule.php index d73dfb51b..ad6520696 100644 --- a/src/Gateway/GatewayModule.php +++ b/src/Gateway/GatewayModule.php @@ -6,8 +6,8 @@ namespace Mollie\WooCommerce\Gateway; -use Automattic\WooCommerce\Admin\Overrides\Order; use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController; +use Automattic\WooCommerce\StoreApi\Exceptions\RouteException; use Mollie\WooCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use Mollie\WooCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; use Mollie\WooCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule; @@ -103,7 +103,7 @@ public function services(): array } return $availableMethods; }, - 'gateway.getKlarnaPaymentMethodsAfterFeatureFlag' => static function (ContainerInterface $container): array { + 'gateway.getPaymentMethodsAfterFeatureFlag' => static function (ContainerInterface $container): array { $availablePaymentMethods = $container->get('gateway.listAllMethodsAvailable'); $klarnaOneFlag = apply_filters('inpsyde.feature-flags.mollie-woocommerce.klarna_one_enabled', true); if (!$klarnaOneFlag) { @@ -111,6 +111,12 @@ public function services(): array return $method['id'] !== Constants::KLARNA; }); } + $bancomatpayFlag = apply_filters('inpsyde.feature-flags.mollie-woocommerce.bancomatpay_enabled', true); + if (!$bancomatpayFlag) { + return array_filter($availablePaymentMethods, static function ($method) { + return $method['id'] !== Constants::BANCOMATPAY; + }); + } return $availablePaymentMethods; }, 'gateway.isSDDGatewayEnabled' => static function (ContainerInterface $container): bool { @@ -264,7 +270,14 @@ static function () { [$this, 'in3FieldsMandatoryPayForOrder'], 11 ); + add_action( + 'woocommerce_checkout_posted_data', + [$this, 'switchFields'], + 11 + ); + add_action('woocommerce_rest_checkout_process_payment_with_context', [$this, 'addPhoneWhenRest'], 11); } + // Set order to paid and processed when eventually completed without Mollie add_action('woocommerce_payment_complete', [$this, 'setOrderPaidByOtherGateway'], 10, 1); $appleGateway = isset($container->get('gateway.instances')['mollie_wc_gateway_applepay']) ? $container->get( @@ -314,6 +327,17 @@ static function ($paymentContext) { } ); add_action('add_meta_boxes_woocommerce_page_wc-orders', [$this, 'addShopOrderMetabox'], 10); + add_filter('woocommerce_form_field_args', static function ($args, $key, $value) use ($container) { + if ($key !== 'billing_phone') { + return $args; + } + if ($args['required'] === true) { + update_option('mollie_wc_is_phone_required_flag', true); + } else { + update_option('mollie_wc_is_phone_required_flag', false); + } + return $args; + }, 10, 3); return true; } @@ -583,7 +607,7 @@ public function instantiatePaymentMethodGateways(ContainerInterface $container): protected function instantiatePaymentMethods($container): array { $paymentMethods = []; - $listAllAvailablePaymentMethods = $container->get('gateway.getKlarnaPaymentMethodsAfterFeatureFlag'); + $listAllAvailablePaymentMethods = $container->get('gateway.getPaymentMethodsAfterFeatureFlag'); $iconFactory = $container->get(IconFactory::class); assert($iconFactory instanceof IconFactory); $settingsHelper = $container->get('settings.settings_helper'); @@ -630,18 +654,18 @@ public function BillieFieldsMandatory($fields, $errors) public function in3FieldsMandatory($fields, $errors) { $gatewayName = "mollie_wc_gateway_in3"; - $phoneField = 'billing_phone'; + $phoneField = 'billing_phone_in3'; $birthdateField = self::FIELD_IN3_BIRTHDATE; $phoneLabel = __('Phone', 'mollie-payments-for-woocommerce'); $birthDateLabel = __('Birthdate', 'mollie-payments-for-woocommerce'); - $fields = $this->addPaymentMethodMandatoryFields($fields, $gatewayName, $phoneField, $phoneLabel, $errors); + $fields = $this->addPaymentMethodMandatoryFieldsPhoneVerification($fields, $gatewayName, $phoneField, $phoneLabel, $errors); return $this->addPaymentMethodMandatoryFields($fields, $gatewayName, $birthdateField, $birthDateLabel, $errors); } /** - * @param Order $order + * @param $order */ - public function in3FieldsMandatoryPayForOrder(Order $order) + public function in3FieldsMandatoryPayForOrder($order) { $paymentMethod = filter_input(INPUT_POST, 'payment_method', FILTER_SANITIZE_SPECIAL_CHARS) ?? false; @@ -661,6 +685,21 @@ public function in3FieldsMandatoryPayForOrder(Order $order) 'error' ); } + $phoneValue = filter_input(INPUT_POST, 'billing_phone_in3', FILTER_SANITIZE_SPECIAL_CHARS) ?? false; + $phoneValue = $phoneValue && $this->isPhoneValid($phoneValue) ? $phoneValue : false; + $phoneLabel = __('Phone', 'mollie-payments-for-woocommerce'); + + if (!$phoneValue) { + wc_add_notice( + sprintf( + __('%s is a required field. Valid phone format +000000000', 'mollie-payments-for-woocommerce'), + "$phoneLabel" + ), + 'error' + ); + } else { + $order->set_billing_phone($phoneValue); + } } /** @@ -723,4 +762,91 @@ public function addPaymentMethodMandatoryFields($fields, string $gatewayName, st return $fields; } + + public function addPaymentMethodMandatoryFieldsPhoneVerification( + $fields, + string $gatewayName, + string $field, + string $fieldLabel, + $errors + ) { + if ($fields['payment_method'] !== $gatewayName) { + return $fields; + } + if (isset($fields['billing_phone']) && $this->isPhoneValid($fields['billing_phone'])) { + return $fields; + } + $fieldPosted = filter_input(INPUT_POST, $field, FILTER_SANITIZE_SPECIAL_CHARS) ?? false; + if (!$fieldPosted) { + $errors->add( + 'validation', + sprintf( + __('%s is a required field.', 'woocommerce'), + "$fieldLabel" + ) + ); + return $fields; + } + + if (!$this->isPhoneValid($fieldPosted)) { + $errors->add( + 'validation', + sprintf( + __('%s is not a valid phone number. Valid phone format +00000000000', 'woocommerce'), + "$fieldLabel" + ) + ); + return $fields; + } else { + $fields['billing_phone'] = $fieldPosted; + } + return $fields; + } + + public function switchFields($data) + { + if (isset($data['payment_method']) && $data['payment_method'] === 'mollie_wc_gateway_in3') { + $fieldPosted = filter_input(INPUT_POST, 'billing_phone_in3', FILTER_SANITIZE_SPECIAL_CHARS) ?? false; + if ($fieldPosted) { + $data['billing_phone'] = !empty($fieldPosted) ? $fieldPosted : $data['billing_phone']; + } + } + if (isset($data['payment_method']) && $data['payment_method'] === 'mollie_wc_gateway_billie') { + $fieldPosted = filter_input(INPUT_POST, 'billing_company_billie', FILTER_SANITIZE_SPECIAL_CHARS) ?? false; + if ($fieldPosted) { + $data['billing_company'] = !empty($fieldPosted) ? $fieldPosted : $data['billing_company']; + } + } + return $data; + } + + private function isPhoneValid($billing_phone) + { + return preg_match('/^\+[1-9]\d{10,13}$/', $billing_phone); + } + + public function addPhoneWhenRest($arrayContext) + { + $context = $arrayContext; + $phoneMandatoryGateways = ['mollie_wc_gateway_in3']; + $paymentMethod = $context->payment_data['payment_method']; + if (in_array($paymentMethod, $phoneMandatoryGateways)) { + $billingPhone = $context->order->get_billing_phone(); + if (!empty($billingPhone) && $this->isPhoneValid($billingPhone)) { + return; + } + $billingPhone = $context->payment_data['billing_phone']; + if ($billingPhone) { + $context->order->set_billing_phone($billingPhone); + $context->order->save(); + } else { + $message = __('Please introduce a valid phone number. +00000000000', 'mollie-payments-for-woocommerce'); + throw new RouteException( + 'woocommerce_rest_checkout_process_payment_error', + $message, + 402 + ); + } + } + } } diff --git a/src/Log/WcPsrLoggerAdapter.php b/src/Log/WcPsrLoggerAdapter.php index ce9ca3f1b..781a872fc 100644 --- a/src/Log/WcPsrLoggerAdapter.php +++ b/src/Log/WcPsrLoggerAdapter.php @@ -80,7 +80,7 @@ public function log($level, $message, array $context = []) } if (\WC_Log_Levels::get_level_severity($wcLevel) < \WC_Log_Levels::get_level_severity($this->loggingLevel)) { - throw new InvalidArgumentException("Unknown log level ${$wcLevel}"); + throw new InvalidArgumentException("Unknown log level {$wcLevel}"); } if (isset($context['source']) && $context['source'] !== $this-> loggerSource) { diff --git a/src/MerchantCapture/MerchantCaptureModule.php b/src/MerchantCapture/MerchantCaptureModule.php index 697a457f8..0bdca1dfa 100644 --- a/src/MerchantCapture/MerchantCaptureModule.php +++ b/src/MerchantCapture/MerchantCaptureModule.php @@ -147,13 +147,17 @@ public function run(ContainerInterface $container): bool add_action('init', static function () use ($container) { $pluginId = $container->get('shared.plugin_id'); $captureSettings = new MollieCaptureSettings(); - if (!apply_filters('mollie_wc_gateway_enable_merchant_capture_module', false)) { + if (!apply_filters('mollie_wc_gateway_enable_merchant_capture_module', true)) { return; } add_action( $pluginId . '_after_webhook_action', - static function (Payment $payment, WC_Order $order) use ($container) { + static function ($payment, WC_Order $order) use ($container) { + + if (!$payment instanceof Payment) { + return; + } if ($payment->isAuthorized()) { if (!$payment->getAmountCaptured() == 0.0) { diff --git a/src/Payment/MollieObject.php b/src/Payment/MollieObject.php index 0f362bcf2..9a69a834a 100644 --- a/src/Payment/MollieObject.php +++ b/src/Payment/MollieObject.php @@ -588,13 +588,13 @@ protected function addMandateIdMetaToFirstPaymentSubscriptionOrder( $subscription->update_meta_data('_mollie_payment_id', $payment->id); $subscription->set_payment_method('mollie_wc_gateway_' . $payment->method); $subscription->save(); - $subcriptionParentOrder = $subscription->get_parent(); - if ($subcriptionParentOrder) { - $subcriptionParentOrder->update_meta_data( + $subscriptionParentOrder = $subscription->get_parent(); + if ($subscriptionParentOrder) { + $subscriptionParentOrder->update_meta_data( '_mollie_mandate_id', $payment->mandateId ); - $subcriptionParentOrder->save(); + $subscriptionParentOrder->save(); } } } diff --git a/src/Payment/PaymentService.php b/src/Payment/PaymentService.php index c2123d869..f866de5fa 100644 --- a/src/Payment/PaymentService.php +++ b/src/Payment/PaymentService.php @@ -467,6 +467,11 @@ protected function processAsMolliePayment( $data, $order ); + $data = apply_filters( + 'woocommerce_' . $this->gateway->id . 'payment_args', + $data, + $order + ); try { // Only enable this for hardcore debugging! @@ -486,7 +491,7 @@ protected function processAsMolliePayment( : '', ]; - $this->logger->debug($apiCallLog); + $this->logger->debug(json_encode($apiCallLog, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); // Try as simple payment $paymentObject = $this->apiHelper->getApiClient( @@ -524,6 +529,21 @@ protected function processPaymentForMollie( // PROCESS REGULAR PAYMENT AS MOLLIE ORDER // if ($molliePaymentType === self::PAYMENT_METHOD_TYPE_ORDER) { + // if the capture is set to manual, and this is a credit card payment, we need to create a payment instead of an order + $captureType = get_option('mollie-payments-for-woocommerce_place_payment_onhold'); + if ($captureType === 'later_capture' && $this->gateway->id === 'mollie_wc_gateway_creditcard') { + $this->logger->debug( + "{$this->gateway->id}: Create payment for order {$orderId} capture set to manual", + [true] + ); + + $paymentObject = $this->processAsMolliePayment( + $order, + $customer_id, + $apiKey + ); + return $paymentObject; + } $this->logger->debug( "{$this->gateway->id}: Create Mollie payment object for order {$orderId}", [true] diff --git a/src/PaymentMethods/AbstractPaymentMethod.php b/src/PaymentMethods/AbstractPaymentMethod.php index 1b16d1f3b..a83cee26f 100644 --- a/src/PaymentMethods/AbstractPaymentMethod.php +++ b/src/PaymentMethods/AbstractPaymentMethod.php @@ -297,9 +297,9 @@ public function defaultSettings(): array { $fields = $this->getAllFormFields(); //remove setting title fields - $fields = array_filter($fields, static function ($key) { - return !is_numeric($key); - }, ARRAY_FILTER_USE_KEY); + $fields = array_filter($fields, static function ($field) { + return isset($field['type']) && $field['type'] !== 'title'; + }); //we don't save the default description or title, in case the language changes unset($fields['description']); unset($fields['title']); diff --git a/src/PaymentMethods/Bancomatpay.php b/src/PaymentMethods/Bancomatpay.php new file mode 100644 index 000000000..054ef951d --- /dev/null +++ b/src/PaymentMethods/Bancomatpay.php @@ -0,0 +1,31 @@ + 'bancomatpay', + 'defaultTitle' => __('Bancomat Pay', 'mollie-payments-for-woocommerce'), + 'settingsDescription' => '', + 'defaultDescription' => '', + 'paymentFields' => false, + 'instructions' => false, + 'supports' => [ + 'products', + 'refunds', + ], + 'filtersOnBuild' => false, + 'confirmationDelayed' => false, + ]; + } + + public function getFormFields($generalFormFields): array + { + return $generalFormFields; + } +} diff --git a/src/PaymentMethods/Banktransfer.php b/src/PaymentMethods/Banktransfer.php index ab946c46c..c27503213 100644 --- a/src/PaymentMethods/Banktransfer.php +++ b/src/PaymentMethods/Banktransfer.php @@ -82,7 +82,7 @@ public function getFormFields($generalFormFields): array public function filtersOnBuild() { - add_filter('woocommerce_mollie_wc_gateway_' . $this->getProperty('id') . '_args', function (array $args, \WC_Order $order): array { + add_filter('woocommerce_mollie_wc_gateway_' . $this->getProperty('id') . 'payment_args', function (array $args, \WC_Order $order): array { return $this->addPaymentArguments($args, $order); }, 10, 2); } diff --git a/src/PaymentMethods/Billie.php b/src/PaymentMethods/Billie.php index 720aed889..369f49521 100644 --- a/src/PaymentMethods/Billie.php +++ b/src/PaymentMethods/Billie.php @@ -16,7 +16,7 @@ protected function getConfig(): array 'mollie-payments-for-woocommerce' ), 'defaultDescription' => '', - 'paymentFields' => false, + 'paymentFields' => true, 'instructions' => false, 'supports' => [ 'products', diff --git a/src/PaymentMethods/Constants.php b/src/PaymentMethods/Constants.php index 9ff73d941..6f62e6b27 100644 --- a/src/PaymentMethods/Constants.php +++ b/src/PaymentMethods/Constants.php @@ -10,4 +10,6 @@ class Constants public const KLARNA = 'klarna'; public const DIRECTDEBIT = 'directdebit'; public const BANKTRANSFER = 'banktransfer'; + + public const BANCOMATPAY = 'bancomatpay'; } diff --git a/src/PaymentMethods/Giftcard.php b/src/PaymentMethods/Giftcard.php index 395016fa3..dbbd3895c 100644 --- a/src/PaymentMethods/Giftcard.php +++ b/src/PaymentMethods/Giftcard.php @@ -73,6 +73,11 @@ protected function getConfig(): array public function getFormFields($generalFormFields): array { + $searchKey = 'advanced'; + $keys = array_keys($generalFormFields); + $index = array_search($searchKey, $keys); + $before = array_slice($generalFormFields, 0, $index + 1, true); + $after = array_slice($generalFormFields, $index + 1, null, true); $paymentMethodFormFields = [ 'issuers_dropdown_shown' => [ 'title' => __( @@ -105,6 +110,8 @@ public function getFormFields($generalFormFields): array 'default' => __('Select your gift card', 'mollie-payments-for-woocommerce'), ], ]; - return array_merge($generalFormFields, $paymentMethodFormFields); + $before = array_merge($before, $paymentMethodFormFields); + $formFields = array_merge($before, $after); + return $formFields; } } diff --git a/src/PaymentMethods/Ideal.php b/src/PaymentMethods/Ideal.php index c02ee7e75..006ea6d95 100644 --- a/src/PaymentMethods/Ideal.php +++ b/src/PaymentMethods/Ideal.php @@ -29,6 +29,11 @@ public function getConfig(): array public function getFormFields($generalFormFields): array { + $searchKey = 'advanced'; + $keys = array_keys($generalFormFields); + $index = array_search($searchKey, $keys); + $before = array_slice($generalFormFields, 0, $index + 1, true); + $after = array_slice($generalFormFields, $index + 1, null, true); $paymentMethodFormFieds = [ 'issuers_dropdown_shown' => [ 'title' => __('Show iDEAL banks dropdown', 'mollie-payments-for-woocommerce'), @@ -55,6 +60,8 @@ public function getFormFields($generalFormFields): array 'default' => __('Select your bank', 'mollie-payments-for-woocommerce'), ], ]; - return array_merge($generalFormFields, $paymentMethodFormFieds); + $before = array_merge($before, $paymentMethodFormFieds); + $formFields = array_merge($before, $after); + return $formFields; } } diff --git a/src/PaymentMethods/Kbc.php b/src/PaymentMethods/Kbc.php index 5c220cac5..4005b83fd 100644 --- a/src/PaymentMethods/Kbc.php +++ b/src/PaymentMethods/Kbc.php @@ -28,6 +28,11 @@ protected function getConfig(): array public function getFormFields($generalFormFields): array { + $searchKey = 'advanced'; + $keys = array_keys($generalFormFields); + $index = array_search($searchKey, $keys); + $before = array_slice($generalFormFields, 0, $index + 1, true); + $after = array_slice($generalFormFields, $index + 1, null, true); $paymentMethodFormFieds = [ 'issuers_dropdown_shown' => [ 'title' => __( @@ -60,6 +65,8 @@ public function getFormFields($generalFormFields): array 'default' => __('Select your bank', 'mollie-payments-for-woocommerce'), ], ]; - return array_merge($generalFormFields, $paymentMethodFormFieds); + $before = array_merge($before, $paymentMethodFormFieds); + $formFields = array_merge($before, $after); + return $formFields; } } diff --git a/src/PaymentMethods/PaymentFieldsStrategies/BancomatpayFieldsStrategy.php b/src/PaymentMethods/PaymentFieldsStrategies/BancomatpayFieldsStrategy.php new file mode 100644 index 000000000..0952e3924 --- /dev/null +++ b/src/PaymentMethods/PaymentFieldsStrategies/BancomatpayFieldsStrategy.php @@ -0,0 +1,60 @@ +getOrderIdOnPayForOrderPage(); + $phoneValue = $order->get_billing_phone(); + $showPhoneField = true; + } + + if (is_checkout() && !is_checkout_pay_page() && !$isPhoneRequired) { + $showPhoneField = true; + } + + if ($showPhoneField) { + $this->phoneNumber($phoneValue); + } + } + + protected function getOrderIdOnPayForOrderPage() + { + global $wp; + $orderId = absint($wp->query_vars['order-pay']); + return wc_get_order($orderId); + } + + protected function phoneNumber($phoneValue) + { + $phoneValue = $phoneValue ?: ''; + ?> +

+ + + + +

+ getOrderIdOnPayForOrderPage(); + $showCompanyField = empty($order->get_billing_company()); + } + + if (is_checkout() && !is_checkout_pay_page()) { + $showCompanyField = true; + } + + if ($showCompanyField) { + $this->company(); + } + } + + protected function getOrderIdOnPayForOrderPage() + { + global $wp; + $orderId = absint($wp->query_vars['order-pay']); + return wc_get_order($orderId); + } + + protected function company() + { + ?> +

+ + + + +

+ checkSvgIssuers($issuers); - $issuerImageSvg && ($html .= ''); - $html .= $issuer->name; - echo esc_html(wpautop(wptexturize($html))); + if ($issuerImageSvg && isset($issuer->name)) { + $issuerImageSvg = esc_url($issuerImageSvg); + $issuerName = esc_html($issuer->name); + $html .= '' . $issuerName; + } + //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo wpautop(wptexturize($html)); return; } diff --git a/src/PaymentMethods/PaymentFieldsStrategies/In3FieldsStrategy.php b/src/PaymentMethods/PaymentFieldsStrategies/In3FieldsStrategy.php index 47a0d762d..3c0fdcffa 100644 --- a/src/PaymentMethods/PaymentFieldsStrategies/In3FieldsStrategy.php +++ b/src/PaymentMethods/PaymentFieldsStrategies/In3FieldsStrategy.php @@ -7,33 +7,31 @@ class In3FieldsStrategy implements PaymentFieldsStrategyI { const FIELD_BIRTHDATE = "billing_birthdate"; - const FIELD_PHONE = "billing_phone"; + const FIELD_PHONE = "billing_phone_in3"; public function execute($gateway, $dataHelper) { $showBirthdateField = false; $showPhoneField = false; + $isPhoneRequired = get_option('mollie_wc_is_phone_required_flag'); + $phoneValue = false; if (is_checkout_pay_page()) { - $order = $this->getOrderIdOnPayForOrderPage(); - $showPhoneField = empty($order->get_billing_phone()); $showBirthdateField = true; + $showPhoneField = true; + $order = $this->getOrderIdOnPayForOrderPage(); + $phoneValue = $order->get_billing_phone(); } + if (is_checkout() && !is_checkout_pay_page() && !$isPhoneRequired) { + $showPhoneField = true; + } if (is_checkout() && !is_checkout_pay_page()) { - $checkoutFields = WC()->checkout()->get_checkout_fields(); - - if (!isset($checkoutFields["billing"][self::FIELD_PHONE])) { - $showPhoneField = true; - } - - if (!isset($checkoutFields["billing"][self::FIELD_BIRTHDATE])) { - $showBirthdateField = true; - } + $showBirthdateField = true; } if ($showPhoneField) { - $this->phoneNumber(); + $this->phoneNumber($phoneValue); } if ($showBirthdateField) { @@ -63,8 +61,9 @@ protected function dateOfBirth()

'yes', ], - [ + 'display' => [ 'id' => $defaultTitle . '_' . 'title', 'title' => sprintf( /* translators: Placeholder 1: Gateway title */ @@ -37,20 +37,6 @@ public function gatewayFormFields( ), 'type' => 'title', ], - 'title' => [ - 'title' => __('Title', 'mollie-payments-for-woocommerce'), - 'type' => 'text', - /* translators: Placeholder 1: Gateway title */ - 'description' => sprintf( - __( - 'This controls the title which the user sees during checkout. Default %s', - 'mollie-payments-for-woocommerce' - ), - $defaultTitle - ), - 'default' => $defaultTitle, - 'desc_tip' => true, - ], 'use_api_title' => [ 'title' => __( 'Use API dynamic title and gateway logo', @@ -60,18 +46,18 @@ public function gatewayFormFields( 'label' => __('Retrieve the gateway title and logo from the Mollie API', 'mollie-payments-for-woocommerce'), 'default' => 'no', ], - 'description' => [ - 'title' => __('Description', 'mollie-payments-for-woocommerce'), - 'type' => 'textarea', - /* translators: Placeholder 1: Gateway description */ + 'title' => [ + 'title' => __('Title', 'mollie-payments-for-woocommerce'), + 'type' => 'text', + /* translators: Placeholder 1: Gateway title */ 'description' => sprintf( __( - 'Payment method description that the customer will see on your checkout. Default %s', + 'This controls the title which the user sees during checkout. Default %s', 'mollie-payments-for-woocommerce' ), - $defaultDescription + $defaultTitle ), - 'default' => $defaultDescription, + 'default' => $defaultTitle, 'desc_tip' => true, ], 'display_logo' => [ @@ -86,33 +72,6 @@ public function gatewayFormFields( ), 'default' => 'yes', ], - [ - 'id' => $defaultTitle . '_' . 'title', - 'title' => sprintf(__( - 'Sales countries', - 'mollie-payments-for-woocommerce' - )), - 'type' => 'title', - ], - 'allowed_countries' => [ - 'title' => __( - 'Sell to specific countries', - 'mollie-payments-for-woocommerce' - ), - 'desc' => '', - 'css' => 'min-width: 350px;', - 'default' => [], - 'type' => 'multi_select_countries', - ], - [ - 'id' => $defaultTitle . '_' . 'custom_logo', - 'title' => sprintf( - /* translators: Placeholder 1: Gateway title */ - __('%s custom logo', 'mollie-payments-for-woocommerce'), - $defaultTitle - ), - 'type' => 'title', - ], 'enable_custom_logo' => [ 'title' => __( 'Enable custom logo', @@ -141,7 +100,39 @@ public function gatewayFormFields( ), 'desc_tip' => true, ], - [ + 'description' => [ + 'title' => __('Description', 'mollie-payments-for-woocommerce'), + 'type' => 'textarea', + /* translators: Placeholder 1: Gateway description */ + 'description' => sprintf( + __( + 'Payment method description that the customer will see on your checkout. Default %s', + 'mollie-payments-for-woocommerce' + ), + $defaultDescription + ), + 'default' => $defaultDescription, + 'desc_tip' => true, + ], + 'sales' => [ + 'id' => $defaultTitle . '_' . 'title', + 'title' => sprintf(__( + 'Sales countries', + 'mollie-payments-for-woocommerce' + )), + 'type' => 'title', + ], + 'allowed_countries' => [ + 'title' => __( + 'Sell to specific countries', + 'mollie-payments-for-woocommerce' + ), + 'desc' => '', + 'css' => 'min-width: 350px;', + 'default' => [], + 'type' => 'multi_select_countries', + ], + 'surcharge' => [ 'id' => $defaultTitle . '_' . 'surcharge', 'title' => sprintf( /* translators: Placeholder 1: Gateway title */ @@ -239,7 +230,7 @@ public function gatewayFormFields( 'default' => '0.00', 'desc_tip' => true, ], - [ + 'advanced' => [ 'id' => $defaultTitle . '_' . 'advanced', 'title' => sprintf( /* translators: Placeholder 1: gateway title */ @@ -248,26 +239,6 @@ public function gatewayFormFields( ), 'type' => 'title', ], - 'activate_expiry_days_setting' => [ - 'title' => __('Activate expiry time setting', 'mollie-payments-for-woocommerce'), - 'label' => __('Enable expiry time for payments', 'mollie-payments-for-woocommerce'), - 'description' => __('Enable this option if you want to be able to set the time after which the order will expire.', 'mollie-payments-for-woocommerce'), - 'type' => 'checkbox', - 'default' => 'no', - ], - 'order_dueDate' => [ - 'title' => sprintf(__('Expiry time', 'mollie-payments-for-woocommerce')), - 'type' => 'number', - 'custom_attributes' => ['step' => '1', 'min' => '10', 'max' => '526000'], - 'description' => sprintf( - __( - 'Number of MINUTES after the order will expire and will be canceled at Mollie and WooCommerce.', - 'mollie-payments-for-woocommerce' - ) - ), - 'default' => '10', - 'desc_tip' => false, - ], ]; if ($paymentConfirmation) { @@ -306,6 +277,27 @@ public function gatewayFormFields( ]; } + $formFields['activate_expiry_days_setting'] = [ + 'title' => __('Activate expiry time setting', 'mollie-payments-for-woocommerce'), + 'label' => __('Enable expiry time for payments', 'mollie-payments-for-woocommerce'), + 'description' => __('Enable this option if you want to be able to set the time after which the order will expire.', 'mollie-payments-for-woocommerce'), + 'type' => 'checkbox', + 'default' => 'no', + ]; + $formFields['order_dueDate'] = [ + 'title' => sprintf(__('Expiry time', 'mollie-payments-for-woocommerce')), + 'type' => 'number', + 'custom_attributes' => ['step' => '1', 'min' => '10', 'max' => '526000'], + 'description' => sprintf( + __( + 'Number of MINUTES after the order will expire and will be canceled at Mollie and WooCommerce.', + 'mollie-payments-for-woocommerce' + ) + ), + 'default' => '10', + 'desc_tip' => false, + ]; + return $formFields; } } diff --git a/src/Shared/Data.php b/src/Shared/Data.php index 387aa711a..f91865002 100644 --- a/src/Shared/Data.php +++ b/src/Shared/Data.php @@ -705,7 +705,7 @@ public function getAllAvailablePaymentMethods($useCache = true) delete_transient($transient_id); } // No cache exists, call the API and cache the result - if ($methods === false) { + if (empty($methods)) { if (!$apiKey) { return []; } @@ -720,8 +720,8 @@ public function getAllAvailablePaymentMethods($useCache = true) // $methods_cleaned is empty array when the API doesn't return any methods, cache the empty array $methods = $methods_cleaned; - // Set new transients (as cache) - if ($useCache) { + // Set new transients (as cache) only if we have something in + if ($useCache && !empty($methods)) { set_transient($transient_id, $methods, HOUR_IN_SECONDS); } } diff --git a/src/Shared/SharedDataDictionary.php b/src/Shared/SharedDataDictionary.php index eb7224391..7845ff63c 100644 --- a/src/Shared/SharedDataDictionary.php +++ b/src/Shared/SharedDataDictionary.php @@ -33,6 +33,7 @@ class SharedDataDictionary 'Mollie_WC_Gateway_Directdebit', 'Mollie_WC_Gateway_Blik', 'Mollie_WC_Gateway_Twint', + 'Mollie_WC_Gateway_Bancomatpay', ]; public const MOLLIE_OPTIONS_NAMES = [ @@ -68,6 +69,7 @@ class SharedDataDictionary 'mollie-payments-for-woocommerce_removeOptionsAndTransients', 'mollie-plugin-version', 'mollie-new-install', + 'mollie_wc_is_phone_required_flag', ]; public const DB_VERSION_PARAM_NAME = 'mollie-db-version'; public const PLUGIN_VERSION_PARAM_NAME = 'mollie-plugin-version'; diff --git a/src/Subscription/MollieSubscriptionGateway.php b/src/Subscription/MollieSubscriptionGateway.php index 25fd2d545..f62a6e839 100644 --- a/src/Subscription/MollieSubscriptionGateway.php +++ b/src/Subscription/MollieSubscriptionGateway.php @@ -235,15 +235,15 @@ public function scheduled_subscription_payment($renewal_total, WC_Order $renewal $subscriptions = wcs_get_subscriptions_for_renewal_order($renewal_order->get_id()); $subscription = array_pop($subscriptions); // Just need one valid subscription $subscription_mollie_payment_id = $subscription->get_meta('_mollie_payment_id'); - $subcriptionParentOrder = $subscription->get_parent(); - $mandateId = !empty($subcriptionParentOrder) ? $subcriptionParentOrder->get_meta('_mollie_mandate_id') : null; + $subscriptionParentOrder = $subscription->get_parent(); + $mandateId = !empty($subscriptionParentOrder) ? $subscriptionParentOrder->get_meta('_mollie_mandate_id') : null; if (! empty($subscription_mollie_payment_id) && ! empty($subscription)) { $customer_id = $this->restore_mollie_customer_id_and_mandate($customer_id, $subscription_mollie_payment_id, $subscription); } // Get all data for the renewal payment - $initialPaymentUsedOrderAPI = $this->initialPaymentUsedOrderAPI($subcriptionParentOrder); + $initialPaymentUsedOrderAPI = $this->initialPaymentUsedOrderAPI($subscriptionParentOrder); $data = $this->subscriptionObject->getRecurringPaymentRequestData($renewal_order, $customer_id, $initialPaymentUsedOrderAPI); // Allow filtering the renewal payment data @@ -301,14 +301,14 @@ public function scheduled_subscription_payment($renewal_total, WC_Order $renewal (property_exists($payment, 'mandateId') && $payment->mandateId !== null) && $payment->mandateId !== $mandateId - && !empty($subcriptionParentOrder) + && !empty($subscriptionParentOrder) ) { $this->logger->debug("{$this->id}: updating to mandate {$payment->mandateId}"); - $subcriptionParentOrder->update_meta_data( + $subscriptionParentOrder->update_meta_data( '_mollie_mandate_id', $payment->mandateId ); - $subcriptionParentOrder->save(); + $subscriptionParentOrder->save(); $mandateId = $payment->mandateId; } } else { @@ -722,15 +722,15 @@ public function is_available(): bool } /** - * @param $subcriptionParentOrder + * @param $subscriptionParentOrder * @return bool */ - protected function initialPaymentUsedOrderAPI($subcriptionParentOrder): bool + protected function initialPaymentUsedOrderAPI($subscriptionParentOrder): bool { - if (!$subcriptionParentOrder) { + if (!$subscriptionParentOrder) { return false; } - $orderIdMeta = $subcriptionParentOrder->get_meta('_mollie_order_id'); + $orderIdMeta = $subscriptionParentOrder->get_meta('_mollie_order_id'); $parentOrderMeta = $orderIdMeta ?: PaymentService::PAYMENT_METHOD_TYPE_PAYMENT; diff --git a/tests/php/Functional/Subscription/MollieSubscriptionTest.php b/tests/php/Functional/Subscription/MollieSubscriptionTest.php index ae2c43e91..d792bfa8b 100644 --- a/tests/php/Functional/Subscription/MollieSubscriptionTest.php +++ b/tests/php/Functional/Subscription/MollieSubscriptionTest.php @@ -38,7 +38,7 @@ public function __construct($name = null, array $data = [], $dataName = '') * THEN THE ORDER NOTES ARE CREATED * @test */ - public function renewSubcriptionPaymentTest() + public function renewSubscriptionPaymentTest() { $gatewayName = 'mollie_wc_gateway_ideal'; $renewalOrder = $this->wcOrder(); diff --git a/webpack.config.js b/webpack.config.js index 81a5f614e..1ae240bf1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -30,7 +30,6 @@ function configJavaScript ({ basePath }) .addEntry('mollieBlockIndex.min', './resources/js/mollieBlockIndex.js') .addEntry('paypalButtonBlockComponent.min', './resources/js/paypalButtonBlockComponent.js') .addEntry('applepayButtonBlockComponent.min', './resources/js/applepayButtonBlockComponent.js') - .addEntry('mollieBillie.min', './resources/js/mollieBillie.js') .enableSourceMaps(!Encore.isProduction()) return extractEncoreConfig('javascript-configuration')