From a473459ddbf377f3f9d01f596365f89a8e4287fd Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Tue, 23 Jul 2024 17:36:10 +0200
Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Minor=20code=20cleanup=20a?=
=?UTF-8?q?nd=20documentation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/ApplepayButton.js | 192 +++++++++++-------
.../resources/js/ApplepayManager.js | 15 +-
.../js/ApplepayManagerBlockEditor.js | 10 +-
.../resources/js/Context/BaseHandler.js | 8 -
.../resources/js/Context/PreviewHandler.js | 6 +-
.../ppcp-applepay/resources/js/boot-admin.js | 4 +-
.../ppcp-applepay/resources/js/boot-block.js | 8 +-
modules/ppcp-applepay/resources/js/boot.js | 4 +-
8 files changed, 142 insertions(+), 105 deletions(-)
diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js
index b703a9565..3a1a13a00 100644
--- a/modules/ppcp-applepay/resources/js/ApplepayButton.js
+++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js
@@ -10,6 +10,23 @@ import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons';
+/**
+ * List of valid context values that the button can have.
+ *
+ * @type {Object}
+ */
+const CONTEXT = {
+ Product: 'product',
+ Cart: 'cart',
+ Checkout: 'checkout',
+ PayNow: 'pay-now',
+ MiniCart: 'mini-cart',
+ BlockCart: 'cart-block',
+ BlockCheckout: 'checkout-block',
+ Preview: 'preview',
+ Blocks: [ 'cart-block', 'checkout-block' ],
+};
+
/**
* A payment button for Apple Pay.
*
@@ -32,6 +49,20 @@ class ApplePayButton {
*/
context = '';
+ externalHandler = null;
+ buttonConfig = null;
+ ppcpConfig = null;
+ paymentsClient = null;
+ formData = null;
+ contextHandler = null;
+ updatedContactInfo = [];
+ selectedShippingMethod = [];
+
+ /**
+ * Stores initialization data sent to the button.
+ */
+ initialPaymentRequest = null;
+
constructor( context, externalHandler, buttonConfig, ppcpConfig ) {
apmButtonsInit( ppcpConfig );
@@ -39,8 +70,6 @@ class ApplePayButton {
this.externalHandler = externalHandler;
this.buttonConfig = buttonConfig;
this.ppcpConfig = ppcpConfig;
- this.paymentsClient = null;
- this.formData = null;
this.contextHandler = ContextHandlerFactory.create(
this.context,
@@ -48,18 +77,6 @@ class ApplePayButton {
this.ppcpConfig
);
- this.updatedContactInfo = [];
- this.selectedShippingMethod = [];
- this.nonce =
- document.getElementById( 'woocommerce-process-checkout-nonce' )
- ?.value || buttonConfig.nonce;
-
- // Stores initialization data sent to the button.
- this.initialPaymentRequest = null;
-
- // Default eligibility status.
- this.isEligible = true;
-
this.log = function () {
if ( this.buttonConfig.is_debug ) {
//console.log('[ApplePayButton]', ...arguments);
@@ -76,6 +93,39 @@ class ApplePayButton {
document.ppcpApplepayButtons[ this.context ] = this;
}
+ /**
+ * The nonce for ajax requests.
+ *
+ * @return {string} The nonce value
+ */
+ get nonce() {
+ const input = document.getElementById(
+ 'woocommerce-process-checkout-nonce'
+ );
+
+ return input?.value || this.buttonConfig.nonce;
+ }
+
+ /**
+ * Whether the current page qualifies to use the Apple Pay button.
+ *
+ * In admin, the button is always eligible, to display an accurate preview.
+ * On front-end, PayPal's response decides if customers can use Apple Pay.
+ *
+ * @return {boolean} True, if the button can be displayed.
+ */
+ get isEligible() {
+ if ( ! this.isInitialized ) {
+ return true;
+ }
+
+ if ( this.buttonConfig.is_admin ) {
+ return true;
+ }
+
+ return !! ( this.applePayConfig.isEligible && window.ApplePaySession );
+ }
+
init( config ) {
if ( this.isInitialized ) {
return;
@@ -90,9 +140,6 @@ class ApplePayButton {
this.isInitialized = true;
this.applePayConfig = config;
- this.isEligible =
- ( this.applePayConfig.isEligible && window.ApplePaySession ) ||
- this.buttonConfig.is_admin;
const idMinicart = this.buttonConfig.button.mini_cart_wrapper;
const idButton = this.buttonConfig.button.wrapper;
@@ -118,7 +165,7 @@ class ApplePayButton {
this.fetchTransactionInfo().then( () => {
this.addButton();
- if ( this.context === 'mini-cart' ) {
+ if ( CONTEXT.MiniCart === this.context ) {
setupButtonEvents( idMinicart );
} else {
setupButtonEvents( idButton );
@@ -143,23 +190,22 @@ class ApplePayButton {
* Returns configurations relative to this button context.
*/
contextConfig() {
- const config = {
- wrapper: this.buttonConfig.button.wrapper,
- ppcpStyle: this.ppcpConfig.button.style,
- buttonStyle: this.buttonConfig.button.style,
- ppcpButtonWrapper: this.ppcpConfig.button.wrapper,
- };
+ const config = {};
- if ( this.context === 'mini-cart' ) {
+ if ( CONTEXT.MiniCart === this.context ) {
config.wrapper = this.buttonConfig.button.mini_cart_wrapper;
config.ppcpStyle = this.ppcpConfig.button.mini_cart_style;
config.buttonStyle = this.buttonConfig.button.mini_cart_style;
config.ppcpButtonWrapper = this.ppcpConfig.button.mini_cart_wrapper;
+ } else {
+ config.wrapper = this.buttonConfig.button.wrapper;
+ config.ppcpStyle = this.ppcpConfig.button.style;
+ config.buttonStyle = this.buttonConfig.button.style;
+ config.ppcpButtonWrapper = this.ppcpConfig.button.wrapper;
}
- if (
- [ 'cart-block', 'checkout-block' ].indexOf( this.context ) !== -1
- ) {
+ // Block editor configuration.
+ if ( CONTEXT.Blocks.includes( this.context ) ) {
config.ppcpButtonWrapper =
'#express-payment-method-ppcp-gateway-paypal';
}
@@ -203,8 +249,9 @@ class ApplePayButton {
}
/**
- * Starts an ApplePay session.
- * @param paymentRequest
+ * Starts an Apple Pay session.
+ *
+ * @param {Object} paymentRequest The payment request object.
*/
applePaySession( paymentRequest ) {
this.log( 'applePaySession', paymentRequest );
@@ -269,7 +316,7 @@ class ApplePayButton {
window.ppcpFundingSource = 'apple_pay';
// Trigger woocommerce validation if we are in the checkout page.
- if ( this.context === 'checkout' ) {
+ if ( CONTEXT.Checkout === this.context ) {
const checkoutFormSelector = 'form.woocommerce-checkout';
const errorHandler = new ErrorHandler(
PayPalCommerceGateway.labels.error.generic,
@@ -323,13 +370,13 @@ class ApplePayButton {
/**
* If the button should show the shipping fields.
*
- * @return {false|*}
+ * @return {boolean} True, if shipping fields should be captured by ApplePay.
*/
shouldRequireShippingInButton() {
return (
this.contextHandler.shippingAllowed() &&
this.buttonConfig.product.needShipping &&
- ( this.context !== 'checkout' ||
+ ( CONTEXT.Checkout !== this.context ||
this.shouldUpdateButtonWithFormData() )
);
}
@@ -337,10 +384,10 @@ class ApplePayButton {
/**
* If the button should be updated with the form addresses.
*
- * @return {boolean}
+ * @return {boolean} True, when Apple Pay data should be submitted to WooCommerce.
*/
shouldUpdateButtonWithFormData() {
- if ( this.context !== 'checkout' ) {
+ if ( CONTEXT.Checkout !== this.context ) {
return false;
}
return (
@@ -353,7 +400,7 @@ class ApplePayButton {
* Indicates how payment completion should be handled if with the context handler default
* actions. Or with Apple Pay module specific completion.
*
- * @return {boolean}
+ * @return {boolean} True, when the Apple Pay data should be submitted to WooCommerce.
*/
shouldCompletePaymentWithContextHandler() {
// Data already handled, ex: PayNow
@@ -363,7 +410,7 @@ class ApplePayButton {
// Use WC form data mode in Checkout.
return (
- this.context === 'checkout' &&
+ CONTEXT.Checkout === this.context &&
! this.shouldUpdateButtonWithFormData()
);
}
@@ -371,7 +418,7 @@ class ApplePayButton {
/**
* Updates Apple Pay paymentRequest with form data.
*
- * @param paymentRequest
+ * @param {Object} paymentRequest Object to extend with form data.
*/
updateRequestDataWithForm( paymentRequest ) {
if ( ! this.shouldUpdateButtonWithFormData() ) {
@@ -481,11 +528,11 @@ class ApplePayButton {
}
refreshContextData() {
- if ( 'product' === this.context ) {
- // Refresh product data that makes the price change.
+ if ( CONTEXT.Product === this.context ) {
+ // Refresh product data that makes the price change.
this.productQuantity = document.querySelector( 'input.qty' )?.value;
- this.products = this.contextHandler.products();
- this.log( 'Products updated', this.products );
+ this.products = this.contextHandler.products();
+ this.log( 'Products updated', this.products );
}
}
@@ -518,8 +565,9 @@ class ApplePayButton {
*
* @see https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778021-onvalidatemerchant
*
- * @param session
- * @return {(function(*): void)|*}
+ * @param {Object} session The ApplePaySession object.
+ *
+ * @return {(function(*): void)|*} Callback that runs after the merchant validation
*/
onValidateMerchant( session ) {
return ( applePayValidateMerchantEvent ) => {
@@ -548,14 +596,14 @@ class ApplePayButton {
onShippingMethodSelected( session ) {
this.log( 'onshippingmethodselected', this.buttonConfig.ajax_url );
- const ajax_url = this.buttonConfig.ajax_url;
+ const ajaxUrl = this.buttonConfig.ajax_url;
return ( event ) => {
this.log( 'onshippingmethodselected call' );
const data = this.getShippingMethodData( event );
jQuery.ajax( {
- url: ajax_url,
+ url: ajaxUrl,
method: 'POST',
data,
success: (
@@ -599,7 +647,7 @@ class ApplePayButton {
onShippingContactSelected( session ) {
this.log( 'onshippingcontactselected', this.buttonConfig.ajax_url );
- const ajax_url = this.buttonConfig.ajax_url;
+ const ajaxUrl = this.buttonConfig.ajax_url;
return ( event ) => {
this.log( 'onshippingcontactselected call' );
@@ -607,7 +655,7 @@ class ApplePayButton {
const data = this.getShippingContactData( event );
jQuery.ajax( {
- url: ajax_url,
+ url: ajaxUrl,
method: 'POST',
data,
success: (
@@ -637,15 +685,15 @@ class ApplePayButton {
}
getShippingContactData( event ) {
- const product_id = this.buttonConfig.product.id;
+ const productId = this.buttonConfig.product.id;
this.refreshContextData();
switch ( this.context ) {
- case 'product':
+ case CONTEXT.Product:
return {
action: 'ppcp_update_shipping_contact',
- product_id,
+ product_id: productId,
products: JSON.stringify( this.products ),
caller_page: 'productDetail',
product_quantity: this.productQuantity,
@@ -653,11 +701,12 @@ class ApplePayButton {
need_shipping: this.shouldRequireShippingInButton(),
'woocommerce-process-checkout-nonce': this.nonce,
};
- case 'cart':
- case 'checkout':
- case 'cart-block':
- case 'checkout-block':
- case 'mini-cart':
+
+ case CONTEXT.Cart:
+ case CONTEXT.Checkout:
+ case CONTEXT.BlockCart:
+ case CONTEXT.BlockCheckout:
+ case CONTEXT.MiniCart:
return {
action: 'ppcp_update_shipping_contact',
simplified_contact: event.shippingContact,
@@ -669,12 +718,12 @@ class ApplePayButton {
}
getShippingMethodData( event ) {
- const product_id = this.buttonConfig.product.id;
+ const productId = this.buttonConfig.product.id;
this.refreshContextData();
switch ( this.context ) {
- case 'product':
+ case CONTEXT.Product:
return {
action: 'ppcp_update_shipping_method',
shipping_method: event.shippingMethod,
@@ -682,17 +731,18 @@ class ApplePayButton {
this.updatedContactInfo ||
this.initialPaymentRequest.shippingContact ||
this.initialPaymentRequest.billingContact,
- product_id,
+ product_id: productId,
products: JSON.stringify( this.products ),
caller_page: 'productDetail',
product_quantity: this.productQuantity,
'woocommerce-process-checkout-nonce': this.nonce,
};
- case 'cart':
- case 'checkout':
- case 'cart-block':
- case 'checkout-block':
- case 'mini-cart':
+
+ case CONTEXT.Cart:
+ case CONTEXT.Checkout:
+ case CONTEXT.BlockCart:
+ case CONTEXT.BlockCheckout:
+ case CONTEXT.MiniCart:
return {
action: 'ppcp_update_shipping_method',
shipping_method: event.shippingMethod,
@@ -711,10 +761,6 @@ class ApplePayButton {
return async ( event ) => {
this.log( 'onpaymentauthorized call' );
- function form() {
- return document.querySelector( 'form.cart' );
- }
-
const processInWooAndCapture = async ( data ) => {
return new Promise( ( resolve, reject ) => {
try {
@@ -729,7 +775,7 @@ class ApplePayButton {
( this.initialPaymentRequest.shippingMethods ||
[] )[ 0 ];
- const request_data = {
+ const requestData = {
action: 'ppcp_create_order',
caller_page: this.context,
product_id: this.buttonConfig.product.id ?? null,
@@ -754,7 +800,7 @@ class ApplePayButton {
jQuery.ajax( {
url: this.buttonConfig.ajax_url,
method: 'POST',
- data: request_data,
+ data: requestData,
complete: ( jqXHR, textStatus ) => {
this.log( 'onpaymentauthorized complete' );
},
@@ -829,15 +875,15 @@ class ApplePayButton {
restart: () =>
new Promise(
( resolve, reject ) => {
- approveFailed = true;
- resolve();
+ approveFailed = true;
+ resolve();
}
),
order: {
get: () =>
new Promise(
( resolve, reject ) => {
- resolve( null );
+ resolve( null );
}
),
},
diff --git a/modules/ppcp-applepay/resources/js/ApplepayManager.js b/modules/ppcp-applepay/resources/js/ApplepayManager.js
index 0992d9e7d..264610f28 100644
--- a/modules/ppcp-applepay/resources/js/ApplepayManager.js
+++ b/modules/ppcp-applepay/resources/js/ApplepayManager.js
@@ -1,7 +1,9 @@
-import buttonModuleWatcher from '../../../ppcp-button/resources/js/modules/ButtonModuleWatcher';
-import ApplepayButton from './ApplepayButton';
+/* global paypal */
-class ApplepayManager {
+import buttonModuleWatcher from '../../../ppcp-button/resources/js/modules/ButtonModuleWatcher';
+import ApplePayButton from './ApplepayButton';
+
+class ApplePayManager {
constructor( buttonConfig, ppcpConfig ) {
this.buttonConfig = buttonConfig;
this.ppcpConfig = ppcpConfig;
@@ -9,7 +11,7 @@ class ApplepayManager {
this.buttons = [];
buttonModuleWatcher.watchContextBootstrap( ( bootstrap ) => {
- const button = new ApplepayButton(
+ const button = new ApplePayButton(
bootstrap.context,
bootstrap.handler,
buttonConfig,
@@ -40,8 +42,7 @@ class ApplepayManager {
}
/**
- * Gets ApplePay configuration of the PayPal merchant.
- * @return {Promise}
+ * Gets Apple Pay configuration of the PayPal merchant.
*/
async config() {
this.ApplePayConfig = await paypal.Applepay().config();
@@ -49,4 +50,4 @@ class ApplepayManager {
}
}
-export default ApplepayManager;
+export default ApplePayManager;
diff --git a/modules/ppcp-applepay/resources/js/ApplepayManagerBlockEditor.js b/modules/ppcp-applepay/resources/js/ApplepayManagerBlockEditor.js
index 2f4db9d41..1c10bb997 100644
--- a/modules/ppcp-applepay/resources/js/ApplepayManagerBlockEditor.js
+++ b/modules/ppcp-applepay/resources/js/ApplepayManagerBlockEditor.js
@@ -1,6 +1,8 @@
-import ApplepayButton from './ApplepayButton';
+/* global paypal */
-class ApplepayManagerBlockEditor {
+import ApplePayButton from './ApplepayButton';
+
+class ApplePayManagerBlockEditor {
constructor( buttonConfig, ppcpConfig ) {
this.buttonConfig = buttonConfig;
this.ppcpConfig = ppcpConfig;
@@ -17,7 +19,7 @@ class ApplepayManagerBlockEditor {
try {
this.applePayConfig = await paypal.Applepay().config();
- const button = new ApplepayButton(
+ const button = new ApplePayButton(
this.ppcpConfig.context,
null,
this.buttonConfig,
@@ -31,4 +33,4 @@ class ApplepayManagerBlockEditor {
}
}
-export default ApplepayManagerBlockEditor;
+export default ApplePayManagerBlockEditor;
diff --git a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js
index f763ac5d9..cc3a3aeb2 100644
--- a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js
+++ b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js
@@ -1,6 +1,5 @@
import ErrorHandler from '../../../../ppcp-button/resources/js/modules/ErrorHandler';
import CartActionHandler from '../../../../ppcp-button/resources/js/modules/ActionHandler/CartActionHandler';
-import { isPayPalSubscription } from '../../../../ppcp-blocks/resources/js/Helper/Subscription';
class BaseHandler {
constructor( buttonConfig, ppcpConfig ) {
@@ -76,13 +75,6 @@ class BaseHandler {
document.querySelector( '.woocommerce-notices-wrapper' )
);
}
-
- errorHandler() {
- return new ErrorHandler(
- this.ppcpConfig.labels.error.generic,
- document.querySelector( '.woocommerce-notices-wrapper' )
- );
- }
}
export default BaseHandler;
diff --git a/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js b/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js
index 8740705e9..5febfe0c3 100644
--- a/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js
+++ b/modules/ppcp-applepay/resources/js/Context/PreviewHandler.js
@@ -1,10 +1,6 @@
import BaseHandler from './BaseHandler';
class PreviewHandler extends BaseHandler {
- constructor( buttonConfig, ppcpConfig, externalHandler ) {
- super( buttonConfig, ppcpConfig, externalHandler );
- }
-
transactionInfo() {
// We need to return something as ApplePay button initialization expects valid data.
return {
@@ -19,7 +15,7 @@ class PreviewHandler extends BaseHandler {
throw new Error( 'Create order fail. This is just a preview.' );
}
- approveOrder( data, actions ) {
+ approveOrder() {
throw new Error( 'Approve order fail. This is just a preview.' );
}
diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js
index 080d7c8aa..81d8c0b7b 100644
--- a/modules/ppcp-applepay/resources/js/boot-admin.js
+++ b/modules/ppcp-applepay/resources/js/boot-admin.js
@@ -1,4 +1,4 @@
-import ApplepayButton from './ApplepayButton';
+import ApplePayButton from './ApplepayButton';
import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton';
import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager';
@@ -86,7 +86,7 @@ class ApplePayPreviewButton extends PreviewButton {
}
createButton( buttonConfig ) {
- const button = new ApplepayButton(
+ const button = new ApplePayButton(
'preview',
null,
buttonConfig,
diff --git a/modules/ppcp-applepay/resources/js/boot-block.js b/modules/ppcp-applepay/resources/js/boot-block.js
index 8445466eb..c447cb064 100644
--- a/modules/ppcp-applepay/resources/js/boot-block.js
+++ b/modules/ppcp-applepay/resources/js/boot-block.js
@@ -4,8 +4,8 @@ import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Help
import { cartHasSubscriptionProducts } from '../../../ppcp-blocks/resources/js/Helper/Subscription';
import { loadCustomScript } from '@paypal/paypal-js';
import CheckoutHandler from './Context/CheckoutHandler';
-import ApplepayManager from './ApplepayManager';
-import ApplepayManagerBlockEditor from './ApplepayManagerBlockEditor';
+import ApplePayManager from './ApplepayManager';
+import ApplePayManagerBlockEditor from './ApplepayManagerBlockEditor';
const ppcpData = wc.wcSettings.getSetting( 'ppcp-gateway_data' );
const ppcpConfig = ppcpData.scriptData;
@@ -24,8 +24,8 @@ const ApplePayComponent = ( props ) => {
const bootstrap = function () {
const ManagerClass = props.isEditing
- ? ApplepayManagerBlockEditor
- : ApplepayManager;
+ ? ApplePayManagerBlockEditor
+ : ApplePayManager;
const manager = new ManagerClass( buttonConfig, ppcpConfig );
manager.init();
};
diff --git a/modules/ppcp-applepay/resources/js/boot.js b/modules/ppcp-applepay/resources/js/boot.js
index aee735231..8eddafbcb 100644
--- a/modules/ppcp-applepay/resources/js/boot.js
+++ b/modules/ppcp-applepay/resources/js/boot.js
@@ -1,13 +1,13 @@
import { loadCustomScript } from '@paypal/paypal-js';
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
-import ApplepayManager from './ApplepayManager';
+import ApplePayManager from './ApplepayManager';
import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Helper/ButtonRefreshHelper';
( function ( { buttonConfig, ppcpConfig, jQuery } ) {
let manager;
const bootstrap = function () {
- manager = new ApplepayManager( buttonConfig, ppcpConfig );
+ manager = new ApplePayManager( buttonConfig, ppcpConfig );
manager.init();
};