diff --git a/assets/css/checkoutcom-styles.css b/assets/css/checkoutcom-styles.css index 2801d075..7257b67a 100644 --- a/assets/css/checkoutcom-styles.css +++ b/assets/css/checkoutcom-styles.css @@ -717,6 +717,10 @@ ul.wc_payment_methods label[for*="payment_method_wc_checkout_com_"] img { #sepa-iban { height:35px; font-size: 17px; + padding-left: 30px; + background-image: url( '../images/bank.svg' ); + background-repeat: no-repeat; + background-position: left 5px center; } .sepa-continue-btn { @@ -728,4 +732,9 @@ ul.wc_payment_methods label[for*="payment_method_wc_checkout_com_"] img { padding-bottom: 0px; padding-top: 0px; font-size: 13px; +} + +.sepa-example { + font-size: 14px; + font-weight: 800; } \ No newline at end of file diff --git a/assets/images/bank.svg b/assets/images/bank.svg new file mode 100644 index 00000000..e3039c11 --- /dev/null +++ b/assets/images/bank.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/assets/js/admin.js b/assets/js/admin.js index 11db3aa0..3384f6bb 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -102,6 +102,28 @@ jQuery( function ( $ ) { } ); }, + coreSettings: function () { + let enable_fallback_ac = $( '#woocommerce_wc_checkout_com_cards_enable_fallback_ac' ); + let fallback_ckocom_sk = $( '#woocommerce_wc_checkout_com_cards_fallback_ckocom_sk' ); + let fallback_ckocom_pk = $( '#woocommerce_wc_checkout_com_cards_fallback_ckocom_pk' ); + + if ( enable_fallback_ac.length <= 0 ) { + return; + } + + enable_fallback_ac.on( 'change', function () { + if ( this.checked ) { + fallback_ckocom_sk.closest( 'tr' ).show(); + fallback_ckocom_pk.closest( 'tr' ).show(); + } else { + fallback_ckocom_sk.closest( 'tr' ).hide(); + fallback_ckocom_pk.closest( 'tr' ).hide(); + } + } ) + + enable_fallback_ac.trigger( 'change' ); + }, + cardSettings: function () { let ckocom_card_autocap = $( '#ckocom_card_autocap' ); @@ -301,6 +323,8 @@ jQuery( function ( $ ) { admin_functions.orderStatusSettings(); + admin_functions.coreSettings(); + // Script to hide and show fields. admin_functions.cardSettings(); diff --git a/includes/api/class-wc-checkoutcom-api-request.php b/includes/api/class-wc-checkoutcom-api-request.php index d135a426..24636869 100644 --- a/includes/api/class-wc-checkoutcom-api-request.php +++ b/includes/api/class-wc-checkoutcom-api-request.php @@ -822,6 +822,9 @@ public static function void_payment() { * @return array|mixed */ public static function refund_payment( $order_id, $order ) { + $core_settings = get_option( 'woocommerce_wc_checkout_com_cards_settings' ); + $is_fallback_active = ( 'yes' === ( $core_settings['enable_fallback_ac'] ?? 'no' ) ); + $cko_payment_id = get_post_meta( $order_id, '_cko_payment_id', true ); // Check if cko_payment_id is empty. @@ -846,8 +849,68 @@ public static function refund_payment( $order_id, $order ) { $checkout = new Checkout_SDK(); try { - // Check if payment is already voided or captured on checkout.com hub. - $details = $checkout->get_builder()->getPaymentsClient()->getPaymentDetails( $cko_payment_id ); + + try { + // Check if payment is already voided or captured on checkout.com hub. + $details = $checkout->get_builder()->getPaymentsClient()->getPaymentDetails( $cko_payment_id ); + + } catch ( CheckoutApiException $ex ) { + + // Handle above try block exception. + if ( ! $is_fallback_active ) { + $error_message = esc_html__( 'An error has occurred while processing your refund. ', 'checkout-com-unified-payments-api' ); + + // check if gateway response is enabled from module settings. + if ( $gateway_debug ) { + $error_message .= $ex->getMessage(); + } + + WC_Checkoutcom_Utility::logger( $error_message, $ex ); + + return [ 'error' => $error_message ]; + } + + // Handle Retry with fallback account. + $checkout = new Checkout_SDK( true ); + $details = $checkout->get_builder()->getPaymentsClient()->getPaymentDetails( $cko_payment_id ); + + if ( 'Refunded' === $details['status'] && ! $refund_is_less ) { + $error_message = 'Payment has already been refunded on Checkout.com hub for order Id : ' . $order_id; + + return [ 'error' => $error_message ]; + } + + $refund_request = new RefundRequest(); + $refund_request->reference = $order->get_order_number(); + + // Process partial refund if amount is less than order amount. + if ( $refund_is_less ) { + $refund_request->amount = $refund_amount_cents; + + $_SESSION['cko-refund-is-less'] = $refund_is_less; + } + + $order->add_order_note( esc_html__( 'Checkout.com Refund : Process via fallback account.', 'checkout-com-unified-payments-api' ) ); + + $response = $checkout->get_builder()->getPaymentsClient()->refundPayment( $cko_payment_id, $refund_request ); + + if ( ! WC_Checkoutcom_Utility::is_successful( $response ) ) { + /* translators: 1: Order ID. */ + $error_message = sprintf( esc_html__( 'An error has occurred while processing your refund payment on Checkout.com hub. Order Id : %s', 'checkout-com-unified-payments-api' ), $order_id ); + + // Check if gateway response is enabled from module settings. + if ( $gateway_debug ) { + $error_message .= $response; + } + + WC_Checkoutcom_Utility::logger( $error_message, $response ); + + return [ 'error' => $error_message ]; + } else { + return $response; + } + + } if ( 'Refunded' === $details['status'] && ! $refund_is_less ) { $error_message = 'Payment has already been refunded on Checkout.com hub for order Id : ' . $order_id; @@ -862,7 +925,6 @@ public static function refund_payment( $order_id, $order ) { if ( $refund_is_less ) { $refund_request->amount = $refund_amount_cents; - // Set is_mada in session. $_SESSION['cko-refund-is-less'] = $refund_is_less; } @@ -1406,22 +1468,30 @@ public static function mandate_cancel_request( $url, $subscription_id ) { return false; } - $core_settings = get_option( 'woocommerce_wc_checkout_com_cards_settings' ); + $core_settings = get_option( 'woocommerce_wc_checkout_com_cards_settings' ); + $is_fallback_active = ( 'yes' === ( $core_settings['enable_fallback_ac'] ?? 'no' ) ); $core_settings['ckocom_sk'] = cko_is_nas_account() ? 'Bearer ' . $core_settings['ckocom_sk'] : $core_settings['ckocom_sk']; - $wp_request_headers = [ - 'Authorization' => $core_settings['ckocom_sk'], - ]; - $wp_response = wp_remote_post( $url, [ - 'headers' => $wp_request_headers, + 'headers' => [ 'Authorization' => $core_settings['ckocom_sk'] ], ] ); - if ( 200 !== wp_remote_retrieve_response_code( $wp_response ) ) { + // If unauthorized & fallback ABC setup retry with those cred. + if ( 401 === wp_remote_retrieve_response_code( $wp_response ) && $is_fallback_active ) { + + $wp_response = wp_remote_post( + $url, + [ + 'headers' => [ 'Authorization' => $core_settings['fallback_ckocom_sk'] ], + ] + ); + + } elseif ( 200 !== wp_remote_retrieve_response_code( $wp_response ) ) { + WC_Checkoutcom_Utility::logger( sprintf( 'An error has occurred while mandate cancel Order # %d request. Response code: %d', diff --git a/includes/api/class-wc-checkoutcom-utility.php b/includes/api/class-wc-checkoutcom-utility.php index 7c5276ff..91bfcf69 100644 --- a/includes/api/class-wc-checkoutcom-utility.php +++ b/includes/api/class-wc-checkoutcom-utility.php @@ -71,7 +71,7 @@ public static function value_to_decimal( $amount, $currency_symbol ) { * * @return float|int */ - public function decimal_to_value( $amount, $currency_symbol ) { + public static function decimal_to_value( $amount, $currency_symbol ) { $currency = strtoupper( $currency_symbol ); $three_decimal_currency_list = [ 'BHD', 'LYD', 'JOD', 'IQD', 'KWD', 'OMR', 'TND' ]; $zero_decimal_currency_list = [ @@ -117,13 +117,13 @@ public static function get_delayed_capture_timestamp() { // If the input of the delay is numeric. if ( is_numeric( $delay ) ) { // Get total seconds based on the hour input. - $total_seconds = $delay * 3600; + $total_seconds = round( $delay * 3600 ); // If the delay is 0 manually add a 10 seconds delay. if ( 0 === $total_seconds ) { $total_seconds += $default_seconds_delay; } $hours = floor( $total_seconds / 3600 ); - $minutes = floor( $total_seconds / 60 % 60 ); + $minutes = floor( floor( $total_seconds / 60 ) % 60 ); $seconds = floor( $total_seconds % 60 ); // Return date and time in UTC with the delays added. diff --git a/includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php b/includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php index 998e7f67..87369e7f 100644 --- a/includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php +++ b/includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php @@ -88,7 +88,9 @@ public function payment_fields() { // check if apm is selected as payment method. if (jQuery('#payment_method_wc_checkout_com_alternative_payments_sepa').is(':checked')) { - if (0 === jQuery('#sepa-iban').val().length) { + const iban = jQuery('#sepa-iban').val(); + + if (0 === iban.length) { alert( '' ); return false; } diff --git a/includes/settings/class-wc-checkoutcom-cards-settings.php b/includes/settings/class-wc-checkoutcom-cards-settings.php index d2cc00fc..50b5242d 100644 --- a/includes/settings/class-wc-checkoutcom-cards-settings.php +++ b/includes/settings/class-wc-checkoutcom-cards-settings.php @@ -119,7 +119,7 @@ public static function core_settings() { 'default' => 'Pay by Card with Checkout.com', ], 'ckocom_account_type' => [ - 'title' => __( 'Account type', 'checkout-com-unified-payments-api' ), + 'title' => __( 'Account Type', 'checkout-com-unified-payments-api' ), 'type' => 'select', 'description' => __( 'Contact support team to know your account type.', 'checkout-com-unified-payments-api' ), 'desc_tip' => true, @@ -143,6 +143,23 @@ public static function core_settings() { 'description' => sprintf( __( 'You can %1$s find your public key %2$s in the Checkout.com Hub', 'checkout-com-unified-payments-api' ), '', '' ), 'placeholder' => 'pk_xxx', ], + 'enable_fallback_ac' => [ + 'id' => 'enable', + 'title' => __( 'Fallback Account', 'checkout-com-unified-payments-api' ), + 'type' => 'checkbox', + 'label' => __( 'Enable Fallback Account(ABC account) for Refund', 'checkout-com-unified-payments-api' ), + 'default' => 'no', + ], + 'fallback_ckocom_sk' => [ + 'title' => __( 'Secret Key', 'checkout-com-unified-payments-api' ), + 'type' => 'text', + 'placeholder' => 'sk_xxx', + ], + 'fallback_ckocom_pk' => [ + 'title' => __( 'Public Key', 'checkout-com-unified-payments-api' ), + 'type' => 'text', + 'placeholder' => 'pk_xxx', + ], ]; return apply_filters( 'wc_checkout_com_cards', $settings ); diff --git a/languages/checkout-com-unified-payments-api.pot b/languages/checkout-com-unified-payments-api.pot index bf0c95e3..162ed3ad 100644 --- a/languages/checkout-com-unified-payments-api.pot +++ b/languages/checkout-com-unified-payments-api.pot @@ -2,16 +2,16 @@ # This file is distributed under the same license as the Checkout.com Payment Gateway plugin. msgid "" msgstr "" -"Project-Id-Version: Checkout.com Payment Gateway 4.4.14\n" +"Project-Id-Version: Checkout.com Payment Gateway 4.4.15\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/checkout-com-unified-payments-api\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2023-04-20T14:54:52+05:30\n" +"POT-Creation-Date: 2023-09-21T10:56:41+05:30\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"X-Generator: WP-CLI 2.7.1\n" +"X-Generator: WP-CLI 2.8.1\n" "X-Domain: checkout-com-unified-payments-api\n" #. Plugin Name of the plugin @@ -259,28 +259,28 @@ msgstr "" msgid "SEPA Direct Debit" msgstr "" -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:92 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:94 msgid "Please enter your bank accounts iban" msgstr "" -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:97 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:99 msgid "Please accept the mandate to continue" msgstr "" -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:127 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:129 msgid "Checkout.com - SEPA payment for free order." msgstr "" -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:143 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:145 msgid "Please try correct IBAN" msgstr "" -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:145 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:147 msgid " Please try correct IBAN" msgstr "" #. translators: 1: Result ID, 2: Mandate reference. -#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:186 +#: includes/apms/class-wc-gateway-checkout-com-alternative-payments-sepa.php:188 msgid "Checkout.com - Sepa payment Action ID : %1$s - Sepa mandate reference : %2$s" msgstr "" @@ -1175,8 +1175,12 @@ msgstr "" msgid "Cadastro de Pessoas Físicas" msgstr "" +#: templates/class-wc-checkoutcom-apm-templates.php:111 +msgid "IBAN." +msgstr "" + #: templates/class-wc-checkoutcom-apm-templates.php:112 -msgid "IBAN" +msgid "DE00 0000 0000 0000 0000 00" msgstr "" #: templates/class-wc-checkoutcom-apm-templates.php:115 @@ -1187,51 +1191,51 @@ msgstr "" msgid "Please fill in the required fields." msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:154 +#: templates/class-wc-checkoutcom-apm-templates.php:200 msgid "SEPA Direct Debit Mandate for single payment" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:160 +#: templates/class-wc-checkoutcom-apm-templates.php:206 msgid "Creditor" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:161 +#: templates/class-wc-checkoutcom-apm-templates.php:207 msgid "b4payment GmbH" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:162 +#: templates/class-wc-checkoutcom-apm-templates.php:208 msgid "Obermünsterstraße 14" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:163 +#: templates/class-wc-checkoutcom-apm-templates.php:209 msgid "93047 Regensburg" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:164 +#: templates/class-wc-checkoutcom-apm-templates.php:210 msgid "GERMANY" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:166 +#: templates/class-wc-checkoutcom-apm-templates.php:212 msgid "Creditor ID: DE36ZZZ00001690322" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:169 +#: templates/class-wc-checkoutcom-apm-templates.php:215 msgid "Debtor" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:183 +#: templates/class-wc-checkoutcom-apm-templates.php:229 msgid "By accepting this mandate form, you authorise (A) b4payment GmbH to send instructions to your bank to debit your account (B) your bank to debit your account in accordance with the instructions from b4payment GmbH." msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:184 +#: templates/class-wc-checkoutcom-apm-templates.php:230 msgid "As part of your rights, you are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited." msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:193 +#: templates/class-wc-checkoutcom-apm-templates.php:239 msgid "I accept the mandate for a single payment" msgstr "" -#: templates/class-wc-checkoutcom-apm-templates.php:204 +#: templates/class-wc-checkoutcom-apm-templates.php:250 msgid "Your rights regarding the above mandate are explained in a statement that you can obtain from your bank." msgstr "" diff --git a/lib/class-checkout-sdk.php b/lib/class-checkout-sdk.php index 94047436..9758b725 100644 --- a/lib/class-checkout-sdk.php +++ b/lib/class-checkout-sdk.php @@ -35,15 +35,16 @@ class Checkout_SDK { /** * Constructor. + * + * @param bool $use_fallback */ - public function __construct() { - + public function __construct( $use_fallback = false ) { $core_settings = get_option( 'woocommerce_wc_checkout_com_cards_settings' ); $environment = 'sandbox' === $core_settings['ckocom_environment'] ? Environment::sandbox() : Environment::production(); $this->nas_account_type = cko_is_nas_account(); - if ( $this->nas_account_type ) { + if ( $this->nas_account_type && false === $use_fallback ) { $builder = CheckoutFourSdk::staticKeys(); } else { $builder = CheckoutDefaultSdk::staticKeys(); @@ -53,6 +54,11 @@ public function __construct() { $builder->setSecretKey( $core_settings['ckocom_sk'] ); $builder->setEnvironment( $environment ); + if ( $use_fallback ) { + $builder->setPublicKey( $core_settings['fallback_ckocom_pk'] ); + $builder->setSecretKey( $core_settings['fallback_ckocom_sk'] ); + } + try { $this->builder = $builder->build(); diff --git a/readme.txt b/readme.txt index 9fb8a8a6..3a2b58fe 100644 --- a/readme.txt +++ b/readme.txt @@ -171,6 +171,9 @@ http://example.com/?wc-api=wc_checkoutcom_webhook After the plugin has been configured, customers will be able to choose Checkout.com as a valid payment method. == Changelog == +v4.4.15 20th March 2023 +- **[tweak]** Update IBAN input field validation and styling + v4.4.14 20th March 2023 - **[tweak]** Update Giropay source property and description property diff --git a/templates/class-wc-checkoutcom-apm-templates.php b/templates/class-wc-checkoutcom-apm-templates.php index daf54d18..19d3c9b7 100755 --- a/templates/class-wc-checkoutcom-apm-templates.php +++ b/templates/class-wc-checkoutcom-apm-templates.php @@ -107,9 +107,9 @@ public static function get_sepa_details( $current_user ) { - - - + Example: GB33BUKB20201555555555 / DE75512108001245126199 / FR7630006000011234567890189 + + @@ -131,6 +131,52 @@ public static function get_sepa_details( $current_user ) { } }) + + jQuery( '#sepa-iban' ).on( 'paste', (event) => { + const clipboardData = event.clipboardData || event.originalEvent.clipboardData || window.clipboardData; + + if ( clipboardData ){ + let text = clipboardData.getData('text'); + text = text.toLocaleUpperCase(); + text = text.replace(/[^a-zA-Z0-9]/g, ''); + event.target.value = text; + event.preventDefault(); + } + }) + + jQuery( '#sepa-iban' ).on( 'keypress', function (event) { + const evt = event || window.event; + + // Reject input if not a-z or A-Z or 0-9 . + const regex = new RegExp("^[a-zA-Z0-9]+$"); + const key = String.fromCharCode( ! event.charCode ? event.which : event.charCode ); + if ( ! regex.test(key) ) { + event.preventDefault(); + return false; + } + + // Ensure we only handle printable keys, excluding enter and space. + const charCode = typeof evt.which == "number" ? evt.which : evt.keyCode; + if (charCode && charCode > 32) { + const keyChar = String.fromCharCode(charCode); + + // Transform typed character. + let mappedChar = keyChar.toLocaleUpperCase(); + let start, end; + if ( typeof this.selectionStart == "number" && typeof this.selectionEnd == "number" ) { + + start = this.selectionStart; + end = this.selectionEnd; + + this.value = this.value.slice( 0, start ) + mappedChar + this.value.slice( end ); + + // Move the caret. + this.selectionStart = this.selectionEnd = start + 1; + } + } + + return false; + });
Example: GB33BUKB20201555555555 / DE75512108001245126199 / FR7630006000011234567890189