This repository has been archived by the owner on Feb 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add defined payment method configs and implement initialization logic
- Loading branch information
Showing
13 changed files
with
276 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 11 additions & 4 deletions
15
assets/js/base/components/payment-methods/express-payment-methods.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { default as useActivePaymentMethod } from './use-active-payment-method'; | ||
export { default as usePaymentEvents } from './use-payment-events'; | ||
export * from './use-payment-methods'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
assets/js/base/hooks/payment-methods/use-payment-methods.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { | ||
getPaymentMethods, | ||
getExpressPaymentMethods, | ||
} from '@woocommerce/blocks-registry'; | ||
import { useState, useEffect, useRef } from '@wordpress/element'; | ||
|
||
const usePaymentMethodState = ( registeredPaymentMethods ) => { | ||
const [ paymentMethods, setPaymentMethods ] = useState( [] ); | ||
const [ isInitialized, setIsInitialized ] = useState( false ); | ||
const countPaymentMethodsInitializing = useRef( | ||
Object.keys( registeredPaymentMethods ).length | ||
); | ||
|
||
useEffect( () => { | ||
// if all payment methods are initialized then bail. | ||
if ( isInitialized ) { | ||
return; | ||
} | ||
// loop through payment methods and see what the state is | ||
for ( const paymentMethodId in registeredPaymentMethods ) { | ||
const current = registeredPaymentMethods[ paymentMethodId ]; | ||
current.canMakePayment | ||
.then( ( canPay ) => { | ||
if ( canPay ) { | ||
setPaymentMethods( ( previousPaymentMethods ) => { | ||
return { | ||
...previousPaymentMethods, | ||
[ current.id ]: current, | ||
}; | ||
} ); | ||
} | ||
// update the initialized count | ||
countPaymentMethodsInitializing.current--; | ||
// if count remaining less than 1, then set initialized. | ||
if ( countPaymentMethodsInitializing.current < 1 ) { | ||
setIsInitialized( true ); | ||
} | ||
} ) | ||
.catch( ( error ) => { | ||
// @todo, would be a good place to use the checkout error | ||
// hooks here? Or maybe throw and catch by error boundary? | ||
throw new Error( | ||
'Problem with payment method initialization' + | ||
( error.message || '' ) | ||
); | ||
} ); | ||
} | ||
}, [ isInitialized ] ); | ||
|
||
return { paymentMethods, isInitialized }; | ||
}; | ||
|
||
export const usePaymentMethods = () => | ||
usePaymentMethodState( getPaymentMethods() ); | ||
export const useExpressPaymentMethods = () => | ||
usePaymentMethodState( getExpressPaymentMethods() ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,36 @@ | ||
export const assertValidPaymentMethodComponent = ( paymentMethod ) => { | ||
export const assertValidPaymentMethodComponent = ( | ||
component, | ||
componentName | ||
) => { | ||
// @todo detect if functional component (not render prop) | ||
if ( typeof paymentMethod !== 'function' ) { | ||
if ( typeof component !== 'function' ) { | ||
throw new Error( | ||
'The registered payment method must be a functional component' | ||
`The ${ componentName } for the payment method must be a functional component` | ||
); | ||
} | ||
}; | ||
|
||
export const assertValidPaymentMethod = ( paymentMethod ) => { | ||
// paymentMethods are expected to have 4 properties, tab, content, name, ariaLabel. | ||
if ( ! paymentMethod.tab ) { | ||
throw new Error( | ||
'A payment method is expected to have a tab property' | ||
); | ||
export const assertConfigHasProperties = ( | ||
config, | ||
expectedProperties = [] | ||
) => { | ||
const missingProperties = expectedProperties.reduce( ( acc, property ) => { | ||
if ( ! config[ property ] ) { | ||
acc.push( property ); | ||
} | ||
return acc; | ||
}, [] ); | ||
if ( missingProperties.length > 0 ) { | ||
const message = | ||
'The payment method configuration object is missing the following properties:'; | ||
throw new Error( message + missingProperties.join( ', ' ) ); | ||
} | ||
if ( ! paymentMethod.content ) { | ||
throw new Error( | ||
'A payment method is expected to have a content property' | ||
); | ||
} | ||
if ( ! paymentMethod.ariaLabel ) { | ||
throw new Error( | ||
'A payment method is expected to have an ariaLabel property. This is used for tabs aria-label property.' | ||
); | ||
} | ||
try { | ||
assertValidPaymentMethodComponent( paymentMethod.content ); | ||
} catch ( e ) { | ||
throw new Error( | ||
'The paymentMethod.content value must be a functional components' | ||
); | ||
} | ||
try { | ||
assertValidPaymentMethodComponent( paymentMethod.tab ); | ||
} catch ( e ) { | ||
}; | ||
|
||
export const assertValidPaymentMethodCreator = ( creator, configName ) => { | ||
if ( typeof creator !== 'function' ) { | ||
throw new Error( | ||
'The paymentMethod.tab value must be a functional components' | ||
`A payment method must be registered with a function that creates and returns a ${ configName } instance` | ||
); | ||
} | ||
}; |
36 changes: 36 additions & 0 deletions
36
assets/js/blocks-registry/payment-methods/express-payment-method-config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { | ||
assertConfigHasProperties, | ||
assertValidPaymentMethodComponent, | ||
} from './assertions'; | ||
|
||
export default class ExpressPaymentMethodConfig { | ||
constructor( config ) { | ||
// validate config | ||
ExpressPaymentMethodConfig.assertValidConfig( config ); | ||
this.id = config.id; | ||
this.activeContent = config.activeContent; | ||
this.canMakePayment = config.canMakePayment; | ||
Object.freeze( this ); | ||
} | ||
|
||
static assertValidConfig = ( config ) => { | ||
assertConfigHasProperties( config, [ 'id', 'activeContent' ] ); | ||
if ( typeof config.id !== 'string' ) { | ||
throw new Error( | ||
'The id for the express payment method must be a string' | ||
); | ||
} | ||
assertValidPaymentMethodComponent( | ||
config.activeContent, | ||
'activeContent' | ||
); | ||
if ( ! ( config.canMakePayment instanceof Promise ) ) { | ||
throw new Error( | ||
'The canMakePayment property for the express payment method must be a promise.' | ||
); | ||
} | ||
}; | ||
} |
51 changes: 51 additions & 0 deletions
51
assets/js/blocks-registry/payment-methods/payment-method-config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { | ||
assertConfigHasProperties, | ||
assertValidPaymentMethodComponent, | ||
} from './assertions'; | ||
|
||
export default class PaymentMethodConfig { | ||
constructor( config ) { | ||
// validate config | ||
PaymentMethodConfig.assertValidConfig( config ); | ||
this.id = config.id; | ||
this.label = config.label; | ||
this.stepContent = config.stepContent; | ||
this.ariaLabel = config.ariaLabel; | ||
this.activeContent = config.activeContent; | ||
this.canMakePayment = config.canMakePayment; | ||
Object.freeze( this ); | ||
} | ||
|
||
static assertValidConfig = ( config ) => { | ||
assertConfigHasProperties( config, [ | ||
'id', | ||
'label', | ||
'stepContent', | ||
'ariaLabel', | ||
'activeContent', | ||
'canMakePayment', | ||
] ); | ||
if ( typeof config.id !== 'string' ) { | ||
throw new Error( 'The id for the payment method must be a string' ); | ||
} | ||
assertValidPaymentMethodComponent( config.label, 'label' ); | ||
assertValidPaymentMethodComponent( config.stepContent, 'stepContent' ); | ||
assertValidPaymentMethodComponent( | ||
config.activeContent, | ||
'activeContent' | ||
); | ||
if ( typeof config.ariaLabel !== 'string' ) { | ||
throw new Error( | ||
'The ariaLabel for the payment method must be a string' | ||
); | ||
} | ||
if ( ! ( config.canMakePayment instanceof Promise ) ) { | ||
throw new Error( | ||
'The canMakePayment property for the payment method must be a promise.' | ||
); | ||
} | ||
}; | ||
} |
Oops, something went wrong.