relocate dcc fields to gateway description, use \WC_Payment_Gateway_CC, reutilize theme styles for dcc fields as much as possible

This commit is contained in:
David Remer 2020-09-14 14:17:39 +03:00
parent e4b6a412ea
commit 084eb2a908
8 changed files with 132 additions and 151 deletions

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -1,3 +1,5 @@
import dccInputFactory from "../Helper/DccInputFactory";
class CreditCardRenderer { class CreditCardRenderer {
constructor(defaultConfig, errorHandler) { constructor(defaultConfig, errorHandler) {
@ -23,28 +25,46 @@ class CreditCardRenderer {
return; 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')); 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 ( if (
this.defaultConfig.enforce_vault 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(formWrapper + ' .ppcp-credit-card-vault').checked = true;
document.querySelector(wrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true); document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);
} }
paypal.HostedFields.render({ paypal.HostedFields.render({
createOrder: contextConfig.createOrder, createOrder: contextConfig.createOrder,
fields: { fields: {
number: { number: {
selector: wrapper + ' .ppcp-credit-card', selector: '#ppcp-credit-card-gateway-card-number',
placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number, placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number,
}, },
cvv: { cvv: {
selector: wrapper + ' .ppcp-cvv', selector: '#ppcp-credit-card-gateway-card-cvc',
placeholder: this.defaultConfig.hosted_fields.labels.cvv, placeholder: this.defaultConfig.hosted_fields.labels.cvv,
}, },
expirationDate: { expirationDate: {
selector: wrapper + ' .ppcp-expiration-date', selector: '#ppcp-credit-card-gateway-card-expiry',
placeholder: this.defaultConfig.hosted_fields.labels.mm_yyyy, placeholder: this.defaultConfig.hosted_fields.labels.mm_yyyy,
} }
} }
@ -79,8 +99,8 @@ class CreditCardRenderer {
hostedFields.on('inputSubmitRequest', function () { hostedFields.on('inputSubmitRequest', function () {
submitEvent(null); submitEvent(null);
}); });
document.querySelector(wrapper).addEventListener( document.querySelector(wrapper + ' button').addEventListener(
'submit', 'click',
submitEvent submitEvent
); );
}); });
@ -88,7 +108,7 @@ class CreditCardRenderer {
document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener( document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener(
'click', 'click',
() => { () => {
document.querySelector('label[for=ppcp-credit-card-ppcp-hosted-fields]').click(); document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click();
} }
) )
} }

View file

@ -313,15 +313,6 @@ class SmartButton implements SmartButtonInterface {
return false; 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; $load_script = false;
if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) { if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) {
$load_script = true; $load_script = true;
@ -498,21 +489,9 @@ class SmartButton implements SmartButtonInterface {
) : ''; ) : '';
printf( printf(
'<form id="%1$s"> '<div id="%1$s">
<div class="ppcp-dcc-credit-card-wrapper" style="display: none"> <button class="button alt">%6$s</button>
<label for="ppcp-credit-card-%1$s">%2$s</label> </div><div id="payments-sdk__contingency-lightbox"></div><style id="ppcp-hide-dcc">.payment_method_ppcp-credit-card-gateway {display:none;}</style>',
<span id="ppcp-credit-card-%1$s" class="ppcp-credit-card"></span>
<label for="ppcp-expiration-date-%1$s">%3$s</label>
<span
id="ppcp-expiration-date-%1$s"
class="ppcp-expiration-date"
></span>
<label for="ppcp-cvv-%1$s">%4$s</label>
<span id="ppcp-cvv-%1$s" class="ppcp-cvv"></span>
%5$s
<button class="button alt">%6$s</button>
</div>
</form><div id="payments-sdk__contingency-lightbox"></div><style id="ppcp-hide-dcc">.payment_method_ppcp-credit-card-gateway {display:none;}</style>',
esc_attr( $id ), esc_attr( $id ),
esc_html__( 'Credit Card number', 'paypal-payments-for-woocommerce' ), esc_html__( 'Credit Card number', 'paypal-payments-for-woocommerce' ),
esc_html__( 'Expiration', 'paypal-payments-for-woocommerce' ), esc_html__( 'Expiration', 'paypal-payments-for-woocommerce' ),

View file

@ -6,8 +6,7 @@ module.exports = {
mode: isProduction ? 'production' : 'development', mode: isProduction ? 'production' : 'development',
target: 'web', target: 'web',
entry: { entry: {
button: path.resolve('./resources/js/button.js'), button: path.resolve('./resources/js/button.js')
hostedfields: path.resolve('./resources/css/hosted-fields.scss'),
}, },
output: { output: {
path: path.resolve(__dirname, 'assets/'), path: path.resolve(__dirname, 'assets/'),

View file

@ -19,7 +19,9 @@ use Psr\Container\ContainerInterface;
/** /**
* Class CreditCardGateway * Class CreditCardGateway
*/ */
class CreditCardGateway extends PayPalGateway { class CreditCardGateway extends \WC_Payment_Gateway_CC {
use ProcessPaymentTrait;
const ID = 'ppcp-credit-card-gateway'; const ID = 'ppcp-credit-card-gateway';
@ -76,6 +78,7 @@ class CreditCardGateway extends PayPalGateway {
'subscription_payment_method_change_customer', 'subscription_payment_method_change_customer',
'subscription_payment_method_change_admin', 'subscription_payment_method_change_admin',
'multiple_subscriptions', 'multiple_subscriptions',
'credit_card_form_cvc_on_saved_method',
); );
} }

View file

@ -23,6 +23,8 @@ use Psr\Container\ContainerInterface;
*/ */
class PayPalGateway extends \WC_Payment_Gateway { class PayPalGateway extends \WC_Payment_Gateway {
use ProcessPaymentTrait;
const ID = 'ppcp-gateway'; const ID = 'ppcp-gateway';
const CAPTURED_META_KEY = '_ppcp_paypal_captured'; const CAPTURED_META_KEY = '_ppcp_paypal_captured';
const INTENT_META_KEY = '_ppcp_paypal_intent'; 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. * Captures an authorized payment for an WooCommerce order.
* *

View file

@ -0,0 +1,82 @@
<?php
/**
* The process_payment functionality for the both gateways.
*
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
*/
declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
/**
* Trait ProcessPaymentTrait
*/
trait ProcessPaymentTrait {
/**
* 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;
}
}