diff --git a/modules/ppcp-axo-block/resources/css/gateway.scss b/modules/ppcp-axo-block/resources/css/gateway.scss
index b1296ea1b..4611bfa35 100644
--- a/modules/ppcp-axo-block/resources/css/gateway.scss
+++ b/modules/ppcp-axo-block/resources/css/gateway.scss
@@ -17,10 +17,19 @@ $fast-transition-duration: 0.5s;
}
// 1. AXO Block Radio Label
-#ppcp-axo-block-radio-label {
- @include flex-space-between;
+.wc-block-checkout__payment-method label[for="radio-control-wc-payment-method-options-ppcp-axo-gateway"] {
+ padding-right: .875em;
+}
+
+#radio-control-wc-payment-method-options-ppcp-axo-gateway__label {
+ display: flex;
+ align-items: center;
width: 100%;
padding-right: 1em;
+
+ .wc-block-components-payment-method-icons {
+ margin: 0;
+ }
}
// 2. AXO Block Card
@@ -70,15 +79,16 @@ $fast-transition-duration: 0.5s;
}
&__edit {
- background-color: transparent;
+ flex-grow: 1;
+ margin-left: auto;
+ text-align: right;
border: 0;
- color: inherit;
- cursor: pointer;
- display: block;
font-family: inherit;
- margin: 0 0 0 auto;
font-size: 0.875em;
font-weight: normal;
+ color: inherit;
+ background-color: transparent;
+ cursor: pointer;
&:hover {
text-decoration: underline;
diff --git a/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButton.js b/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButton.js
index c2a4eaa65..d3b27b17a 100644
--- a/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButton.js
+++ b/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButton.js
@@ -1,15 +1,28 @@
import { createElement } from '@wordpress/element';
+import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
+import { STORE_NAME } from '../../stores/axoStore';
/**
* Renders a button to change the selected card in the checkout process.
*
- * @param {Object} props
- * @param {Function} props.onChangeButtonClick - Callback function to handle the click event.
- * @return {JSX.Element} The rendered button as an anchor tag.
+ * @return {JSX.Element|null} The rendered button as an anchor tag, or null if conditions aren't met.
*/
-const CardChangeButton = ( { onChangeButtonClick } ) =>
- createElement(
+const CardChangeButton = () => {
+ const { isGuest, cardDetails, cardChangeHandler } = useSelect(
+ ( select ) => ( {
+ isGuest: select( STORE_NAME ).getIsGuest(),
+ cardDetails: select( STORE_NAME ).getCardDetails(),
+ cardChangeHandler: select( STORE_NAME ).getCardChangeHandler(),
+ } ),
+ []
+ );
+
+ if ( isGuest || ! cardDetails || ! cardChangeHandler ) {
+ return null;
+ }
+
+ return createElement(
'a',
{
className:
@@ -19,10 +32,11 @@ const CardChangeButton = ( { onChangeButtonClick } ) =>
// Prevent default anchor behavior
event.preventDefault();
// Call the provided click handler
- onChangeButtonClick();
+ cardChangeHandler();
},
},
__( 'Choose a different card', 'woocommerce-paypal-payments' )
);
+};
export default CardChangeButton;
diff --git a/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButtonManager.js b/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButtonManager.js
deleted file mode 100644
index 2b6deba4f..000000000
--- a/modules/ppcp-axo-block/resources/js/components/Card/CardChangeButtonManager.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { createElement, createRoot, useEffect } from '@wordpress/element';
-import CardChangeButton from './CardChangeButton';
-
-/**
- * Manages the insertion and removal of the CardChangeButton in the DOM.
- *
- * @param {Object} props
- * @param {Function} props.onChangeButtonClick - Callback function for when the card change button is clicked.
- * @return {null} This component doesn't render any visible elements directly.
- */
-const CardChangeButtonManager = ( { onChangeButtonClick } ) => {
- useEffect( () => {
- const radioLabelElement = document.getElementById(
- 'ppcp-axo-block-radio-label'
- );
-
- if ( radioLabelElement ) {
- // Check if the change button doesn't already exist
- if (
- ! radioLabelElement.querySelector(
- '.wc-block-checkout-axo-block-card__edit'
- )
- ) {
- // Create a new container for the button
- const buttonContainer = document.createElement( 'div' );
- radioLabelElement.appendChild( buttonContainer );
-
- // Create a React root and render the CardChangeButton
- const root = createRoot( buttonContainer );
- root.render(
- createElement( CardChangeButton, { onChangeButtonClick } )
- );
- }
- }
-
- // Cleanup function to remove the button when the component unmounts
- return () => {
- const button = document.querySelector(
- '.wc-block-checkout-axo-block-card__edit'
- );
- if ( button && button.parentNode ) {
- button.parentNode.remove();
- }
- };
- }, [ onChangeButtonClick ] );
-
- // This component doesn't render anything directly
- return null;
-};
-
-export default CardChangeButtonManager;
diff --git a/modules/ppcp-axo-block/resources/js/components/Card/index.js b/modules/ppcp-axo-block/resources/js/components/Card/index.js
index c9250078e..7c44148bc 100644
--- a/modules/ppcp-axo-block/resources/js/components/Card/index.js
+++ b/modules/ppcp-axo-block/resources/js/components/Card/index.js
@@ -1,4 +1,2 @@
export { default as Card } from './Card';
export { default as CardChangeButton } from './CardChangeButton';
-export { default as CardChangeButtonManager } from './CardChangeButtonManager';
-export { injectCardChangeButton, removeCardChangeButton } from './utils';
diff --git a/modules/ppcp-axo-block/resources/js/components/Card/utils.js b/modules/ppcp-axo-block/resources/js/components/Card/utils.js
deleted file mode 100644
index 915511885..000000000
--- a/modules/ppcp-axo-block/resources/js/components/Card/utils.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createElement, createRoot } from '@wordpress/element';
-import CardChangeButtonManager from './CardChangeButtonManager';
-
-/**
- * Injects a card change button into the DOM.
- *
- * @param {Function} onChangeButtonClick - Callback function for when the card change button is clicked.
- */
-export const injectCardChangeButton = ( onChangeButtonClick ) => {
- // Create a container for the button
- const container = document.createElement( 'div' );
- document.body.appendChild( container );
-
- // Render the CardChangeButtonManager in the new container
- createRoot( container ).render(
- createElement( CardChangeButtonManager, { onChangeButtonClick } )
- );
-};
-
-/**
- * Removes the card change button from the DOM if it exists.
- */
-export const removeCardChangeButton = () => {
- const button = document.querySelector(
- '.wc-block-checkout-axo-block-card__edit'
- );
-
- // Remove the button's parent node if it exists
- if ( button && button.parentNode ) {
- button.parentNode.remove();
- }
-};
diff --git a/modules/ppcp-axo-block/resources/js/components/TitleLabel/TitleLabel.js b/modules/ppcp-axo-block/resources/js/components/TitleLabel/TitleLabel.js
new file mode 100644
index 000000000..6435e23de
--- /dev/null
+++ b/modules/ppcp-axo-block/resources/js/components/TitleLabel/TitleLabel.js
@@ -0,0 +1,24 @@
+import CardChangeButton from './../Card/CardChangeButton';
+
+/**
+ * TitleLabel component for displaying a payment method title with icons and a change card button.
+ *
+ * @param {Object} props - Component props
+ * @param {Object} props.components - Object containing WooCommerce components
+ * @param {Object} props.config - Configuration object for the payment method
+ * @return {JSX.Element} WordPress element
+ */
+const TitleLabel = ( { components, config } ) => {
+ const axoConfig = window.wc_ppcp_axo;
+ const { PaymentMethodIcons } = components;
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+export default TitleLabel;
diff --git a/modules/ppcp-axo-block/resources/js/components/TitleLabel/index.js b/modules/ppcp-axo-block/resources/js/components/TitleLabel/index.js
new file mode 100644
index 000000000..9ca79db8f
--- /dev/null
+++ b/modules/ppcp-axo-block/resources/js/components/TitleLabel/index.js
@@ -0,0 +1 @@
+export { default as TitleLabel } from './TitleLabel';
diff --git a/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js b/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js
index 563f9510d..8cc887668 100644
--- a/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js
+++ b/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js
@@ -1,7 +1,6 @@
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { populateWooFields } from '../helpers/fieldHelpers';
import { injectShippingChangeButton } from '../components/Shipping';
-import { injectCardChangeButton } from '../components/Card';
import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
/**
@@ -16,7 +15,6 @@ import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
* @param {Function} setWooShippingAddress - Function to update WooCommerce shipping address.
* @param {Function} setWooBillingAddress - Function to update WooCommerce billing address.
* @param {Function} onChangeShippingAddressClick - Handler for shipping address change.
- * @param {Function} onChangeCardButtonClick - Handler for card change.
* @return {Function} The email lookup handler function.
*/
export const createEmailLookupHandler = (
@@ -28,8 +26,7 @@ export const createEmailLookupHandler = (
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
- onChangeShippingAddressClick,
- onChangeCardButtonClick
+ onChangeShippingAddressClick
) => {
return async ( email ) => {
try {
@@ -102,9 +99,8 @@ export const createEmailLookupHandler = (
setWooBillingAddress
);
- // Inject change buttons for shipping and card
+ // Inject the change button for shipping
injectShippingChangeButton( onChangeShippingAddressClick );
- injectCardChangeButton( onChangeCardButtonClick );
} else {
log( 'Authentication failed or did not succeed', 'warn' );
}
diff --git a/modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js b/modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
index 1da3cca85..07247f2e3 100644
--- a/modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
+++ b/modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
@@ -3,7 +3,6 @@ import { useDispatch } from '@wordpress/data';
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { STORE_NAME } from '../stores/axoStore';
import { removeShippingChangeButton } from '../components/Shipping';
-import { removeCardChangeButton } from '../components/Card';
import { removeWatermark } from '../components/Watermark';
import {
removeEmailFunctionality,
@@ -50,7 +49,6 @@ const useAxoCleanup = () => {
// Remove AXO UI elements
removeShippingChangeButton();
- removeCardChangeButton();
removeWatermark();
// Remove email functionality if it was set up
diff --git a/modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js b/modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
index af1aaca38..629ce05d4 100644
--- a/modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
+++ b/modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
@@ -35,6 +35,7 @@ const useAxoSetup = (
setIsAxoScriptLoaded,
setShippingAddress,
setCardDetails,
+ setCardChangeHandler,
} = useDispatch( STORE_NAME );
// Check if PayPal script has loaded
@@ -73,6 +74,7 @@ const useAxoSetup = (
if ( paypalLoaded && fastlaneSdk ) {
setIsAxoScriptLoaded( true );
setIsAxoActive( true );
+ setCardChangeHandler( onChangeCardButtonClick );
// Create and set up email lookup handler
const emailLookupHandler = createEmailLookupHandler(
@@ -84,8 +86,7 @@ const useAxoSetup = (
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
- onChangeShippingAddressClick,
- onChangeCardButtonClick
+ onChangeShippingAddressClick
);
setupEmailFunctionality( emailLookupHandler );
}
diff --git a/modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js b/modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js
new file mode 100644
index 000000000..94c727784
--- /dev/null
+++ b/modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js
@@ -0,0 +1,36 @@
+import { useMemo } from '@wordpress/element';
+
+const DEFAULT_ALLOWED_CARDS = [ 'VISA', 'MASTERCARD', 'AMEX', 'DISCOVER' ];
+
+/**
+ * Custom hook to determine the allowed card options based on configuration.
+ *
+ * @param {Object} axoConfig - The AXO configuration object.
+ * @return {Array} The final list of allowed card options.
+ */
+const useCardOptions = ( axoConfig ) => {
+ const merchantCountry = axoConfig.merchant_country || 'US';
+
+ return useMemo( () => {
+ const allowedCards = new Set(
+ axoConfig.allowed_cards?.[ merchantCountry ] ||
+ DEFAULT_ALLOWED_CARDS
+ );
+
+ // Create a Set of disabled cards, converting each to uppercase
+ const disabledCards = new Set(
+ ( axoConfig.disable_cards || [] ).map( ( card ) =>
+ card.toUpperCase()
+ )
+ );
+
+ // Filter out disabled cards from the allowed cards
+ const finalCardOptions = [ ...allowedCards ].filter(
+ ( card ) => ! disabledCards.has( card )
+ );
+
+ return finalCardOptions;
+ }, [ axoConfig.allowed_cards, axoConfig.disable_cards, merchantCountry ] );
+};
+
+export default useCardOptions;
diff --git a/modules/ppcp-axo-block/resources/js/hooks/useFastlaneSdk.js b/modules/ppcp-axo-block/resources/js/hooks/useFastlaneSdk.js
index ae93a67af..47a917644 100644
--- a/modules/ppcp-axo-block/resources/js/hooks/useFastlaneSdk.js
+++ b/modules/ppcp-axo-block/resources/js/hooks/useFastlaneSdk.js
@@ -3,6 +3,7 @@ import { useSelect } from '@wordpress/data';
import Fastlane from '../../../../ppcp-axo/resources/js/Connection/Fastlane';
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { useDeleteEmptyKeys } from './useDeleteEmptyKeys';
+import useCardOptions from './useCardOptions';
import useAllowedLocations from './useAllowedLocations';
import { STORE_NAME } from '../stores/axoStore';
@@ -27,6 +28,8 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
[]
);
+ const cardOptions = useCardOptions( axoConfig );
+
const styleOptions = useMemo( () => {
return deleteEmptyKeys( configRef.current.axoConfig.style_options );
}, [ deleteEmptyKeys ] );
@@ -51,10 +54,13 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
window.localStorage.setItem( 'axoEnv', 'sandbox' );
}
- // Connect to Fastlane with locale and style options
+ // Connect to Fastlane with locale, style options, and allowed card brands
await fastlane.connect( {
locale: configRef.current.ppcpConfig.locale,
styles: styleOptions,
+ cardOptions: {
+ allowedBrands: cardOptions,
+ },
shippingAddressOptions: {
allowedLocations,
},
@@ -77,6 +83,7 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
styleOptions,
isPayPalLoaded,
namespace,
+ cardOptions,
allowedLocations,
] );
diff --git a/modules/ppcp-axo-block/resources/js/index.js b/modules/ppcp-axo-block/resources/js/index.js
index a45473e50..f58279af5 100644
--- a/modules/ppcp-axo-block/resources/js/index.js
+++ b/modules/ppcp-axo-block/resources/js/index.js
@@ -13,6 +13,7 @@ import usePayPalCommerceGateway from './hooks/usePayPalCommerceGateway';
// Components
import { Payment } from './components/Payment/Payment';
+import { TitleLabel } from './components/TitleLabel';
const gatewayHandle = 'ppcp-axo-gateway';
const namespace = 'ppcpBlocksPaypalAxo';
@@ -89,12 +90,7 @@ const Axo = ( props ) => {
registerPaymentMethod( {
name: initialConfig.id,
- label: (
-
- ),
+ label: ,
content: ,
edit: createElement( initialConfig.title ),
ariaLabel: initialConfig.title,
diff --git a/modules/ppcp-axo-block/resources/js/stores/axoStore.js b/modules/ppcp-axo-block/resources/js/stores/axoStore.js
index f779f983c..c7afb91ef 100644
--- a/modules/ppcp-axo-block/resources/js/stores/axoStore.js
+++ b/modules/ppcp-axo-block/resources/js/stores/axoStore.js
@@ -12,6 +12,7 @@ const DEFAULT_STATE = {
shippingAddress: null,
cardDetails: null,
phoneNumber: '',
+ cardChangeHandler: null,
};
// Action creators for updating the store state
@@ -52,6 +53,10 @@ const actions = {
type: 'SET_PHONE_NUMBER',
payload: phoneNumber,
} ),
+ setCardChangeHandler: ( cardChangeHandler ) => ( {
+ type: 'SET_CARD_CHANGE_HANDLER',
+ payload: cardChangeHandler,
+ } ),
};
/**
@@ -81,6 +86,8 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
return { ...state, cardDetails: action.payload };
case 'SET_PHONE_NUMBER':
return { ...state, phoneNumber: action.payload };
+ case 'SET_CARD_CHANGE_HANDLER':
+ return { ...state, cardChangeHandler: action.payload };
default:
return state;
}
@@ -97,6 +104,7 @@ const selectors = {
getShippingAddress: ( state ) => state.shippingAddress,
getCardDetails: ( state ) => state.cardDetails,
getPhoneNumber: ( state ) => state.phoneNumber,
+ getCardChangeHandler: ( state ) => state.cardChangeHandler,
};
// Create and register the Redux store for the AXO block
@@ -163,3 +171,12 @@ export const setCardDetails = ( cardDetails ) => {
export const setPhoneNumber = ( phoneNumber ) => {
dispatch( STORE_NAME ).setPhoneNumber( phoneNumber );
};
+
+/**
+ * Action dispatcher to update the card change handler in the store.
+ *
+ * @param {Function} cardChangeHandler - The card change handler function.
+ */
+export const setCardChangeHandler = ( cardChangeHandler ) => {
+ dispatch( STORE_NAME ).setCardChangeHandler( cardChangeHandler );
+};
diff --git a/modules/ppcp-axo-block/services.php b/modules/ppcp-axo-block/services.php
index 35a253881..61a3c77a7 100644
--- a/modules/ppcp-axo-block/services.php
+++ b/modules/ppcp-axo-block/services.php
@@ -38,6 +38,7 @@ return array(
$container->get( 'wcgateway.configuration.dcc' ),
$container->get( 'onboarding.environment' ),
$container->get( 'wcgateway.url' ),
+ $container->get( 'axo.supported-country-card-type-matrix' ),
$container->get( 'axo.shipping-wc-enabled-locations' )
);
},
diff --git a/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php b/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php
index e7d43608d..373c61023 100644
--- a/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php
+++ b/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php
@@ -79,6 +79,13 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
*/
private $wcgateway_module_url;
+ /**
+ * The supported country card type matrix.
+ *
+ * @var array
+ */
+ private $supported_country_card_type_matrix;
+
/**
* The list of WooCommerce enabled shipping locations.
*
@@ -98,6 +105,7 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
* @param DCCGatewayConfiguration $dcc_configuration The DCC gateway settings.
* @param Environment $environment The environment object.
* @param string $wcgateway_module_url The WcGateway module URL.
+ * @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
*/
public function __construct(
@@ -109,18 +117,20 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
DCCGatewayConfiguration $dcc_configuration,
Environment $environment,
string $wcgateway_module_url,
+ array $supported_country_card_type_matrix,
array $enabled_shipping_locations
) {
- $this->name = AxoGateway::ID;
- $this->module_url = $module_url;
- $this->version = $version;
- $this->gateway = $gateway;
- $this->smart_button = $smart_button;
- $this->settings = $settings;
- $this->dcc_configuration = $dcc_configuration;
- $this->environment = $environment;
- $this->wcgateway_module_url = $wcgateway_module_url;
- $this->enabled_shipping_locations = $enabled_shipping_locations;
+ $this->name = AxoGateway::ID;
+ $this->module_url = $module_url;
+ $this->version = $version;
+ $this->gateway = $gateway;
+ $this->smart_button = $smart_button;
+ $this->settings = $settings;
+ $this->dcc_configuration = $dcc_configuration;
+ $this->environment = $environment;
+ $this->wcgateway_module_url = $wcgateway_module_url;
+ $this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
+ $this->enabled_shipping_locations = $enabled_shipping_locations;
}
/**
@@ -216,6 +226,8 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
: null, // Set to null if WC()->cart is null or get_total doesn't exist.
),
),
+ 'allowed_cards' => $this->supported_country_card_type_matrix,
+ 'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
'enabled_shipping_locations' => $this->enabled_shipping_locations,
'style_options' => array(
'root' => array(
@@ -253,6 +265,8 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
),
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
+ 'card_icons' => $this->settings->has( 'card_icons' ) ? (array) $this->settings->get( 'card_icons' ) : array(),
+ 'merchant_country' => WC()->countries->get_base_country(),
);
}
}
diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js
index de9fcff5c..51dd34147 100644
--- a/modules/ppcp-axo/resources/js/AxoManager.js
+++ b/modules/ppcp-axo/resources/js/AxoManager.js
@@ -85,6 +85,8 @@ class AxoManager {
},
};
+ this.cardOptions = this.getCardOptions();
+
this.enabledShippingLocations =
this.axoConfig.enabled_shipping_locations;
@@ -664,6 +666,9 @@ class AxoManager {
await this.fastlane.connect( {
locale: this.locale,
styles: this.styles,
+ cardOptions: {
+ allowedBrands: this.cardOptions,
+ },
shippingAddressOptions: {
allowedLocations: this.enabledShippingLocations,
},
@@ -1251,6 +1256,31 @@ class AxoManager {
return this.axoConfig?.widgets?.email === 'use_widget';
}
+ getCardOptions() {
+ const DEFAULT_ALLOWED_CARDS = [
+ 'VISA',
+ 'MASTERCARD',
+ 'AMEX',
+ 'DISCOVER',
+ ];
+ const merchantCountry = this.axoConfig.merchant_country || 'US';
+
+ const allowedCards = new Set(
+ this.axoConfig.allowed_cards?.[ merchantCountry ] ||
+ DEFAULT_ALLOWED_CARDS
+ );
+
+ const disabledCards = new Set(
+ ( this.axoConfig.disable_cards || [] ).map( ( card ) =>
+ card.toUpperCase()
+ )
+ );
+
+ return [ ...allowedCards ].filter(
+ ( card ) => ! disabledCards.has( card )
+ );
+ }
+
deleteKeysWithEmptyString = ( obj ) => {
for ( const key of Object.keys( obj ) ) {
if ( obj[ key ] === '' ) {
diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php
index 4e7748032..e93df1721 100644
--- a/modules/ppcp-axo/services.php
+++ b/modules/ppcp-axo/services.php
@@ -68,6 +68,7 @@ return array(
$container->get( 'api.shop.currency.getter' ),
$container->get( 'woocommerce.logger.woocommerce' ),
$container->get( 'wcgateway.url' ),
+ $container->get( 'axo.supported-country-card-type-matrix' ),
$container->get( 'axo.shipping-wc-enabled-locations' )
);
},
@@ -111,7 +112,31 @@ return array(
)
);
},
-
+ /**
+ * The matrix which countries and card type combinations can be used for AXO.
+ */
+ 'axo.supported-country-card-type-matrix' => static function ( ContainerInterface $container ) : array {
+ /**
+ * Returns which countries and card type combinations can be used for AXO.
+ */
+ return apply_filters(
+ 'woocommerce_paypal_payments_axo_supported_country_card_type_matrix',
+ array(
+ 'US' => array(
+ 'VISA',
+ 'MASTERCARD',
+ 'AMEX',
+ 'DISCOVER',
+ ),
+ 'CA' => array(
+ 'VISA',
+ 'MASTERCARD',
+ 'AMEX',
+ 'DISCOVER',
+ ),
+ )
+ );
+ },
'axo.settings-conflict-notice' => static function ( ContainerInterface $container ) : string {
$settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' );
assert( $settings_notice_generator instanceof SettingsNoticeGenerator );
diff --git a/modules/ppcp-axo/src/Assets/AxoManager.php b/modules/ppcp-axo/src/Assets/AxoManager.php
index f0ad8b012..d2d4351a7 100644
--- a/modules/ppcp-axo/src/Assets/AxoManager.php
+++ b/modules/ppcp-axo/src/Assets/AxoManager.php
@@ -29,28 +29,28 @@ class AxoManager {
*
* @var string
*/
- private $module_url;
+ private string $module_url;
/**
* The assets version.
*
* @var string
*/
- private $version;
+ private string $version;
/**
* The settings.
*
* @var Settings
*/
- private $settings;
+ private Settings $settings;
/**
* The environment object.
*
* @var Environment
*/
- private $environment;
+ private Environment $environment;
/**
* The Settings status helper.
@@ -71,22 +71,27 @@ class AxoManager {
*
* @var LoggerInterface
*/
- private $logger;
+ private LoggerInterface $logger;
/**
* Session handler.
*
* @var SessionHandler
*/
- private $session_handler;
+ private SessionHandler $session_handler;
/**
* The WcGateway module URL.
*
* @var string
*/
- private $wcgateway_module_url;
-
+ private string $wcgateway_module_url;
+ /**
+ * The supported country card type matrix.
+ *
+ * @var array
+ */
+ private array $supported_country_card_type_matrix;
/**
* The list of WooCommerce enabled shipping locations.
*
@@ -106,6 +111,7 @@ class AxoManager {
* @param CurrencyGetter $currency The getter of the 3-letter currency code of the shop.
* @param LoggerInterface $logger The logger.
* @param string $wcgateway_module_url The WcGateway module URL.
+ * @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
*/
public function __construct(
@@ -118,19 +124,21 @@ class AxoManager {
CurrencyGetter $currency,
LoggerInterface $logger,
string $wcgateway_module_url,
+ array $supported_country_card_type_matrix,
array $enabled_shipping_locations
) {
- $this->module_url = $module_url;
- $this->version = $version;
- $this->session_handler = $session_handler;
- $this->settings = $settings;
- $this->environment = $environment;
- $this->settings_status = $settings_status;
- $this->currency = $currency;
- $this->logger = $logger;
- $this->wcgateway_module_url = $wcgateway_module_url;
- $this->enabled_shipping_locations = $enabled_shipping_locations;
+ $this->module_url = $module_url;
+ $this->version = $version;
+ $this->session_handler = $session_handler;
+ $this->settings = $settings;
+ $this->environment = $environment;
+ $this->settings_status = $settings_status;
+ $this->currency = $currency;
+ $this->logger = $logger;
+ $this->wcgateway_module_url = $wcgateway_module_url;
+ $this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
+ $this->enabled_shipping_locations = $enabled_shipping_locations;
}
/**
@@ -193,6 +201,8 @@ class AxoManager {
'value' => WC()->cart->get_total( 'numeric' ),
),
),
+ 'allowed_cards' => $this->supported_country_card_type_matrix,
+ 'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
'enabled_shipping_locations' => $this->enabled_shipping_locations,
'style_options' => array(
'root' => array(
@@ -231,6 +241,7 @@ class AxoManager {
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ),
+ 'merchant_country' => WC()->countries->get_base_country(),
);
}
diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php
index 512f61cb2..2caed32d7 100644
--- a/modules/ppcp-axo/src/AxoModule.php
+++ b/modules/ppcp-axo/src/AxoModule.php
@@ -377,11 +377,15 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule {
$dcc_configuration = $c->get( 'wcgateway.configuration.dcc' );
assert( $dcc_configuration instanceof DCCGatewayConfiguration );
+ $subscription_helper = $c->get( 'wc-subscriptions.helper' );
+ assert( $subscription_helper instanceof SubscriptionHelper );
+
return ! is_user_logged_in()
&& CartCheckoutDetector::has_classic_checkout()
&& $dcc_configuration->use_fastlane()
&& ! $this->is_excluded_endpoint()
- && is_checkout();
+ && is_checkout()
+ && ! $subscription_helper->cart_contains_subscription();
}
/**
diff --git a/modules/ppcp-blocks/resources/js/Components/card-fields.js b/modules/ppcp-blocks/resources/js/Components/card-fields.js
index 05d41b315..f47b18f35 100644
--- a/modules/ppcp-blocks/resources/js/Components/card-fields.js
+++ b/modules/ppcp-blocks/resources/js/Components/card-fields.js
@@ -3,7 +3,10 @@ import { useEffect, useState } from '@wordpress/element';
import {
PayPalScriptProvider,
PayPalCardFieldsProvider,
- PayPalCardFieldsForm,
+ PayPalNameField,
+ PayPalNumberField,
+ PayPalExpiryField,
+ PayPalCVVField,
} from '@paypal/react-paypal-js';
import { CheckoutHandler } from './checkout-handler';
@@ -14,6 +17,7 @@ import {
onApproveSavePayment,
} from '../card-fields-config';
import { cartHasSubscriptionProducts } from '../Helper/Subscription';
+import { __ } from '@wordpress/i18n';
export function CardFields( {
config,
@@ -92,7 +96,16 @@ export function CardFields( {
console.error( err );
} }
>
-
+
+
+
{
- const {PaymentMethodIcons} = components;
- return <>
-
-
- >
-}
+const Label = ( { components } ) => {
+ const { PaymentMethodIcons } = components;
+ return (
+ <>
+
+
+ >
+ );
+};
-registerPaymentMethod({
- name: config.id,
- label: