diff --git a/modules/ppcp-button/resources/css/hosted-fields.scss b/modules/ppcp-button/resources/css/hosted-fields.scss index ed4731360..e69de29bb 100644 --- a/modules/ppcp-button/resources/css/hosted-fields.scss +++ b/modules/ppcp-button/resources/css/hosted-fields.scss @@ -1,50 +0,0 @@ -.ppcp-card-icon { - max-width: 50px; - margin-left: 5px; -} - -#ppcp-hosted-fields { - - .ppcp-dcc-credit-card-wrapper { - width: 100%; - display: grid; - grid-template-columns: 55% 1fr 1fr; - grid-template-rows: 1fr 1fr auto; - grid-column-gap: 15px; - margin-bottom: 15px; - - label, span { - height: 30px; - padding: 0; - margin: 0; - overflow: hidden; - position: relative; - vertical-align: bottom; - font-size: 10px; - } - - label { - grid-row: 1/2; - } - span { - grid-row: 2/3; - background:white; - border: 1px #666; - padding: 5px; - } - - button { - grid-row: 3/4; - grid-column: 1/4; - } - - label { - line-height: 30px; - } - } - -} - - - - diff --git a/modules/ppcp-button/resources/js/modules/Helper/DccInputFactory.js b/modules/ppcp-button/resources/js/modules/Helper/DccInputFactory.js new file mode 100644 index 000000000..94923eaa7 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/DccInputFactory.js @@ -0,0 +1,11 @@ +const dccInputFactory = (original) => { + const styles = window.getComputedStyle(original); + const newElement = document.createElement('span'); + newElement.setAttribute('id', original.id); + Object.values(styles).forEach( (prop) => { + newElement.style[prop] = '' + styles[prop]; + }); + return newElement; +} + +export default dccInputFactory; \ No newline at end of file diff --git a/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js b/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js index 05c5191af..56c7d7977 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js @@ -1,3 +1,5 @@ +import dccInputFactory from "../Helper/DccInputFactory"; + class CreditCardRenderer { constructor(defaultConfig, errorHandler) { @@ -23,28 +25,46 @@ class CreditCardRenderer { return; } + const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway'); + const oldDisplayStyle = gateWayBox.style.display; + gateWayBox.style.display = 'block'; document.querySelector('#ppcp-hide-dcc').parentNode.removeChild(document.querySelector('#ppcp-hide-dcc')); + const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number'); + const cardNumber = dccInputFactory(cardNumberField); + cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField); + + const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry'); + const cardExpiry = dccInputFactory(cardExpiryField); + cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField); + + const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc'); + const cardCode = dccInputFactory(cardCodeField); + cardCodeField.parentNode.replaceChild(cardCode, cardCodeField); + + gateWayBox.style.display = oldDisplayStyle; + + const formWrapper = '.payment_box payment_method_ppcp-credit-card-gateway'; if ( this.defaultConfig.enforce_vault - && document.querySelector(wrapper + ' .ppcp-credit-card-vault') + && document.querySelector(formWrapper + ' .ppcp-credit-card-vault') ) { - document.querySelector(wrapper + ' .ppcp-credit-card-vault').checked = true; - document.querySelector(wrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true); + document.querySelector(formWrapper + ' .ppcp-credit-card-vault').checked = true; + document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true); } paypal.HostedFields.render({ createOrder: contextConfig.createOrder, fields: { number: { - selector: wrapper + ' .ppcp-credit-card', + selector: '#ppcp-credit-card-gateway-card-number', placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number, }, cvv: { - selector: wrapper + ' .ppcp-cvv', + selector: '#ppcp-credit-card-gateway-card-cvc', placeholder: this.defaultConfig.hosted_fields.labels.cvv, }, expirationDate: { - selector: wrapper + ' .ppcp-expiration-date', + selector: '#ppcp-credit-card-gateway-card-expiry', placeholder: this.defaultConfig.hosted_fields.labels.mm_yyyy, } } @@ -79,8 +99,8 @@ class CreditCardRenderer { hostedFields.on('inputSubmitRequest', function () { submitEvent(null); }); - document.querySelector(wrapper).addEventListener( - 'submit', + document.querySelector(wrapper + ' button').addEventListener( + 'click', submitEvent ); }); @@ -88,7 +108,7 @@ class CreditCardRenderer { document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener( 'click', () => { - document.querySelector('label[for=ppcp-credit-card-ppcp-hosted-fields]').click(); + document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click(); } ) } diff --git a/modules/ppcp-button/src/Assets/class-smartbutton.php b/modules/ppcp-button/src/Assets/class-smartbutton.php index 653c6af4d..524b4e1d8 100644 --- a/modules/ppcp-button/src/Assets/class-smartbutton.php +++ b/modules/ppcp-button/src/Assets/class-smartbutton.php @@ -313,15 +313,6 @@ class SmartButton implements SmartButtonInterface { return false; } - if ( $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) { - wp_enqueue_style( - 'ppcp-hosted-fields', - $this->module_url . '/assets/css/hosted-fields.css', - array(), - 1 - ); - } - $load_script = false; if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) { $load_script = true; @@ -498,21 +489,9 @@ class SmartButton implements SmartButtonInterface { ) : ''; printf( - '
- -
', + '
+ +
', esc_attr( $id ), esc_html__( 'Credit Card number', 'paypal-payments-for-woocommerce' ), esc_html__( 'Expiration', 'paypal-payments-for-woocommerce' ), diff --git a/modules/ppcp-button/webpack.config.js b/modules/ppcp-button/webpack.config.js index 1c017677c..7ebdb3bc1 100644 --- a/modules/ppcp-button/webpack.config.js +++ b/modules/ppcp-button/webpack.config.js @@ -6,8 +6,7 @@ module.exports = { mode: isProduction ? 'production' : 'development', target: 'web', entry: { - button: path.resolve('./resources/js/button.js'), - hostedfields: path.resolve('./resources/css/hosted-fields.scss'), + button: path.resolve('./resources/js/button.js') }, output: { path: path.resolve(__dirname, 'assets/'), diff --git a/modules/ppcp-wc-gateway/src/Gateway/class-creditcardgateway.php b/modules/ppcp-wc-gateway/src/Gateway/class-creditcardgateway.php index 4c09a17d5..e2888a2e1 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/class-creditcardgateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/class-creditcardgateway.php @@ -19,7 +19,9 @@ use Psr\Container\ContainerInterface; /** * Class CreditCardGateway */ -class CreditCardGateway extends PayPalGateway { +class CreditCardGateway extends \WC_Payment_Gateway_CC { + + use ProcessPaymentTrait; const ID = 'ppcp-credit-card-gateway'; @@ -76,6 +78,7 @@ class CreditCardGateway extends PayPalGateway { 'subscription_payment_method_change_customer', 'subscription_payment_method_change_admin', 'multiple_subscriptions', + 'credit_card_form_cvc_on_saved_method', ); } diff --git a/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php b/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php index 676f46aa1..6bb72fa96 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php @@ -23,6 +23,8 @@ use Psr\Container\ContainerInterface; */ class PayPalGateway extends \WC_Payment_Gateway { + use ProcessPaymentTrait; + const ID = 'ppcp-gateway'; const CAPTURED_META_KEY = '_ppcp_paypal_captured'; const INTENT_META_KEY = '_ppcp_paypal_intent'; @@ -168,71 +170,6 @@ class PayPalGateway extends \WC_Payment_Gateway { } } - /** - * Process a payment for an WooCommerce order. - * - * @param int $order_id The WooCommerce order id. - * - * @return array|null - */ - public function process_payment( $order_id ) { - global $woocommerce; - $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wc_order, \WC_Order::class ) ) { - return null; - } - - /** - * If the WC_Order is payed through the approved webhook. - */ - //phpcs:disable WordPress.Security.NonceVerification.Recommended - if ( isset( $_REQUEST['ppcp-resume-order'] ) && $wc_order->has_status( 'processing' ) ) { - $this->session_handler->destroy_session_data(); - return array( - 'result' => 'success', - 'redirect' => $this->get_return_url( $wc_order ), - ); - } - //phpcs:enable WordPress.Security.NonceVerification.Recommended - - try { - if ( $this->order_processor->process( $wc_order, $woocommerce ) ) { - $this->session_handler->destroy_session_data(); - return array( - 'result' => 'success', - 'redirect' => $this->get_return_url( $wc_order ), - ); - } - } catch ( PayPalApiException $error ) { - if ( $error->has_detail( 'INSTRUMENT_DECLINED' ) ) { - $this->session_handler->increment_insufficient_funding_tries(); - $host = $this->config->has( 'sandbox_on' ) && $this->config->get( 'sandbox_on' ) ? - 'https://www.sandbox.paypal.com/' : 'https://www.paypal.com/'; - $url = $host . 'checkoutnow?token=' . $this->session_handler->order()->id(); - if ( $this->session_handler->insufficient_funding_tries() >= 3 ) { - $this->session_handler->destroy_session_data(); - wc_add_notice( - __( 'Please use a different payment method.', 'paypal-payments-for-woocommerce' ), - 'error' - ); - return null; - } - return array( - 'result' => 'success', - 'redirect' => $url, - ); - } - - $this->session_handler->destroy_session_data(); - } - wc_add_notice( - $this->order_processor->last_error(), - 'error' - ); - - return null; - } - /** * Captures an authorized payment for an WooCommerce order. * diff --git a/modules/ppcp-wc-gateway/src/Gateway/class-processpaymenttrait.php b/modules/ppcp-wc-gateway/src/Gateway/class-processpaymenttrait.php new file mode 100644 index 000000000..5835840ec --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Gateway/class-processpaymenttrait.php @@ -0,0 +1,82 @@ +has_status( 'processing' ) ) { + $this->session_handler->destroy_session_data(); + return array( + 'result' => 'success', + 'redirect' => $this->get_return_url( $wc_order ), + ); + } + //phpcs:enable WordPress.Security.NonceVerification.Recommended + + try { + if ( $this->order_processor->process( $wc_order, $woocommerce ) ) { + $this->session_handler->destroy_session_data(); + return array( + 'result' => 'success', + 'redirect' => $this->get_return_url( $wc_order ), + ); + } + } catch ( PayPalApiException $error ) { + if ( $error->has_detail( 'INSTRUMENT_DECLINED' ) ) { + $this->session_handler->increment_insufficient_funding_tries(); + $host = $this->config->has( 'sandbox_on' ) && $this->config->get( 'sandbox_on' ) ? + 'https://www.sandbox.paypal.com/' : 'https://www.paypal.com/'; + $url = $host . 'checkoutnow?token=' . $this->session_handler->order()->id(); + if ( $this->session_handler->insufficient_funding_tries() >= 3 ) { + $this->session_handler->destroy_session_data(); + wc_add_notice( + __( 'Please use a different payment method.', 'paypal-payments-for-woocommerce' ), + 'error' + ); + return null; + } + return array( + 'result' => 'success', + 'redirect' => $url, + ); + } + + $this->session_handler->destroy_session_data(); + } + wc_add_notice( + $this->order_processor->last_error(), + 'error' + ); + + return null; + } +}