mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
♻️ Move most of the display logic to base class
The PaymentButton base class now handles display logic that is shared between different APMs
This commit is contained in:
parent
b85a16abda
commit
fc805a4369
4 changed files with 539 additions and 414 deletions
|
@ -15,6 +15,54 @@ export const ButtonEvents = Object.freeze( {
|
||||||
REDRAW: 'ppcp_redraw_method',
|
REDRAW: 'ppcp_redraw_method',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} defaultId - Default wrapper ID.
|
||||||
|
* @param {string} miniCartId - Wrapper inside the mini-cart.
|
||||||
|
* @param {string} smartButtonId - ID of the smart button wrapper.
|
||||||
|
* @param {string} blockId - Block wrapper ID (express checkout, block cart).
|
||||||
|
* @param {string} gatewayId - Gateway wrapper ID (classic checkout).
|
||||||
|
* @return {{MiniCart, Gateway, Block, SmartButton, Default}} List of all wrapper IDs, by context.
|
||||||
|
*/
|
||||||
|
export function combineWrapperIds(
|
||||||
|
defaultId = '',
|
||||||
|
miniCartId = '',
|
||||||
|
smartButtonId = '',
|
||||||
|
blockId = '',
|
||||||
|
gatewayId = ''
|
||||||
|
) {
|
||||||
|
const sanitize = ( id ) => id.replace( /^#/, '' );
|
||||||
|
|
||||||
|
return {
|
||||||
|
Default: sanitize( defaultId ),
|
||||||
|
SmartButton: sanitize( smartButtonId ),
|
||||||
|
Block: sanitize( blockId ),
|
||||||
|
Gateway: sanitize( gatewayId ),
|
||||||
|
MiniCart: sanitize( miniCartId ),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns full payment button styles by combining the global ppcpConfig with
|
||||||
|
* payment-method-specific styling provided via buttonConfig.
|
||||||
|
*
|
||||||
|
* @param {Object} ppcpConfig - Global plugin configuration.
|
||||||
|
* @param {Object} buttonConfig - Payment method specific configuration.
|
||||||
|
* @return {{MiniCart: (*), Default: (*)}} Combined styles, separated by context.
|
||||||
|
*/
|
||||||
|
export function combineStyles( ppcpConfig, buttonConfig ) {
|
||||||
|
return {
|
||||||
|
Default: {
|
||||||
|
...ppcpConfig.style,
|
||||||
|
...buttonConfig.style,
|
||||||
|
},
|
||||||
|
MiniCart: {
|
||||||
|
...ppcpConfig.mini_cart_style,
|
||||||
|
...buttonConfig.mini_cart_style,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if the given event name is a valid Payment Button event.
|
* Verifies if the given event name is a valid Payment Button event.
|
||||||
*
|
*
|
||||||
|
@ -46,3 +94,24 @@ export function dispatchButtonEvent( { event, paymentMethod = '' } ) {
|
||||||
|
|
||||||
document.body.dispatchEvent( new Event( fullEventName ) );
|
document.body.dispatchEvent( new Event( fullEventName ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener for the provided button event.
|
||||||
|
*
|
||||||
|
* @param {Object} options - The options for the event listener.
|
||||||
|
* @param {string} options.event - Event to observe.
|
||||||
|
* @param {string} [options.paymentMethod] - The payment method name (optional).
|
||||||
|
* @param {Function} options.callback - The callback function to execute when the event is triggered.
|
||||||
|
* @throws {Error} Throws an error if the event is invalid.
|
||||||
|
*/
|
||||||
|
export function observeButtonEvent( { event, paymentMethod = '', callback } ) {
|
||||||
|
if ( ! isValidButtonEvent( event ) ) {
|
||||||
|
throw new Error( `Invalid event: ${ event }` );
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullEventName = paymentMethod
|
||||||
|
? `${ event }-${ paymentMethod }`
|
||||||
|
: event;
|
||||||
|
|
||||||
|
document.body.addEventListener( fullEventName, callback );
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
import ConsoleLogger from '../../../../../ppcp-wc-gateway/resources/js/helper/ConsoleLogger';
|
import ConsoleLogger from '../../../../../ppcp-wc-gateway/resources/js/helper/ConsoleLogger';
|
||||||
import { apmButtonsInit } from '../Helper/ApmButtons';
|
import { apmButtonsInit } from '../Helper/ApmButtons';
|
||||||
|
import { PaymentContext } from '../Helper/CheckoutMethodState';
|
||||||
|
import {
|
||||||
|
ButtonEvents,
|
||||||
|
dispatchButtonEvent,
|
||||||
|
observeButtonEvent,
|
||||||
|
} from '../Helper/PaymentButtonHelpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of all available styling options for this button.
|
||||||
|
*
|
||||||
|
* @typedef {Object} StylesCollection
|
||||||
|
* @property {string} Default - Default button styling.
|
||||||
|
* @property {string} MiniCart - Styles for mini-cart button.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of all available wrapper IDs that are possible for the button.
|
||||||
|
*
|
||||||
|
* @typedef {Object} WrapperCollection
|
||||||
|
* @property {string} Default - Default button wrapper.
|
||||||
|
* @property {string} Gateway - Wrapper for separate gateway.
|
||||||
|
* @property {string} Block - Wrapper for block checkout button.
|
||||||
|
* @property {string} MiniCart - Wrapper for mini-cart button.
|
||||||
|
* @property {string} SmartButton - Wrapper for smart button container.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for APM payment buttons, like GooglePay and ApplePay.
|
* Base class for APM payment buttons, like GooglePay and ApplePay.
|
||||||
|
@ -12,6 +37,11 @@ export default class PaymentButton {
|
||||||
*/
|
*/
|
||||||
#logger;
|
#logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
#methodId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the payment button is initialized.
|
* Whether the payment button is initialized.
|
||||||
*
|
*
|
||||||
|
@ -21,27 +51,105 @@ export default class PaymentButton {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button's context.
|
* The button's context.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
#context;
|
#context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing the IDs of all possible wrapper elements that might contain this
|
||||||
|
* button; only one wrapper is relevant, depending on the value of the context.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
#wrappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {StylesCollection}
|
||||||
|
*/
|
||||||
|
#styles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APM relevant configuration; e.g., configuration of the GooglePay button
|
||||||
|
*/
|
||||||
#buttonConfig;
|
#buttonConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin-wide configuration; i.e., PayPal client ID, shop currency, etc.
|
||||||
|
*/
|
||||||
#ppcpConfig;
|
#ppcpConfig;
|
||||||
|
|
||||||
constructor( gatewayName, context, buttonConfig, ppcpConfig ) {
|
/**
|
||||||
this.#logger = new ConsoleLogger( gatewayName, context );
|
* Whether the current browser/website support the payment method.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
#isEligible = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this button is visible. Modified by `show()` and `hide()`
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
#isVisible = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently visible payment button.
|
||||||
|
*
|
||||||
|
* @see {PaymentButton.insertButton}
|
||||||
|
* @type {HTMLElement|null}
|
||||||
|
*/
|
||||||
|
#button = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the payment button instance.
|
||||||
|
*
|
||||||
|
* @param {string} methodId - Payment method ID (slug, e.g., "ppcp-googlepay").
|
||||||
|
* @param {string} context - Button context name.
|
||||||
|
* @param {WrapperCollection} wrappers - Button wrapper IDs, by context.
|
||||||
|
* @param {StylesCollection} styles - Button styles, by context.
|
||||||
|
* @param {Object} buttonConfig - Payment button specific configuration.
|
||||||
|
* @param {Object} ppcpConfig - Plugin wide configuration object.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
methodId,
|
||||||
|
context,
|
||||||
|
wrappers,
|
||||||
|
styles,
|
||||||
|
buttonConfig,
|
||||||
|
ppcpConfig
|
||||||
|
) {
|
||||||
|
const methodName = methodId.replace( /^ppcp?-/, '' );
|
||||||
|
|
||||||
|
this.#methodId = methodId;
|
||||||
|
|
||||||
|
this.#logger = new ConsoleLogger( methodName, context );
|
||||||
this.#logger.enabled = !! buttonConfig?.is_debug;
|
this.#logger.enabled = !! buttonConfig?.is_debug;
|
||||||
|
|
||||||
this.#context = context;
|
this.#context = context;
|
||||||
|
this.#wrappers = wrappers;
|
||||||
|
this.#styles = styles;
|
||||||
this.#buttonConfig = buttonConfig;
|
this.#buttonConfig = buttonConfig;
|
||||||
this.#ppcpConfig = ppcpConfig;
|
this.#ppcpConfig = ppcpConfig;
|
||||||
|
|
||||||
apmButtonsInit( ppcpConfig );
|
apmButtonsInit( ppcpConfig );
|
||||||
|
this.initEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the payment button was fully initialized. Read-only.
|
* Internal ID of the payment gateway.
|
||||||
*
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {string} The internal gateway ID.
|
||||||
|
*/
|
||||||
|
get methodId() {
|
||||||
|
return this.#methodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the payment button was fully initialized.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
* @return {boolean} True indicates, that the button was fully initialized.
|
* @return {boolean} True indicates, that the button was fully initialized.
|
||||||
*/
|
*/
|
||||||
get isInitialized() {
|
get isInitialized() {
|
||||||
|
@ -49,16 +157,188 @@ export default class PaymentButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button's context. Read-only.
|
* The button's context.
|
||||||
*
|
*
|
||||||
* TODO: Convert the string to a context-object (primitive obsession smell)
|
* TODO: Convert the string to a context-object (primitive obsession smell)
|
||||||
*
|
*
|
||||||
|
* @readonly
|
||||||
* @return {string} The button context.
|
* @return {string} The button context.
|
||||||
*/
|
*/
|
||||||
get context() {
|
get context() {
|
||||||
return this.#context;
|
return this.#context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button wrapper details.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {WrapperCollection} Wrapper IDs.
|
||||||
|
*/
|
||||||
|
get wrappers() {
|
||||||
|
return this.#wrappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the context-relevant button style object.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {string} Styling options.
|
||||||
|
*/
|
||||||
|
get style() {
|
||||||
|
if ( PaymentContext.MiniCart === this.context ) {
|
||||||
|
return this.#styles.MiniCart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#styles.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the context-relevant wrapper ID.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {string} The wrapper-element's ID (without the `#` prefix).
|
||||||
|
*/
|
||||||
|
get wrapperId() {
|
||||||
|
if ( PaymentContext.MiniCart === this.context ) {
|
||||||
|
return this.wrappers.MiniCart;
|
||||||
|
} else if ( this.isSeparateGateway ) {
|
||||||
|
return this.wrappers.Gateway;
|
||||||
|
} else if ( PaymentContext.Blocks.includes( this.context ) ) {
|
||||||
|
return this.wrappers.Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.wrappers.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the current payment button should be rendered as a stand-alone gateway.
|
||||||
|
* The return value `false` usually means, that the payment button is bundled with all available
|
||||||
|
* payment buttons.
|
||||||
|
*
|
||||||
|
* The decision depends on the button context (placement) and the plugin settings.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if the current button represents a stand-alone gateway.
|
||||||
|
*/
|
||||||
|
get isSeparateGateway() {
|
||||||
|
return (
|
||||||
|
this.#buttonConfig.is_wc_gateway_enabled &&
|
||||||
|
PaymentContext.Gateways.includes( this.context )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the current button instance has valid and complete configuration details.
|
||||||
|
* Used during initialization to decide if the button can be initialized or should be skipped.
|
||||||
|
*
|
||||||
|
* Can be implemented by the derived class.
|
||||||
|
*
|
||||||
|
* @return {boolean} True indicates the config is valid and initialization can continue.
|
||||||
|
*/
|
||||||
|
get isConfigValid() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the browser can accept this payment method.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if payments are technically possible.
|
||||||
|
*/
|
||||||
|
get isEligible() {
|
||||||
|
return this.#isEligible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the eligibility state of this button component.
|
||||||
|
*
|
||||||
|
* @param {boolean} newState Whether the browser can accept payments.
|
||||||
|
*/
|
||||||
|
set isEligible( newState ) {
|
||||||
|
if ( newState === this.#isEligible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#isEligible = newState;
|
||||||
|
this.triggerRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The visibility state of the button.
|
||||||
|
* This flag does not reflect actual visibility on the page, but rather, if the button
|
||||||
|
* is intended/allowed to be displayed, in case all other checks pass.
|
||||||
|
*
|
||||||
|
* @return {boolean} True indicates, that the button can be displayed.
|
||||||
|
*/
|
||||||
|
get isVisible() {
|
||||||
|
return this.#isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the visibility of the button.
|
||||||
|
*
|
||||||
|
* A visible button does not always force the button to render on the page. It only means, that
|
||||||
|
* the button is allowed or not allowed to render, if certain other conditions are met.
|
||||||
|
*
|
||||||
|
* @param {boolean} newState Whether rendering the button is allowed.
|
||||||
|
*/
|
||||||
|
set isVisible( newState ) {
|
||||||
|
if ( this.#isVisible === newState ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#isVisible = newState;
|
||||||
|
this.triggerRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTML element that wraps the current button
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {HTMLElement|null} The wrapper element, or null.
|
||||||
|
*/
|
||||||
|
get wrapperElement() {
|
||||||
|
return document.getElementById( this.wrapperId );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the main button-wrapper is present in the current DOM.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {boolean} True, if the button context (wrapper element) is found.
|
||||||
|
*/
|
||||||
|
get isPresent() {
|
||||||
|
return this.wrapperElement instanceof HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of HTMLElements that belong to the payment button.
|
||||||
|
*
|
||||||
|
* @readonly
|
||||||
|
* @return {HTMLElement[]} List of payment button wrapper elements.
|
||||||
|
*/
|
||||||
|
get allElements() {
|
||||||
|
const selectors = [];
|
||||||
|
|
||||||
|
// Payment button (Pay now, smart button block)
|
||||||
|
selectors.push( `#${ this.wrapperId }` );
|
||||||
|
|
||||||
|
// Block Checkout: Express checkout button.
|
||||||
|
if ( PaymentContext.Blocks.includes( this.context ) ) {
|
||||||
|
selectors.push( `#${ this.wrappers.Block }` );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classic Checkout: Separate gateway.
|
||||||
|
if ( this.isSeparateGateway ) {
|
||||||
|
selectors.push(
|
||||||
|
`.wc_payment_method.payment_method_${ this.methodId }`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log( 'Wrapper Elements:', selectors );
|
||||||
|
return /** @type {HTMLElement[]} */ selectors.flatMap( ( selector ) =>
|
||||||
|
Array.from( document.querySelectorAll( selector ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a debug detail to the browser console.
|
* Log a debug detail to the browser console.
|
||||||
*
|
*
|
||||||
|
@ -98,4 +378,134 @@ export default class PaymentButton {
|
||||||
reinit() {
|
reinit() {
|
||||||
this.#isInitialized = false;
|
this.#isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerRedraw() {
|
||||||
|
dispatchButtonEvent( {
|
||||||
|
event: ButtonEvents.REDRAW,
|
||||||
|
paymentMethod: this.methodId,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches event listeners to show or hide the payment button when needed.
|
||||||
|
*/
|
||||||
|
initEventListeners() {
|
||||||
|
// Refresh the button - this might show, hide or re-create the payment button.
|
||||||
|
observeButtonEvent( {
|
||||||
|
event: ButtonEvents.REDRAW,
|
||||||
|
paymentMethod: this.methodId,
|
||||||
|
callback: () => this.refresh(),
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Events relevant for buttons inside a payment gateway.
|
||||||
|
if ( PaymentContext.Gateways.includes( this.context ) ) {
|
||||||
|
// Hide the button right after the user selected _any_ gateway.
|
||||||
|
observeButtonEvent( {
|
||||||
|
event: ButtonEvents.INVALIDATE,
|
||||||
|
callback: () => ( this.isVisible = false ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Show the button (again) when the user selected the current gateway.
|
||||||
|
observeButtonEvent( {
|
||||||
|
event: ButtonEvents.RENDER,
|
||||||
|
paymentMethod: this.methodId,
|
||||||
|
callback: () => ( this.isVisible = true ),
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the payment button on the page.
|
||||||
|
*/
|
||||||
|
refresh() {
|
||||||
|
const showButtonWrapper = () => {
|
||||||
|
this.log( 'Show' );
|
||||||
|
|
||||||
|
const styleSelectors = `style[data-hide-gateway="${ this.methodId }"]`;
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll( styleSelectors )
|
||||||
|
.forEach( ( el ) => el.remove() );
|
||||||
|
|
||||||
|
this.allElements.forEach( ( element ) => {
|
||||||
|
element.style.display = 'block';
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideButtonWrapper = () => {
|
||||||
|
this.log( 'Hide' );
|
||||||
|
|
||||||
|
this.allElements.forEach( ( element ) => {
|
||||||
|
element.style.display = 'none';
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Refresh or hide the actual payment button.
|
||||||
|
if ( this.isVisible ) {
|
||||||
|
this.addButton();
|
||||||
|
} else {
|
||||||
|
this.removeButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the wrapper or gateway entry, i.e. add space for the button.
|
||||||
|
if ( this.isEligible && this.isPresent ) {
|
||||||
|
showButtonWrapper();
|
||||||
|
} else {
|
||||||
|
hideButtonWrapper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the button wrapper element and inserts the provided payment button into the DOM.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} button - The button element to inject.
|
||||||
|
*/
|
||||||
|
insertButton( button ) {
|
||||||
|
if ( ! this.isPresent ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.#button ) {
|
||||||
|
this.#button.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#button = button;
|
||||||
|
this.log( 'addButton', button );
|
||||||
|
|
||||||
|
const wrapper = this.wrapperElement;
|
||||||
|
const { shape, height } = this.style;
|
||||||
|
const methodSlug = this.methodId.replace( /^ppcp?-/, '' );
|
||||||
|
|
||||||
|
wrapper.classList.add(
|
||||||
|
`ppcp-button-${ shape }`,
|
||||||
|
'ppcp-button-apm',
|
||||||
|
`ppcp-button-${ methodSlug }`
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( height ) {
|
||||||
|
wrapper.style.height = `${ height }px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.appendChild( button );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the payment button from the DOM.
|
||||||
|
*/
|
||||||
|
removeButton() {
|
||||||
|
if ( ! this.isPresent ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log( 'removeButton' );
|
||||||
|
|
||||||
|
if ( this.#button ) {
|
||||||
|
this.#button.remove();
|
||||||
|
}
|
||||||
|
this.#button = null;
|
||||||
|
|
||||||
|
const wrapper = this.wrapperElement;
|
||||||
|
|
||||||
|
wrapper.innerHTML = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/* global google */
|
/* global google */
|
||||||
|
|
||||||
|
import {
|
||||||
|
combineStyles,
|
||||||
|
combineWrapperIds,
|
||||||
|
} from '../../../ppcp-button/resources/js/modules/Helper/PaymentButtonHelpers';
|
||||||
import PaymentButton from '../../../ppcp-button/resources/js/modules/Renderer/PaymentButton';
|
import PaymentButton from '../../../ppcp-button/resources/js/modules/Renderer/PaymentButton';
|
||||||
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
|
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
|
||||||
import UpdatePaymentData from './Helper/UpdatePaymentData';
|
import UpdatePaymentData from './Helper/UpdatePaymentData';
|
||||||
import {
|
import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState';
|
||||||
PaymentMethods,
|
|
||||||
PaymentContext as CONTEXT,
|
|
||||||
} from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin-specific styling.
|
* Plugin-specific styling.
|
||||||
|
@ -28,24 +29,6 @@ import {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class GooglepayButton extends PaymentButton {
|
class GooglepayButton extends PaymentButton {
|
||||||
#wrapperId = '';
|
|
||||||
#ppcpButtonWrapperId = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the current client support the payment button.
|
|
||||||
* This state is mainly dependent on the response of `PaymentClient.isReadyToPay()`
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
#isEligible = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this button is visible. Modified by `show()` and `hide()`
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
#isVisible = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client reference, provided by the Google Pay JS SDK.
|
* Client reference, provided by the Google Pay JS SDK.
|
||||||
* @see https://developers.google.com/pay/api/web/reference/client
|
* @see https://developers.google.com/pay/api/web/reference/client
|
||||||
|
@ -59,221 +42,54 @@ class GooglepayButton extends PaymentButton {
|
||||||
ppcpConfig,
|
ppcpConfig,
|
||||||
contextHandler
|
contextHandler
|
||||||
) {
|
) {
|
||||||
super( 'GooglePayButton', context, buttonConfig, ppcpConfig );
|
const wrappers = combineWrapperIds(
|
||||||
|
buttonConfig.button.wrapper,
|
||||||
|
buttonConfig.button.mini_cart_wrapper,
|
||||||
|
ppcpConfig.button.wrapper,
|
||||||
|
'express-payment-method-ppcp-googlepay',
|
||||||
|
'ppc-button-ppcp-googlepay'
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log( ppcpConfig.button, buttonConfig.button );
|
||||||
|
|
||||||
|
const styles = combineStyles( ppcpConfig.button, buttonConfig.button );
|
||||||
|
|
||||||
|
if ( 'buy' === styles.MiniCart.type ) {
|
||||||
|
styles.MiniCart.type = 'pay';
|
||||||
|
}
|
||||||
|
|
||||||
|
super(
|
||||||
|
PaymentMethods.GOOGLEPAY,
|
||||||
|
context,
|
||||||
|
wrappers,
|
||||||
|
styles,
|
||||||
|
buttonConfig,
|
||||||
|
ppcpConfig
|
||||||
|
);
|
||||||
|
|
||||||
this.externalHandler = externalHandler;
|
|
||||||
this.buttonConfig = buttonConfig;
|
this.buttonConfig = buttonConfig;
|
||||||
this.ppcpConfig = ppcpConfig;
|
|
||||||
this.contextHandler = contextHandler;
|
this.contextHandler = contextHandler;
|
||||||
|
|
||||||
this.refresh = this.refresh.bind( this );
|
|
||||||
|
|
||||||
this.log( 'Create instance' );
|
this.log( 'Create instance' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the current payment button should be rendered as a stand-alone gateway.
|
* @inheritDoc
|
||||||
* The return value `false` usually means, that the payment button is bundled with all available
|
|
||||||
* payment buttons.
|
|
||||||
*
|
|
||||||
* The decision depends on the button context (placement) and the plugin settings.
|
|
||||||
*
|
|
||||||
* @return {boolean} True, if the current button represents a stand-alone gateway.
|
|
||||||
*/
|
*/
|
||||||
get isSeparateGateway() {
|
get isConfigValid() {
|
||||||
return (
|
const validEnvs = [ 'PRODUCTION', 'TEST' ];
|
||||||
this.buttonConfig.is_wc_gateway_enabled &&
|
|
||||||
CONTEXT.Gateways.includes( this.context )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if ( ! validEnvs.includes( this.buttonConfig.environment ) ) {
|
||||||
* Returns the wrapper ID for the current button context.
|
this.error( 'Invalid environment.', this.buttonConfig.environment );
|
||||||
* The ID varies for the MiniCart context.
|
return false;
|
||||||
*
|
|
||||||
* @return {string} The wrapper-element's ID (without the `#` prefix).
|
|
||||||
*/
|
|
||||||
get wrapperId() {
|
|
||||||
if ( ! this.#wrapperId ) {
|
|
||||||
let id;
|
|
||||||
|
|
||||||
if ( CONTEXT.MiniCart === this.context ) {
|
|
||||||
id = this.buttonConfig.button.mini_cart_wrapper;
|
|
||||||
} else if ( this.isSeparateGateway ) {
|
|
||||||
id = 'ppc-button-ppcp-googlepay';
|
|
||||||
} else {
|
|
||||||
id = this.buttonConfig.button.wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#wrapperId = id.replace( /^#/, '' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.#wrapperId;
|
if ( ! typeof this.contextHandler?.validateContext() ) {
|
||||||
}
|
this.error( 'Invalid context handler.', this.contextHandler );
|
||||||
|
return false;
|
||||||
/**
|
|
||||||
* Returns the wrapper ID for the ppcpButton
|
|
||||||
*
|
|
||||||
* @return {string} The wrapper-element's ID (without the `#` prefix).
|
|
||||||
*/
|
|
||||||
get ppcpButtonWrapperId() {
|
|
||||||
if ( ! this.#ppcpButtonWrapperId ) {
|
|
||||||
let id;
|
|
||||||
|
|
||||||
if ( CONTEXT.MiniCart === this.context ) {
|
|
||||||
id = this.ppcpConfig.button.mini_cart_wrapper;
|
|
||||||
} else if ( CONTEXT.Blocks.includes( this.context ) ) {
|
|
||||||
id = 'express-payment-method-ppcp-gateway-paypal';
|
|
||||||
} else {
|
|
||||||
id = this.ppcpConfig.button.wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#ppcpButtonWrapperId = id.replace( /^#/, '' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.#ppcpButtonWrapperId;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the context-relevant PPCP style object.
|
|
||||||
* The style for the MiniCart context can be different.
|
|
||||||
*
|
|
||||||
* The PPCP style are custom style options, that are provided by this plugin.
|
|
||||||
*
|
|
||||||
* @return {PPCPStyle} The style object.
|
|
||||||
*/
|
|
||||||
get ppcpStyle() {
|
|
||||||
if ( CONTEXT.MiniCart === this.context ) {
|
|
||||||
return this.ppcpConfig.button.mini_cart_style;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.ppcpConfig.button.style;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns default style options that are propagated to and rendered by the Google Pay button.
|
|
||||||
*
|
|
||||||
* These styles are the official style options provided by the Google Pay SDK.
|
|
||||||
*
|
|
||||||
* @return {GooglePayStyle} The style object.
|
|
||||||
*/
|
|
||||||
get buttonStyle() {
|
|
||||||
let style;
|
|
||||||
|
|
||||||
if ( CONTEXT.MiniCart === this.context ) {
|
|
||||||
style = this.buttonConfig.button.mini_cart_style;
|
|
||||||
|
|
||||||
// Handle incompatible types.
|
|
||||||
if ( style.type === 'buy' ) {
|
|
||||||
style.type = 'pay';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
style = this.buttonConfig.button.style;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: style.type,
|
|
||||||
language: style.language,
|
|
||||||
color: style.color,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the HTML element that wraps the current button
|
|
||||||
*
|
|
||||||
* @return {HTMLElement|null} The wrapper element, or null.
|
|
||||||
*/
|
|
||||||
get wrapperElement() {
|
|
||||||
return document.getElementById( this.wrapperId );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of HTMLElements that belong to the payment button.
|
|
||||||
*
|
|
||||||
* @return {HTMLElement[]} List of payment button wrapper elements.
|
|
||||||
*/
|
|
||||||
get allElements() {
|
|
||||||
const selectors = [];
|
|
||||||
|
|
||||||
// Payment button (Pay now, smart button block)
|
|
||||||
selectors.push( `#${ this.wrapperId }` );
|
|
||||||
|
|
||||||
// Block Checkout: Express checkout button.
|
|
||||||
if ( CONTEXT.Blocks.includes( this.context ) ) {
|
|
||||||
selectors.push( '#express-payment-method-ppcp-googlepay' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Classic Checkout: Google Pay gateway.
|
|
||||||
if ( CONTEXT.Gateways === this.context ) {
|
|
||||||
selectors.push(
|
|
||||||
'.wc_payment_method.payment_method_ppcp-googlepay'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log( 'Wrapper Elements:', selectors );
|
|
||||||
return /** @type {HTMLElement[]} */ selectors.flatMap( ( selector ) =>
|
|
||||||
Array.from( document.querySelectorAll( selector ) )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the main button-wrapper is present in the current DOM.
|
|
||||||
*
|
|
||||||
* @return {boolean} True, if the button context (wrapper element) is found.
|
|
||||||
*/
|
|
||||||
get isPresent() {
|
|
||||||
return this.wrapperElement instanceof HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The visibility state of the button.
|
|
||||||
* This flag does not reflect actual visibility on the page, but rather, if the button
|
|
||||||
* is intended/allowed to be displayed, in case all other checks pass.
|
|
||||||
*
|
|
||||||
* @return {boolean} True indicates, that the button can be displayed
|
|
||||||
*/
|
|
||||||
get isVisible() {
|
|
||||||
return this.#isVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the visibility of the button.
|
|
||||||
*
|
|
||||||
* A visible button does not always force the button to render on the page. It only means, that
|
|
||||||
* the button is allowed or not allowed to render, if certain other conditions are met.
|
|
||||||
*
|
|
||||||
* @param {boolean} newState Whether rendering the button is allowed.
|
|
||||||
*/
|
|
||||||
set isVisible( newState ) {
|
|
||||||
if ( this.#isVisible === newState ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#isVisible = newState;
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the browser can accept Google Pay payments.
|
|
||||||
*
|
|
||||||
* @return {boolean} True, if payments are technically possible.
|
|
||||||
*/
|
|
||||||
get isEligible() {
|
|
||||||
return this.#isEligible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the eligibility state of this button component.
|
|
||||||
*
|
|
||||||
* @param {boolean} newState Whether the browser can accept payments.
|
|
||||||
*/
|
|
||||||
set isEligible( newState ) {
|
|
||||||
if ( newState === this.#isEligible ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#isEligible = newState;
|
|
||||||
this.refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init( config = null, transactionInfo = null ) {
|
init( config = null, transactionInfo = null ) {
|
||||||
|
@ -288,27 +104,24 @@ class GooglepayButton extends PaymentButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! this.googlePayConfig || ! this.transactionInfo ) {
|
if ( ! this.googlePayConfig || ! this.transactionInfo ) {
|
||||||
this.error(
|
this.error( 'Missing config or transactionInfo during init.' );
|
||||||
'Init called without providing config or transactionInfo'
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! this.validateConfig() ) {
|
if ( ! this.isConfigValid ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! this.contextHandler.validateContext() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
this.allowedPaymentMethods = config.allowedPaymentMethods;
|
this.allowedPaymentMethods = config.allowedPaymentMethods;
|
||||||
this.baseCardPaymentMethod = this.allowedPaymentMethods[ 0 ];
|
this.baseCardPaymentMethod = this.allowedPaymentMethods[ 0 ];
|
||||||
|
|
||||||
|
super.init();
|
||||||
this.initClient();
|
this.initClient();
|
||||||
this.initEventHandlers();
|
|
||||||
|
if ( ! this.isPresent ) {
|
||||||
|
this.log( 'Payment wrapper not found', this.wrapperId );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.paymentsClient
|
this.paymentsClient
|
||||||
.isReadyToPay(
|
.isReadyToPay(
|
||||||
|
@ -319,17 +132,7 @@ class GooglepayButton extends PaymentButton {
|
||||||
)
|
)
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
this.log( 'PaymentsClient.isReadyToPay response:', response );
|
this.log( 'PaymentsClient.isReadyToPay response:', response );
|
||||||
|
this.isEligible = !! response.result;
|
||||||
/**
|
|
||||||
* In case the button wrapper element is not present in the DOM yet, wait for it
|
|
||||||
* to appear. Only proceed, if a button wrapper is found on this page.
|
|
||||||
*
|
|
||||||
* Not sure if this is needed, or if we can directly test for `this.isPresent`
|
|
||||||
* without any delay.
|
|
||||||
*/
|
|
||||||
this.waitForWrapper( () => {
|
|
||||||
this.isEligible = !! response.result;
|
|
||||||
} );
|
|
||||||
} )
|
} )
|
||||||
.catch( ( err ) => {
|
.catch( ( err ) => {
|
||||||
console.error( err );
|
console.error( err );
|
||||||
|
@ -346,30 +149,6 @@ class GooglepayButton extends PaymentButton {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
validateConfig() {
|
|
||||||
if (
|
|
||||||
[ 'PRODUCTION', 'TEST' ].indexOf(
|
|
||||||
this.buttonConfig.environment
|
|
||||||
) === -1
|
|
||||||
) {
|
|
||||||
console.error(
|
|
||||||
'[GooglePayButton] Invalid environment.',
|
|
||||||
this.buttonConfig.environment
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! this.contextHandler ) {
|
|
||||||
console.error(
|
|
||||||
'[GooglePayButton] Invalid context handler.',
|
|
||||||
this.contextHandler
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
initClient() {
|
initClient() {
|
||||||
const callbacks = {
|
const callbacks = {
|
||||||
onPaymentAuthorized: this.onPaymentAuthorized.bind( this ),
|
onPaymentAuthorized: this.onPaymentAuthorized.bind( this ),
|
||||||
|
@ -394,51 +173,6 @@ class GooglepayButton extends PaymentButton {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
initEventHandlers() {
|
|
||||||
if ( CONTEXT.Gateways.includes( this.context ) ) {
|
|
||||||
document.body.addEventListener( 'ppcp_invalidate_methods', () => {
|
|
||||||
this.isVisible = false;
|
|
||||||
} );
|
|
||||||
|
|
||||||
document.body.addEventListener(
|
|
||||||
`ppcp_render_method-${ PaymentMethods.GOOGLEPAY }`,
|
|
||||||
() => {
|
|
||||||
this.isVisible = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* Review: The following logic appears to be unnecessary. Is it still required?
|
|
||||||
* /
|
|
||||||
const ppcpButtonWrapper = `#${ this.ppcpButtonWrapperId }`;
|
|
||||||
const wrapper = `#${ this.wrapperId }`;
|
|
||||||
if ( wrapper === ppcpButtonWrapper ) {
|
|
||||||
throw new Error(
|
|
||||||
`[GooglePayButton] "wrapper" and "ppcpButtonWrapper" values must differ to avoid infinite loop. Current value: "${ wrapper }"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const syncButtonVisibility = () => {
|
|
||||||
const $ppcpButtonWrapper = jQuery( ppcpButtonWrapper );
|
|
||||||
setVisible( wrapper, $ppcpButtonWrapper.is( ':visible' ) );
|
|
||||||
setEnabled(
|
|
||||||
wrapper,
|
|
||||||
! $ppcpButtonWrapper.hasClass( 'ppcp-disabled' )
|
|
||||||
);
|
|
||||||
};
|
|
||||||
jQuery( document ).on(
|
|
||||||
'ppcp-shown ppcp-hidden ppcp-enabled ppcp-disabled',
|
|
||||||
( ev, data ) => {
|
|
||||||
if ( jQuery( data.selector ).is( ppcpButtonWrapper ) ) {
|
|
||||||
syncButtonVisibility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
syncButtonVisibility();
|
|
||||||
//
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildReadyToPayRequest( allowedPaymentMethods, baseRequest ) {
|
buildReadyToPayRequest( allowedPaymentMethods, baseRequest ) {
|
||||||
this.log( 'Ready To Pay request', baseRequest, allowedPaymentMethods );
|
this.log( 'Ready To Pay request', baseRequest, allowedPaymentMethods );
|
||||||
|
|
||||||
|
@ -448,25 +182,11 @@ class GooglepayButton extends PaymentButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a Google Pay purchase button
|
* Add a Google Pay purchase button.
|
||||||
*/
|
*/
|
||||||
addButton() {
|
addButton() {
|
||||||
this.log( 'addButton' );
|
|
||||||
|
|
||||||
const wrapper = this.wrapperElement;
|
|
||||||
const baseCardPaymentMethod = this.baseCardPaymentMethod;
|
const baseCardPaymentMethod = this.baseCardPaymentMethod;
|
||||||
const { color, type, language } = this.buttonStyle;
|
const { color, type, language } = this.style;
|
||||||
const { shape, height } = this.ppcpStyle;
|
|
||||||
|
|
||||||
wrapper.classList.add(
|
|
||||||
`ppcp-button-${ shape }`,
|
|
||||||
'ppcp-button-apm',
|
|
||||||
'ppcp-button-googlepay'
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( height ) {
|
|
||||||
wrapper.style.height = `${ height }px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://developers.google.com/pay/api/web/reference/client#createButton
|
* @see https://developers.google.com/pay/api/web/reference/client#createButton
|
||||||
|
@ -480,84 +200,7 @@ class GooglepayButton extends PaymentButton {
|
||||||
buttonSizeMode: 'fill',
|
buttonSizeMode: 'fill',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
this.log( 'Insert Button', {
|
this.insertButton( button );
|
||||||
wrapper,
|
|
||||||
button,
|
|
||||||
} );
|
|
||||||
|
|
||||||
wrapper.replaceChildren( button );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for the current button's wrapper element to become available in the DOM.
|
|
||||||
*
|
|
||||||
* Not sure if still needed, or if a simple `this.isPresent` check is sufficient.
|
|
||||||
*
|
|
||||||
* @param {Function} callback Function to call when the wrapper element was detected. Only
|
|
||||||
* called on success.
|
|
||||||
* @param {number} delay Optional. Polling interval to inspect the DOM. Default to 0.1 sec
|
|
||||||
* @param {number} timeout Optional. Max timeout in ms. Defaults to 2 sec
|
|
||||||
*/
|
|
||||||
waitForWrapper( callback, delay = 100, timeout = 2000 ) {
|
|
||||||
let interval = 0;
|
|
||||||
const startTime = Date.now();
|
|
||||||
|
|
||||||
const stop = () => {
|
|
||||||
if ( interval ) {
|
|
||||||
clearInterval( interval );
|
|
||||||
}
|
|
||||||
interval = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkElement = () => {
|
|
||||||
if ( this.isPresent ) {
|
|
||||||
stop();
|
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeElapsed = Date.now() - startTime;
|
|
||||||
|
|
||||||
if ( timeElapsed > timeout ) {
|
|
||||||
stop();
|
|
||||||
this.error( 'Wrapper not found:', this.wrapperId );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interval = setInterval( checkElement, delay );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refreshes the payment button on the page.
|
|
||||||
*/
|
|
||||||
refresh() {
|
|
||||||
const showButtonWrapper = () => {
|
|
||||||
this.log( 'Show' );
|
|
||||||
|
|
||||||
// Classic Checkout: Make the Google Pay gateway visible.
|
|
||||||
document
|
|
||||||
.querySelectorAll( 'style#ppcp-hide-google-pay' )
|
|
||||||
.forEach( ( el ) => el.remove() );
|
|
||||||
|
|
||||||
this.allElements.forEach( ( element ) => {
|
|
||||||
element.style.display = 'block';
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
|
|
||||||
const hideButtonWrapper = () => {
|
|
||||||
this.log( 'Hide' );
|
|
||||||
|
|
||||||
this.allElements.forEach( ( element ) => {
|
|
||||||
element.style.display = 'none';
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( this.isVisible && this.isEligible && this.isPresent ) {
|
|
||||||
showButtonWrapper();
|
|
||||||
this.addButton();
|
|
||||||
} else {
|
|
||||||
hideButtonWrapper();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
|
|
|
@ -345,9 +345,12 @@ class Button implements ButtonInterface {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function hide_gateway_until_eligible() : void {
|
protected function hide_gateway_until_eligible() : void {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<style id="ppcp-hide-google-pay">
|
<style data-hide-gateway='<?php echo esc_attr( GooglePayGateway::ID ); ?>'>
|
||||||
.wc_payment_method.payment_method_ppcp-googlepay { : none}
|
.wc_payment_method.payment_method_ppcp-googlepay {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue