mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Move card details and shipping address to the Redux store
This commit is contained in:
parent
75960fc4a4
commit
5a31fdd183
6 changed files with 122 additions and 72 deletions
|
@ -6,7 +6,7 @@ import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
|
|||
export const createEmailLookupHandler = (
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
setCardDetails,
|
||||
snapshotFields,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
|
@ -68,7 +68,7 @@ export const createEmailLookupHandler = (
|
|||
setShippingAddress( profileData.shippingAddress );
|
||||
}
|
||||
if ( profileData && profileData.card ) {
|
||||
setCard( profileData.card );
|
||||
setCardDetails( profileData.card );
|
||||
}
|
||||
|
||||
console.log( 'Profile Data:', profileData );
|
||||
|
|
|
@ -15,11 +15,14 @@ const useAxoSetup = (
|
|||
ppcpConfig,
|
||||
fastlaneSdk,
|
||||
paymentComponent,
|
||||
onChangeCardButtonClick,
|
||||
setShippingAddress,
|
||||
setCard
|
||||
onChangeCardButtonClick
|
||||
) => {
|
||||
const { setIsAxoActive, setIsAxoScriptLoaded } = useDispatch( STORE_NAME );
|
||||
const {
|
||||
setIsAxoActive,
|
||||
setIsAxoScriptLoaded,
|
||||
setShippingAddress,
|
||||
setCardDetails,
|
||||
} = useDispatch( STORE_NAME );
|
||||
const paypalLoaded = usePayPalScript( ppcpConfig );
|
||||
|
||||
const onChangeShippingAddressClick = useShippingAddressChange(
|
||||
|
@ -53,7 +56,7 @@ const useAxoSetup = (
|
|||
const emailLookupHandler = createEmailLookupHandler(
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
setCardDetails,
|
||||
snapshotFields,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
|
@ -76,7 +79,7 @@ const useAxoSetup = (
|
|||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
setCardDetails,
|
||||
paymentComponent,
|
||||
] );
|
||||
|
||||
|
|
|
@ -1,53 +1,73 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { useAddressEditing } from './useAddressEditing';
|
||||
import useCustomerData from './useCustomerData';
|
||||
import { STORE_NAME } from '../stores/axoStore';
|
||||
|
||||
export const useCardChange = ( fastlaneSdk, setCard ) => {
|
||||
export const useCardChange = ( fastlaneSdk ) => {
|
||||
const { setBillingAddressEditing } = useAddressEditing();
|
||||
const { setBillingAddress: setWooBillingAddress } = useCustomerData();
|
||||
const { setCardDetails, setShippingAddress } = useDispatch( STORE_NAME );
|
||||
|
||||
return useCallback( async () => {
|
||||
if ( fastlaneSdk ) {
|
||||
const { selectionChanged, selectedCard } =
|
||||
await fastlaneSdk.profile.showCardSelector();
|
||||
if ( selectionChanged ) {
|
||||
setCard( selectedCard );
|
||||
console.log( 'Selected card changed:', selectedCard );
|
||||
console.log( 'Setting new billing details:', selectedCard );
|
||||
|
||||
if ( selectionChanged && selectedCard?.paymentSource?.card ) {
|
||||
// Use the fallback logic for cardholder's name.
|
||||
const { name, billingAddress } =
|
||||
selectedCard.paymentSource.card;
|
||||
|
||||
// Split the full name into first and last name
|
||||
const nameParts = name.split( ' ' );
|
||||
const firstName = nameParts[ 0 ];
|
||||
const lastName = nameParts.slice( 1 ).join( ' ' );
|
||||
// If name is missing, use billing details as a fallback for the name.
|
||||
let firstName = '';
|
||||
let lastName = '';
|
||||
|
||||
if ( name ) {
|
||||
const nameParts = name.split( ' ' );
|
||||
firstName = nameParts[ 0 ];
|
||||
lastName = nameParts.slice( 1 ).join( ' ' );
|
||||
}
|
||||
|
||||
const newBillingAddress = {
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
address_1: billingAddress.addressLine1,
|
||||
address_2: billingAddress.addressLine2 || '',
|
||||
city: billingAddress.adminArea2,
|
||||
state: billingAddress.adminArea1,
|
||||
postcode: billingAddress.postalCode,
|
||||
country: billingAddress.countryCode,
|
||||
address_1: billingAddress?.addressLine1 || '',
|
||||
address_2: billingAddress?.addressLine2 || '',
|
||||
city: billingAddress?.adminArea2 || '',
|
||||
state: billingAddress?.adminArea1 || '',
|
||||
postcode: billingAddress?.postalCode || '',
|
||||
country: billingAddress?.countryCode || '',
|
||||
};
|
||||
|
||||
await new Promise( ( resolve ) => {
|
||||
setWooBillingAddress( newBillingAddress );
|
||||
resolve();
|
||||
} );
|
||||
|
||||
await new Promise( ( resolve ) => {
|
||||
setBillingAddressEditing( false );
|
||||
resolve();
|
||||
} );
|
||||
// Batch state updates.
|
||||
await Promise.all( [
|
||||
new Promise( ( resolve ) => {
|
||||
setCardDetails( selectedCard );
|
||||
resolve();
|
||||
} ),
|
||||
new Promise( ( resolve ) => {
|
||||
setWooBillingAddress( newBillingAddress );
|
||||
resolve();
|
||||
} ),
|
||||
new Promise( ( resolve ) => {
|
||||
setShippingAddress( newBillingAddress );
|
||||
resolve();
|
||||
} ),
|
||||
new Promise( ( resolve ) => {
|
||||
setBillingAddressEditing( false );
|
||||
resolve();
|
||||
} ),
|
||||
] );
|
||||
} else {
|
||||
console.error( 'Selected card or billing address is missing.' );
|
||||
}
|
||||
}
|
||||
}, [
|
||||
fastlaneSdk,
|
||||
setCard,
|
||||
setCardDetails,
|
||||
setWooBillingAddress,
|
||||
setShippingAddress,
|
||||
setBillingAddressEditing,
|
||||
] );
|
||||
};
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { STORE_NAME } from '../stores/axoStore';
|
||||
|
||||
const useHandlePaymentSetup = (
|
||||
emitResponse,
|
||||
card,
|
||||
paymentComponent,
|
||||
tokenizedCustomerData
|
||||
) => {
|
||||
const { cardDetails } = useSelect(
|
||||
( select ) => ( {
|
||||
shippingAddress: select( STORE_NAME ).getShippingAddress(),
|
||||
cardDetails: select( STORE_NAME ).getCardDetails(),
|
||||
} ),
|
||||
[]
|
||||
);
|
||||
|
||||
return useCallback( async () => {
|
||||
const isRyanFlow = !! card?.id;
|
||||
let cardToken = card?.id;
|
||||
const isRyanFlow = !! cardDetails?.id;
|
||||
let cardToken = cardDetails?.id;
|
||||
|
||||
if ( ! cardToken && paymentComponent ) {
|
||||
cardToken = await paymentComponent
|
||||
|
@ -38,7 +47,13 @@ const useHandlePaymentSetup = (
|
|||
},
|
||||
},
|
||||
};
|
||||
}, [ card, paymentComponent, tokenizedCustomerData ] );
|
||||
}, [
|
||||
cardDetails?.id,
|
||||
emitResponse.responseTypes.ERROR,
|
||||
emitResponse.responseTypes.SUCCESS,
|
||||
paymentComponent,
|
||||
tokenizedCustomerData,
|
||||
] );
|
||||
};
|
||||
|
||||
export default useHandlePaymentSetup;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { useState } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||
|
||||
// Hooks
|
||||
|
@ -13,6 +14,9 @@ import useHandlePaymentSetup from './hooks/useHandlePaymentSetup';
|
|||
import { Payment } from './components/Payment/Payment';
|
||||
import usePaymentSetupEffect from './hooks/usePaymentSetupEffect';
|
||||
|
||||
// Store
|
||||
import { STORE_NAME } from './stores/axoStore';
|
||||
|
||||
const gatewayHandle = 'ppcp-axo-gateway';
|
||||
const ppcpConfig = wc.wcSettings.getSetting( `${ gatewayHandle }_data` );
|
||||
|
||||
|
@ -25,16 +29,20 @@ const axoConfig = window.wc_ppcp_axo;
|
|||
const Axo = ( props ) => {
|
||||
const { eventRegistration, emitResponse } = props;
|
||||
const { onPaymentSetup } = eventRegistration;
|
||||
const [ shippingAddress, setShippingAddress ] = useState( null );
|
||||
const [ card, setCard ] = useState( null );
|
||||
const [ paymentComponent, setPaymentComponent ] = useState( null );
|
||||
|
||||
const { cardDetails } = useSelect(
|
||||
( select ) => ( {
|
||||
cardDetails: select( STORE_NAME ).getCardDetails(),
|
||||
} ),
|
||||
[]
|
||||
);
|
||||
|
||||
const fastlaneSdk = useFastlaneSdk( axoConfig, ppcpConfig );
|
||||
const tokenizedCustomerData = useTokenizeCustomerData();
|
||||
const onChangeCardButtonClick = useCardChange( fastlaneSdk, setCard );
|
||||
const onChangeCardButtonClick = useCardChange( fastlaneSdk );
|
||||
const handlePaymentSetup = useHandlePaymentSetup(
|
||||
emitResponse,
|
||||
card,
|
||||
paymentComponent,
|
||||
tokenizedCustomerData
|
||||
);
|
||||
|
@ -43,9 +51,7 @@ const Axo = ( props ) => {
|
|||
ppcpConfig,
|
||||
fastlaneSdk,
|
||||
paymentComponent,
|
||||
onChangeCardButtonClick,
|
||||
setShippingAddress,
|
||||
setCard
|
||||
onChangeCardButtonClick
|
||||
);
|
||||
|
||||
const { handlePaymentLoad } = usePaymentSetupEffect(
|
||||
|
@ -56,22 +62,15 @@ const Axo = ( props ) => {
|
|||
|
||||
useAxoCleanup();
|
||||
|
||||
const handleCardChange = ( selectedCard ) => {
|
||||
console.log( 'Card selection changed', selectedCard );
|
||||
setCard( selectedCard );
|
||||
};
|
||||
|
||||
console.log( 'Rendering Axo component', {
|
||||
fastlaneSdk,
|
||||
card,
|
||||
shippingAddress,
|
||||
} );
|
||||
|
||||
return fastlaneSdk ? (
|
||||
<Payment
|
||||
fastlaneSdk={ fastlaneSdk }
|
||||
card={ card }
|
||||
onChange={ handleCardChange }
|
||||
card={ cardDetails }
|
||||
onChange={ onChangeCardButtonClick }
|
||||
onPaymentLoad={ handlePaymentLoad }
|
||||
onChangeButtonClick={ onChangeCardButtonClick }
|
||||
/>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// File: axoStore.js
|
||||
|
||||
import { createReduxStore, register, dispatch } from '@wordpress/data';
|
||||
|
||||
export const STORE_NAME = 'woocommerce-paypal-payments/axo-block';
|
||||
|
||||
// Initial state
|
||||
// Initial state.
|
||||
const DEFAULT_STATE = {
|
||||
isGuest: true,
|
||||
isAxoActive: false,
|
||||
isAxoScriptLoaded: false,
|
||||
isEmailSubmitted: false,
|
||||
isEmailLookupCompleted: false,
|
||||
shippingAddress: null,
|
||||
cardDetails: null,
|
||||
};
|
||||
|
||||
// Actions
|
||||
// Actions.
|
||||
const actions = {
|
||||
setIsGuest: ( isGuest ) => ( {
|
||||
type: 'SET_IS_GUEST',
|
||||
|
@ -35,9 +35,17 @@ const actions = {
|
|||
type: 'SET_IS_EMAIL_LOOKUP_COMPLETED',
|
||||
payload: isEmailLookupCompleted,
|
||||
} ),
|
||||
setShippingAddress: ( shippingAddress ) => ( {
|
||||
type: 'SET_SHIPPING_ADDRESS',
|
||||
payload: shippingAddress,
|
||||
} ),
|
||||
setCardDetails: ( cardDetails ) => ( {
|
||||
type: 'SET_CARD_DETAILS',
|
||||
payload: cardDetails,
|
||||
} ),
|
||||
};
|
||||
|
||||
// Reducer
|
||||
// Reducer.
|
||||
const reducer = ( state = DEFAULT_STATE, action ) => {
|
||||
switch ( action.type ) {
|
||||
case 'SET_IS_GUEST':
|
||||
|
@ -50,21 +58,27 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
|
|||
return { ...state, isEmailSubmitted: action.payload };
|
||||
case 'SET_IS_EMAIL_LOOKUP_COMPLETED':
|
||||
return { ...state, isEmailLookupCompleted: action.payload };
|
||||
case 'SET_SHIPPING_ADDRESS':
|
||||
return { ...state, shippingAddress: action.payload };
|
||||
case 'SET_CARD_DETAILS':
|
||||
return { ...state, cardDetails: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Selectors
|
||||
// Selectors.
|
||||
const selectors = {
|
||||
getIsGuest: ( state ) => state.isGuest,
|
||||
getIsAxoActive: ( state ) => state.isAxoActive,
|
||||
getIsAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
|
||||
getIsEmailSubmitted: ( state ) => state.isEmailSubmitted,
|
||||
getIsEmailLookupCompleted: ( state ) => state.isEmailLookupCompleted,
|
||||
getShippingAddress: ( state ) => state.shippingAddress,
|
||||
getCardDetails: ( state ) => state.cardDetails,
|
||||
};
|
||||
|
||||
// Create and register the store
|
||||
// Create and register the store.
|
||||
const store = createReduxStore( STORE_NAME, {
|
||||
reducer,
|
||||
actions,
|
||||
|
@ -73,20 +87,19 @@ const store = createReduxStore( STORE_NAME, {
|
|||
|
||||
register( store );
|
||||
|
||||
// Action dispatchers.
|
||||
export const setIsGuest = ( isGuest ) => {
|
||||
try {
|
||||
dispatch( STORE_NAME ).setIsGuest( isGuest );
|
||||
} catch ( error ) {
|
||||
console.error( 'Error updating isGuest state:', error );
|
||||
}
|
||||
dispatch( STORE_NAME ).setIsGuest( isGuest );
|
||||
};
|
||||
|
||||
export const setIsEmailLookupCompleted = ( isEmailLookupCompleted ) => {
|
||||
try {
|
||||
dispatch( STORE_NAME ).setIsEmailLookupCompleted(
|
||||
isEmailLookupCompleted
|
||||
);
|
||||
} catch ( error ) {
|
||||
console.error( 'Error updating isEmailLookupCompleted state:', error );
|
||||
}
|
||||
dispatch( STORE_NAME ).setIsEmailLookupCompleted( isEmailLookupCompleted );
|
||||
};
|
||||
|
||||
export const setShippingAddress = ( shippingAddress ) => {
|
||||
dispatch( STORE_NAME ).setShippingAddress( shippingAddress );
|
||||
};
|
||||
|
||||
export const setCardDetails = ( cardDetails ) => {
|
||||
dispatch( STORE_NAME ).setCardDetails( cardDetails );
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue