mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-01 07:02:48 +08:00
Merge pull request #2704 from woocommerce/PCP-3783-fastlane-allow-merchants-to-disable-specific-card-types
Axo: Add support for card icons in the Block Checkout and add card type limiting for both block and classic checkouts (3783)
This commit is contained in:
commit
c7dfe3293b
19 changed files with 240 additions and 144 deletions
|
@ -17,10 +17,19 @@ $fast-transition-duration: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. AXO Block Radio Label
|
// 1. AXO Block Radio Label
|
||||||
#ppcp-axo-block-radio-label {
|
.wc-block-checkout__payment-method label[for="radio-control-wc-payment-method-options-ppcp-axo-gateway"] {
|
||||||
@include flex-space-between;
|
padding-right: .875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#radio-control-wc-payment-method-options-ppcp-axo-gateway__label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
|
|
||||||
|
.wc-block-components-payment-method-icons {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. AXO Block Card
|
// 2. AXO Block Card
|
||||||
|
@ -70,15 +79,16 @@ $fast-transition-duration: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__edit {
|
&__edit {
|
||||||
background-color: transparent;
|
flex-grow: 1;
|
||||||
|
margin-left: auto;
|
||||||
|
text-align: right;
|
||||||
border: 0;
|
border: 0;
|
||||||
color: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
display: block;
|
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
margin: 0 0 0 auto;
|
|
||||||
font-size: 0.875em;
|
font-size: 0.875em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
color: inherit;
|
||||||
|
background-color: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
import { createElement } from '@wordpress/element';
|
import { createElement } from '@wordpress/element';
|
||||||
|
import { useSelect } from '@wordpress/data';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { STORE_NAME } from '../../stores/axoStore';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a button to change the selected card in the checkout process.
|
* Renders a button to change the selected card in the checkout process.
|
||||||
*
|
*
|
||||||
* @param {Object} props
|
* @return {JSX.Element|null} The rendered button as an anchor tag, or null if conditions aren't met.
|
||||||
* @param {Function} props.onChangeButtonClick - Callback function to handle the click event.
|
|
||||||
* @return {JSX.Element} The rendered button as an anchor tag.
|
|
||||||
*/
|
*/
|
||||||
const CardChangeButton = ( { onChangeButtonClick } ) =>
|
const CardChangeButton = () => {
|
||||||
createElement(
|
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',
|
'a',
|
||||||
{
|
{
|
||||||
className:
|
className:
|
||||||
|
@ -19,10 +32,11 @@ const CardChangeButton = ( { onChangeButtonClick } ) =>
|
||||||
// Prevent default anchor behavior
|
// Prevent default anchor behavior
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
// Call the provided click handler
|
// Call the provided click handler
|
||||||
onChangeButtonClick();
|
cardChangeHandler();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
__( 'Choose a different card', 'woocommerce-paypal-payments' )
|
__( 'Choose a different card', 'woocommerce-paypal-payments' )
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default CardChangeButton;
|
export default CardChangeButton;
|
||||||
|
|
|
@ -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;
|
|
|
@ -1,4 +1,2 @@
|
||||||
export { default as Card } from './Card';
|
export { default as Card } from './Card';
|
||||||
export { default as CardChangeButton } from './CardChangeButton';
|
export { default as CardChangeButton } from './CardChangeButton';
|
||||||
export { default as CardChangeButtonManager } from './CardChangeButtonManager';
|
|
||||||
export { injectCardChangeButton, removeCardChangeButton } from './utils';
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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 (
|
||||||
|
<>
|
||||||
|
<span dangerouslySetInnerHTML={ { __html: config.title } } />
|
||||||
|
<PaymentMethodIcons icons={ axoConfig?.card_icons } />
|
||||||
|
<CardChangeButton />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TitleLabel;
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as TitleLabel } from './TitleLabel';
|
|
@ -1,7 +1,6 @@
|
||||||
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
||||||
import { populateWooFields } from '../helpers/fieldHelpers';
|
import { populateWooFields } from '../helpers/fieldHelpers';
|
||||||
import { injectShippingChangeButton } from '../components/Shipping';
|
import { injectShippingChangeButton } from '../components/Shipping';
|
||||||
import { injectCardChangeButton } from '../components/Card';
|
|
||||||
import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
|
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} setWooShippingAddress - Function to update WooCommerce shipping address.
|
||||||
* @param {Function} setWooBillingAddress - Function to update WooCommerce billing address.
|
* @param {Function} setWooBillingAddress - Function to update WooCommerce billing address.
|
||||||
* @param {Function} onChangeShippingAddressClick - Handler for shipping address change.
|
* @param {Function} onChangeShippingAddressClick - Handler for shipping address change.
|
||||||
* @param {Function} onChangeCardButtonClick - Handler for card change.
|
|
||||||
* @return {Function} The email lookup handler function.
|
* @return {Function} The email lookup handler function.
|
||||||
*/
|
*/
|
||||||
export const createEmailLookupHandler = (
|
export const createEmailLookupHandler = (
|
||||||
|
@ -28,8 +26,7 @@ export const createEmailLookupHandler = (
|
||||||
wooBillingAddress,
|
wooBillingAddress,
|
||||||
setWooShippingAddress,
|
setWooShippingAddress,
|
||||||
setWooBillingAddress,
|
setWooBillingAddress,
|
||||||
onChangeShippingAddressClick,
|
onChangeShippingAddressClick
|
||||||
onChangeCardButtonClick
|
|
||||||
) => {
|
) => {
|
||||||
return async ( email ) => {
|
return async ( email ) => {
|
||||||
try {
|
try {
|
||||||
|
@ -102,9 +99,8 @@ export const createEmailLookupHandler = (
|
||||||
setWooBillingAddress
|
setWooBillingAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
// Inject change buttons for shipping and card
|
// Inject the change button for shipping
|
||||||
injectShippingChangeButton( onChangeShippingAddressClick );
|
injectShippingChangeButton( onChangeShippingAddressClick );
|
||||||
injectCardChangeButton( onChangeCardButtonClick );
|
|
||||||
} else {
|
} else {
|
||||||
log( 'Authentication failed or did not succeed', 'warn' );
|
log( 'Authentication failed or did not succeed', 'warn' );
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { useDispatch } from '@wordpress/data';
|
||||||
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
||||||
import { STORE_NAME } from '../stores/axoStore';
|
import { STORE_NAME } from '../stores/axoStore';
|
||||||
import { removeShippingChangeButton } from '../components/Shipping';
|
import { removeShippingChangeButton } from '../components/Shipping';
|
||||||
import { removeCardChangeButton } from '../components/Card';
|
|
||||||
import { removeWatermark } from '../components/Watermark';
|
import { removeWatermark } from '../components/Watermark';
|
||||||
import {
|
import {
|
||||||
removeEmailFunctionality,
|
removeEmailFunctionality,
|
||||||
|
@ -50,7 +49,6 @@ const useAxoCleanup = () => {
|
||||||
|
|
||||||
// Remove AXO UI elements
|
// Remove AXO UI elements
|
||||||
removeShippingChangeButton();
|
removeShippingChangeButton();
|
||||||
removeCardChangeButton();
|
|
||||||
removeWatermark();
|
removeWatermark();
|
||||||
|
|
||||||
// Remove email functionality if it was set up
|
// Remove email functionality if it was set up
|
||||||
|
|
|
@ -35,6 +35,7 @@ const useAxoSetup = (
|
||||||
setIsAxoScriptLoaded,
|
setIsAxoScriptLoaded,
|
||||||
setShippingAddress,
|
setShippingAddress,
|
||||||
setCardDetails,
|
setCardDetails,
|
||||||
|
setCardChangeHandler,
|
||||||
} = useDispatch( STORE_NAME );
|
} = useDispatch( STORE_NAME );
|
||||||
|
|
||||||
// Check if PayPal script has loaded
|
// Check if PayPal script has loaded
|
||||||
|
@ -73,6 +74,7 @@ const useAxoSetup = (
|
||||||
if ( paypalLoaded && fastlaneSdk ) {
|
if ( paypalLoaded && fastlaneSdk ) {
|
||||||
setIsAxoScriptLoaded( true );
|
setIsAxoScriptLoaded( true );
|
||||||
setIsAxoActive( true );
|
setIsAxoActive( true );
|
||||||
|
setCardChangeHandler( onChangeCardButtonClick );
|
||||||
|
|
||||||
// Create and set up email lookup handler
|
// Create and set up email lookup handler
|
||||||
const emailLookupHandler = createEmailLookupHandler(
|
const emailLookupHandler = createEmailLookupHandler(
|
||||||
|
@ -84,8 +86,7 @@ const useAxoSetup = (
|
||||||
wooBillingAddress,
|
wooBillingAddress,
|
||||||
setWooShippingAddress,
|
setWooShippingAddress,
|
||||||
setWooBillingAddress,
|
setWooBillingAddress,
|
||||||
onChangeShippingAddressClick,
|
onChangeShippingAddressClick
|
||||||
onChangeCardButtonClick
|
|
||||||
);
|
);
|
||||||
setupEmailFunctionality( emailLookupHandler );
|
setupEmailFunctionality( emailLookupHandler );
|
||||||
}
|
}
|
||||||
|
|
36
modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js
Normal file
36
modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js
Normal file
|
@ -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;
|
|
@ -3,6 +3,7 @@ import { useSelect } from '@wordpress/data';
|
||||||
import Fastlane from '../../../../ppcp-axo/resources/js/Connection/Fastlane';
|
import Fastlane from '../../../../ppcp-axo/resources/js/Connection/Fastlane';
|
||||||
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
|
||||||
import { useDeleteEmptyKeys } from './useDeleteEmptyKeys';
|
import { useDeleteEmptyKeys } from './useDeleteEmptyKeys';
|
||||||
|
import useCardOptions from './useCardOptions';
|
||||||
import useAllowedLocations from './useAllowedLocations';
|
import useAllowedLocations from './useAllowedLocations';
|
||||||
import { STORE_NAME } from '../stores/axoStore';
|
import { STORE_NAME } from '../stores/axoStore';
|
||||||
|
|
||||||
|
@ -27,6 +28,8 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const cardOptions = useCardOptions( axoConfig );
|
||||||
|
|
||||||
const styleOptions = useMemo( () => {
|
const styleOptions = useMemo( () => {
|
||||||
return deleteEmptyKeys( configRef.current.axoConfig.style_options );
|
return deleteEmptyKeys( configRef.current.axoConfig.style_options );
|
||||||
}, [ deleteEmptyKeys ] );
|
}, [ deleteEmptyKeys ] );
|
||||||
|
@ -51,10 +54,13 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
|
||||||
window.localStorage.setItem( 'axoEnv', 'sandbox' );
|
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( {
|
await fastlane.connect( {
|
||||||
locale: configRef.current.ppcpConfig.locale,
|
locale: configRef.current.ppcpConfig.locale,
|
||||||
styles: styleOptions,
|
styles: styleOptions,
|
||||||
|
cardOptions: {
|
||||||
|
allowedBrands: cardOptions,
|
||||||
|
},
|
||||||
shippingAddressOptions: {
|
shippingAddressOptions: {
|
||||||
allowedLocations,
|
allowedLocations,
|
||||||
},
|
},
|
||||||
|
@ -77,6 +83,7 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
|
||||||
styleOptions,
|
styleOptions,
|
||||||
isPayPalLoaded,
|
isPayPalLoaded,
|
||||||
namespace,
|
namespace,
|
||||||
|
cardOptions,
|
||||||
allowedLocations,
|
allowedLocations,
|
||||||
] );
|
] );
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import usePayPalCommerceGateway from './hooks/usePayPalCommerceGateway';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { Payment } from './components/Payment/Payment';
|
import { Payment } from './components/Payment/Payment';
|
||||||
|
import { TitleLabel } from './components/TitleLabel';
|
||||||
|
|
||||||
const gatewayHandle = 'ppcp-axo-gateway';
|
const gatewayHandle = 'ppcp-axo-gateway';
|
||||||
const namespace = 'ppcpBlocksPaypalAxo';
|
const namespace = 'ppcpBlocksPaypalAxo';
|
||||||
|
@ -89,12 +90,7 @@ const Axo = ( props ) => {
|
||||||
|
|
||||||
registerPaymentMethod( {
|
registerPaymentMethod( {
|
||||||
name: initialConfig.id,
|
name: initialConfig.id,
|
||||||
label: (
|
label: <TitleLabel config={ initialConfig } />,
|
||||||
<div
|
|
||||||
id="ppcp-axo-block-radio-label"
|
|
||||||
dangerouslySetInnerHTML={ { __html: initialConfig.title } }
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
content: <Axo />,
|
content: <Axo />,
|
||||||
edit: createElement( initialConfig.title ),
|
edit: createElement( initialConfig.title ),
|
||||||
ariaLabel: initialConfig.title,
|
ariaLabel: initialConfig.title,
|
||||||
|
|
|
@ -12,6 +12,7 @@ const DEFAULT_STATE = {
|
||||||
shippingAddress: null,
|
shippingAddress: null,
|
||||||
cardDetails: null,
|
cardDetails: null,
|
||||||
phoneNumber: '',
|
phoneNumber: '',
|
||||||
|
cardChangeHandler: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Action creators for updating the store state
|
// Action creators for updating the store state
|
||||||
|
@ -52,6 +53,10 @@ const actions = {
|
||||||
type: 'SET_PHONE_NUMBER',
|
type: 'SET_PHONE_NUMBER',
|
||||||
payload: phoneNumber,
|
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 };
|
return { ...state, cardDetails: action.payload };
|
||||||
case 'SET_PHONE_NUMBER':
|
case 'SET_PHONE_NUMBER':
|
||||||
return { ...state, phoneNumber: action.payload };
|
return { ...state, phoneNumber: action.payload };
|
||||||
|
case 'SET_CARD_CHANGE_HANDLER':
|
||||||
|
return { ...state, cardChangeHandler: action.payload };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +104,7 @@ const selectors = {
|
||||||
getShippingAddress: ( state ) => state.shippingAddress,
|
getShippingAddress: ( state ) => state.shippingAddress,
|
||||||
getCardDetails: ( state ) => state.cardDetails,
|
getCardDetails: ( state ) => state.cardDetails,
|
||||||
getPhoneNumber: ( state ) => state.phoneNumber,
|
getPhoneNumber: ( state ) => state.phoneNumber,
|
||||||
|
getCardChangeHandler: ( state ) => state.cardChangeHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create and register the Redux store for the AXO block
|
// Create and register the Redux store for the AXO block
|
||||||
|
@ -163,3 +171,12 @@ export const setCardDetails = ( cardDetails ) => {
|
||||||
export const setPhoneNumber = ( phoneNumber ) => {
|
export const setPhoneNumber = ( phoneNumber ) => {
|
||||||
dispatch( STORE_NAME ).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 );
|
||||||
|
};
|
||||||
|
|
|
@ -38,6 +38,7 @@ return array(
|
||||||
$container->get( 'wcgateway.configuration.dcc' ),
|
$container->get( 'wcgateway.configuration.dcc' ),
|
||||||
$container->get( 'onboarding.environment' ),
|
$container->get( 'onboarding.environment' ),
|
||||||
$container->get( 'wcgateway.url' ),
|
$container->get( 'wcgateway.url' ),
|
||||||
|
$container->get( 'axo.supported-country-card-type-matrix' ),
|
||||||
$container->get( 'axo.shipping-wc-enabled-locations' )
|
$container->get( 'axo.shipping-wc-enabled-locations' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -79,6 +79,13 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
*/
|
*/
|
||||||
private $wcgateway_module_url;
|
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.
|
* The list of WooCommerce enabled shipping locations.
|
||||||
*
|
*
|
||||||
|
@ -98,6 +105,7 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
* @param DCCGatewayConfiguration $dcc_configuration The DCC gateway settings.
|
* @param DCCGatewayConfiguration $dcc_configuration The DCC gateway settings.
|
||||||
* @param Environment $environment The environment object.
|
* @param Environment $environment The environment object.
|
||||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
* @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.
|
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -109,18 +117,20 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
DCCGatewayConfiguration $dcc_configuration,
|
DCCGatewayConfiguration $dcc_configuration,
|
||||||
Environment $environment,
|
Environment $environment,
|
||||||
string $wcgateway_module_url,
|
string $wcgateway_module_url,
|
||||||
|
array $supported_country_card_type_matrix,
|
||||||
array $enabled_shipping_locations
|
array $enabled_shipping_locations
|
||||||
) {
|
) {
|
||||||
$this->name = AxoGateway::ID;
|
$this->name = AxoGateway::ID;
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
$this->version = $version;
|
$this->version = $version;
|
||||||
$this->gateway = $gateway;
|
$this->gateway = $gateway;
|
||||||
$this->smart_button = $smart_button;
|
$this->smart_button = $smart_button;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->dcc_configuration = $dcc_configuration;
|
$this->dcc_configuration = $dcc_configuration;
|
||||||
$this->environment = $environment;
|
$this->environment = $environment;
|
||||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||||
$this->enabled_shipping_locations = $enabled_shipping_locations;
|
$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.
|
: 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,
|
'enabled_shipping_locations' => $this->enabled_shipping_locations,
|
||||||
'style_options' => array(
|
'style_options' => array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
|
@ -253,6 +265,8 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
),
|
),
|
||||||
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
|
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
|
||||||
'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
'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(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,8 @@ class AxoManager {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.cardOptions = this.getCardOptions();
|
||||||
|
|
||||||
this.enabledShippingLocations =
|
this.enabledShippingLocations =
|
||||||
this.axoConfig.enabled_shipping_locations;
|
this.axoConfig.enabled_shipping_locations;
|
||||||
|
|
||||||
|
@ -664,6 +666,9 @@ class AxoManager {
|
||||||
await this.fastlane.connect( {
|
await this.fastlane.connect( {
|
||||||
locale: this.locale,
|
locale: this.locale,
|
||||||
styles: this.styles,
|
styles: this.styles,
|
||||||
|
cardOptions: {
|
||||||
|
allowedBrands: this.cardOptions,
|
||||||
|
},
|
||||||
shippingAddressOptions: {
|
shippingAddressOptions: {
|
||||||
allowedLocations: this.enabledShippingLocations,
|
allowedLocations: this.enabledShippingLocations,
|
||||||
},
|
},
|
||||||
|
@ -1251,6 +1256,31 @@ class AxoManager {
|
||||||
return this.axoConfig?.widgets?.email === 'use_widget';
|
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 ) => {
|
deleteKeysWithEmptyString = ( obj ) => {
|
||||||
for ( const key of Object.keys( obj ) ) {
|
for ( const key of Object.keys( obj ) ) {
|
||||||
if ( obj[ key ] === '' ) {
|
if ( obj[ key ] === '' ) {
|
||||||
|
|
|
@ -68,6 +68,7 @@ return array(
|
||||||
$container->get( 'api.shop.currency.getter' ),
|
$container->get( 'api.shop.currency.getter' ),
|
||||||
$container->get( 'woocommerce.logger.woocommerce' ),
|
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||||
$container->get( 'wcgateway.url' ),
|
$container->get( 'wcgateway.url' ),
|
||||||
|
$container->get( 'axo.supported-country-card-type-matrix' ),
|
||||||
$container->get( 'axo.shipping-wc-enabled-locations' )
|
$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 {
|
'axo.settings-conflict-notice' => static function ( ContainerInterface $container ) : string {
|
||||||
$settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' );
|
$settings_notice_generator = $container->get( 'axo.helpers.settings-notice-generator' );
|
||||||
assert( $settings_notice_generator instanceof SettingsNoticeGenerator );
|
assert( $settings_notice_generator instanceof SettingsNoticeGenerator );
|
||||||
|
|
|
@ -29,28 +29,28 @@ class AxoManager {
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $module_url;
|
private string $module_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The assets version.
|
* The assets version.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $version;
|
private string $version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
* @var Settings
|
* @var Settings
|
||||||
*/
|
*/
|
||||||
private $settings;
|
private Settings $settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The environment object.
|
* The environment object.
|
||||||
*
|
*
|
||||||
* @var Environment
|
* @var Environment
|
||||||
*/
|
*/
|
||||||
private $environment;
|
private Environment $environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Settings status helper.
|
* The Settings status helper.
|
||||||
|
@ -71,22 +71,27 @@ class AxoManager {
|
||||||
*
|
*
|
||||||
* @var LoggerInterface
|
* @var LoggerInterface
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session handler.
|
* Session handler.
|
||||||
*
|
*
|
||||||
* @var SessionHandler
|
* @var SessionHandler
|
||||||
*/
|
*/
|
||||||
private $session_handler;
|
private SessionHandler $session_handler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The WcGateway module URL.
|
* The WcGateway module URL.
|
||||||
*
|
*
|
||||||
* @var string
|
* @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.
|
* 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 CurrencyGetter $currency The getter of the 3-letter currency code of the shop.
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
* @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.
|
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -118,19 +124,21 @@ class AxoManager {
|
||||||
CurrencyGetter $currency,
|
CurrencyGetter $currency,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
string $wcgateway_module_url,
|
string $wcgateway_module_url,
|
||||||
|
array $supported_country_card_type_matrix,
|
||||||
array $enabled_shipping_locations
|
array $enabled_shipping_locations
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
$this->version = $version;
|
$this->version = $version;
|
||||||
$this->session_handler = $session_handler;
|
$this->session_handler = $session_handler;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->environment = $environment;
|
$this->environment = $environment;
|
||||||
$this->settings_status = $settings_status;
|
$this->settings_status = $settings_status;
|
||||||
$this->currency = $currency;
|
$this->currency = $currency;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||||
$this->enabled_shipping_locations = $enabled_shipping_locations;
|
$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' ),
|
'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,
|
'enabled_shipping_locations' => $this->enabled_shipping_locations,
|
||||||
'style_options' => array(
|
'style_options' => array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
|
@ -231,6 +241,7 @@ class AxoManager {
|
||||||
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
|
'logging_enabled' => $this->settings->has( 'logging_enabled' ) ? $this->settings->get( 'logging_enabled' ) : '',
|
||||||
'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
||||||
'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ),
|
'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ),
|
||||||
|
'merchant_country' => WC()->countries->get_base_country(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue