mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Merge pull request #2945 from woocommerce/PCP-4020-review-and-fix-the-sandbox-login
Review and fix the login logic - Frontend changes (4020)
This commit is contained in:
commit
689463e243
46 changed files with 1750 additions and 1023 deletions
|
@ -19,11 +19,11 @@ export default {
|
|||
|
||||
// Controls - always start with "DO_".
|
||||
DO_PERSIST_DATA: 'COMMON:DO_PERSIST_DATA',
|
||||
DO_MANUAL_CONNECTION: 'COMMON:DO_MANUAL_CONNECTION',
|
||||
DO_SANDBOX_LOGIN: 'COMMON:DO_SANDBOX_LOGIN',
|
||||
DO_PRODUCTION_LOGIN: 'COMMON:DO_PRODUCTION_LOGIN',
|
||||
DO_DIRECT_API_AUTHENTICATION: 'COMMON:DO_DIRECT_API_AUTHENTICATION',
|
||||
DO_OAUTH_AUTHENTICATION: 'COMMON:DO_OAUTH_AUTHENTICATION',
|
||||
DO_GENERATE_ONBOARDING_URL: 'COMMON:DO_GENERATE_ONBOARDING_URL',
|
||||
DO_REFRESH_MERCHANT: 'COMMON:DO_REFRESH_MERCHANT',
|
||||
DO_REFRESH_FEATURES: 'DO_REFRESH_FEATURES',
|
||||
DO_REFRESH_FEATURES: 'COMMON:DO_REFRESH_FEATURES',
|
||||
DO_RESUBSCRIBE_WEBHOOKS: 'COMMON:DO_RESUBSCRIBE_WEBHOOKS',
|
||||
DO_START_WEBHOOK_SIMULATION: 'COMMON:DO_START_WEBHOOK_SIMULATION',
|
||||
DO_CHECK_WEBHOOK_SIMULATION_STATE:
|
||||
|
|
|
@ -123,28 +123,6 @@ export const setManualConnectionMode = ( useManualConnection ) => ( {
|
|||
payload: { useManualConnection },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Persistent. Changes the "client ID" value.
|
||||
*
|
||||
* @param {string} clientId
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setClientId = ( clientId ) => ( {
|
||||
type: ACTION_TYPES.SET_PERSISTENT,
|
||||
payload: { clientId },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Persistent. Changes the "client secret" value.
|
||||
*
|
||||
* @param {string} clientSecret
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setClientSecret = ( clientSecret ) => ( {
|
||||
type: ACTION_TYPES.SET_PERSISTENT,
|
||||
payload: { clientSecret },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Side effect. Saves the persistent details to the WP database.
|
||||
*
|
||||
|
@ -161,8 +139,12 @@ export const persist = function* () {
|
|||
*
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const connectToSandbox = function* () {
|
||||
return yield { type: ACTION_TYPES.DO_SANDBOX_LOGIN };
|
||||
export const sandboxOnboardingUrl = function* () {
|
||||
return yield {
|
||||
type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL,
|
||||
useSandbox: true,
|
||||
products: [ 'EXPRESS_CHECKOUT' ],
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -171,27 +153,65 @@ export const connectToSandbox = function* () {
|
|||
* @param {string[]} products Which products/features to display in the ISU popup.
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const connectToProduction = function* ( products = [] ) {
|
||||
return yield { type: ACTION_TYPES.DO_PRODUCTION_LOGIN, products };
|
||||
export const productionOnboardingUrl = function* ( products = [] ) {
|
||||
return yield {
|
||||
type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL,
|
||||
useSandbox: false,
|
||||
products,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Side effect. Initiates a manual connection attempt using the provided client ID and secret.
|
||||
* Side effect. Initiates a direct connection attempt using the provided client ID and secret.
|
||||
*
|
||||
* This action accepts parameters instead of fetching data from the Redux state because the
|
||||
* values (ID and secret) are not managed by a central redux store, but might come from private
|
||||
* component state.
|
||||
*
|
||||
* @param {string} clientId - AP client ID (always 80-characters, starting with "A").
|
||||
* @param {string} clientSecret - API client secret.
|
||||
* @param {boolean} useSandbox - Whether the credentials are for a sandbox account.
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const connectViaIdAndSecret = function* () {
|
||||
const { clientId, clientSecret, useSandbox } =
|
||||
yield select( STORE_NAME ).persistentData();
|
||||
|
||||
export const authenticateWithCredentials = function* (
|
||||
clientId,
|
||||
clientSecret,
|
||||
useSandbox
|
||||
) {
|
||||
return yield {
|
||||
type: ACTION_TYPES.DO_MANUAL_CONNECTION,
|
||||
type: ACTION_TYPES.DO_DIRECT_API_AUTHENTICATION,
|
||||
clientId,
|
||||
clientSecret,
|
||||
useSandbox,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Side effect. Completes the ISU login by authenticating the user via the one time sharedId and
|
||||
* authCode provided by PayPal.
|
||||
*
|
||||
* This action accepts parameters instead of fetching data from the Redux state because all
|
||||
* parameters are dynamically generated during the authentication process, and not managed by our
|
||||
* Redux store.
|
||||
*
|
||||
* @param {string} sharedId - OAuth client ID; called "sharedId" to prevent confusion with the API client ID.
|
||||
* @param {string} authCode - OAuth authorization code provided during onboarding.
|
||||
* @param {boolean} useSandbox - Whether the credentials are for a sandbox account.
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const authenticateWithOAuth = function* (
|
||||
sharedId,
|
||||
authCode,
|
||||
useSandbox
|
||||
) {
|
||||
return yield {
|
||||
type: ACTION_TYPES.DO_OAUTH_AUTHENTICATION,
|
||||
sharedId,
|
||||
authCode,
|
||||
useSandbox,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Side effect. Clears and refreshes the merchant data via a REST request.
|
||||
*
|
||||
|
|
|
@ -35,14 +35,25 @@ export const REST_HYDRATE_MERCHANT_PATH = '/wc/v3/wc_paypal/common/merchant';
|
|||
export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/common';
|
||||
|
||||
/**
|
||||
* REST path to perform the manual connection check, using client ID and secret,
|
||||
* REST path to perform the manual connection authentication, using client ID and secret.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: ConnectManualRestEndpoint.php
|
||||
* See: AuthenticateRestEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_MANUAL_CONNECTION_PATH = '/wc/v3/wc_paypal/connect_manual';
|
||||
export const REST_DIRECT_AUTHENTICATION_PATH =
|
||||
'/wc/v3/wc_paypal/authenticate/direct';
|
||||
|
||||
/**
|
||||
* REST path to perform the ISU authentication check, using shared ID and authCode.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: AuthenticateRestEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_ISU_AUTHENTICATION_PATH = '/wc/v3/wc_paypal/authenticate/isu';
|
||||
|
||||
/**
|
||||
* REST path to generate an ISU URL for the PayPal-login.
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
import apiFetch from '@wordpress/api-fetch';
|
||||
|
||||
import {
|
||||
REST_PERSIST_PATH,
|
||||
REST_DIRECT_AUTHENTICATION_PATH,
|
||||
REST_CONNECTION_URL_PATH,
|
||||
REST_HYDRATE_MERCHANT_PATH,
|
||||
REST_MANUAL_CONNECTION_PATH,
|
||||
REST_PERSIST_PATH,
|
||||
REST_REFRESH_FEATURES_PATH,
|
||||
REST_ISU_AUTHENTICATION_PATH,
|
||||
REST_WEBHOOKS,
|
||||
REST_WEBHOOKS_SIMULATE,
|
||||
} from './constants';
|
||||
|
@ -33,15 +34,15 @@ export const controls = {
|
|||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_SANDBOX_LOGIN ]() {
|
||||
async [ ACTION_TYPES.DO_GENERATE_ONBOARDING_URL ]( {
|
||||
products,
|
||||
useSandbox,
|
||||
} ) {
|
||||
try {
|
||||
return apiFetch( {
|
||||
path: REST_CONNECTION_URL_PATH,
|
||||
method: 'POST',
|
||||
data: {
|
||||
environment: 'sandbox',
|
||||
products: [ 'EXPRESS_CHECKOUT' ], // Sandbox always uses EXPRESS_CHECKOUT.
|
||||
},
|
||||
data: { useSandbox, products },
|
||||
} );
|
||||
} catch ( e ) {
|
||||
return {
|
||||
|
@ -51,32 +52,14 @@ export const controls = {
|
|||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_PRODUCTION_LOGIN ]( { products } ) {
|
||||
try {
|
||||
return apiFetch( {
|
||||
path: REST_CONNECTION_URL_PATH,
|
||||
method: 'POST',
|
||||
data: {
|
||||
environment: 'production',
|
||||
products,
|
||||
},
|
||||
} );
|
||||
} catch ( e ) {
|
||||
return {
|
||||
success: false,
|
||||
error: e,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_MANUAL_CONNECTION ]( {
|
||||
async [ ACTION_TYPES.DO_DIRECT_API_AUTHENTICATION ]( {
|
||||
clientId,
|
||||
clientSecret,
|
||||
useSandbox,
|
||||
} ) {
|
||||
try {
|
||||
return await apiFetch( {
|
||||
path: REST_MANUAL_CONNECTION_PATH,
|
||||
path: REST_DIRECT_AUTHENTICATION_PATH,
|
||||
method: 'POST',
|
||||
data: {
|
||||
clientId,
|
||||
|
@ -92,6 +75,29 @@ export const controls = {
|
|||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_OAUTH_AUTHENTICATION ]( {
|
||||
sharedId,
|
||||
authCode,
|
||||
useSandbox,
|
||||
} ) {
|
||||
try {
|
||||
return await apiFetch( {
|
||||
path: REST_ISU_AUTHENTICATION_PATH,
|
||||
method: 'POST',
|
||||
data: {
|
||||
sharedId,
|
||||
authCode,
|
||||
useSandbox,
|
||||
},
|
||||
} );
|
||||
} catch ( e ) {
|
||||
return {
|
||||
success: false,
|
||||
error: e,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_REFRESH_MERCHANT ]() {
|
||||
try {
|
||||
return await apiFetch( { path: REST_HYDRATE_MERCHANT_PATH } );
|
||||
|
|
|
@ -28,11 +28,10 @@ const useHooks = () => {
|
|||
persist,
|
||||
setSandboxMode,
|
||||
setManualConnectionMode,
|
||||
setClientId,
|
||||
setClientSecret,
|
||||
connectToSandbox,
|
||||
connectToProduction,
|
||||
connectViaIdAndSecret,
|
||||
sandboxOnboardingUrl,
|
||||
productionOnboardingUrl,
|
||||
authenticateWithCredentials,
|
||||
authenticateWithOAuth,
|
||||
setActiveModal,
|
||||
startWebhookSimulation,
|
||||
checkWebhookSimulationState,
|
||||
|
@ -43,19 +42,26 @@ const useHooks = () => {
|
|||
const activeModal = useTransient( 'activeModal' );
|
||||
|
||||
// Persistent accessors.
|
||||
const clientId = usePersistent( 'clientId' );
|
||||
const clientSecret = usePersistent( 'clientSecret' );
|
||||
const isSandboxMode = usePersistent( 'useSandbox' );
|
||||
const isManualConnectionMode = usePersistent( 'useManualConnection' );
|
||||
const webhooks = usePersistent( 'webhooks' );
|
||||
const merchant = useSelect(
|
||||
( select ) => select( STORE_NAME ).merchant(),
|
||||
[]
|
||||
);
|
||||
|
||||
// Read-only properties.
|
||||
const wooSettings = useSelect(
|
||||
( select ) => select( STORE_NAME ).wooSettings(),
|
||||
[]
|
||||
);
|
||||
const features = useSelect(
|
||||
( select ) => select( STORE_NAME ).features(),
|
||||
[]
|
||||
);
|
||||
const webhooks = useSelect(
|
||||
( select ) => select( STORE_NAME ).webhooks(),
|
||||
[]
|
||||
);
|
||||
|
||||
const savePersistent = async ( setter, value ) => {
|
||||
setter( value );
|
||||
|
@ -74,19 +80,13 @@ const useHooks = () => {
|
|||
setManualConnectionMode: ( state ) => {
|
||||
return savePersistent( setManualConnectionMode, state );
|
||||
},
|
||||
clientId,
|
||||
setClientId: ( value ) => {
|
||||
return savePersistent( setClientId, value );
|
||||
},
|
||||
clientSecret,
|
||||
setClientSecret: ( value ) => {
|
||||
return savePersistent( setClientSecret, value );
|
||||
},
|
||||
connectToSandbox,
|
||||
connectToProduction,
|
||||
connectViaIdAndSecret,
|
||||
sandboxOnboardingUrl,
|
||||
productionOnboardingUrl,
|
||||
authenticateWithCredentials,
|
||||
authenticateWithOAuth,
|
||||
merchant,
|
||||
wooSettings,
|
||||
features,
|
||||
webhooks,
|
||||
startWebhookSimulation,
|
||||
checkWebhookSimulationState,
|
||||
|
@ -94,36 +94,30 @@ const useHooks = () => {
|
|||
};
|
||||
|
||||
export const useSandbox = () => {
|
||||
const { isSandboxMode, setSandboxMode, connectToSandbox } = useHooks();
|
||||
const { isSandboxMode, setSandboxMode, sandboxOnboardingUrl } = useHooks();
|
||||
|
||||
return { isSandboxMode, setSandboxMode, connectToSandbox };
|
||||
return { isSandboxMode, setSandboxMode, sandboxOnboardingUrl };
|
||||
};
|
||||
|
||||
export const useProduction = () => {
|
||||
const { connectToProduction } = useHooks();
|
||||
const { productionOnboardingUrl } = useHooks();
|
||||
|
||||
return { connectToProduction };
|
||||
return { productionOnboardingUrl };
|
||||
};
|
||||
|
||||
export const useManualConnection = () => {
|
||||
export const useAuthentication = () => {
|
||||
const {
|
||||
isManualConnectionMode,
|
||||
setManualConnectionMode,
|
||||
clientId,
|
||||
setClientId,
|
||||
clientSecret,
|
||||
setClientSecret,
|
||||
connectViaIdAndSecret,
|
||||
authenticateWithCredentials,
|
||||
authenticateWithOAuth,
|
||||
} = useHooks();
|
||||
|
||||
return {
|
||||
isManualConnectionMode,
|
||||
setManualConnectionMode,
|
||||
clientId,
|
||||
setClientId,
|
||||
clientSecret,
|
||||
setClientSecret,
|
||||
connectViaIdAndSecret,
|
||||
authenticateWithCredentials,
|
||||
authenticateWithOAuth,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -150,7 +144,7 @@ export const useWebhooks = () => {
|
|||
};
|
||||
};
|
||||
export const useMerchantInfo = () => {
|
||||
const { merchant } = useHooks();
|
||||
const { merchant, features } = useHooks();
|
||||
const { refreshMerchantData } = useDispatch( STORE_NAME );
|
||||
|
||||
const verifyLoginStatus = useCallback( async () => {
|
||||
|
@ -166,6 +160,7 @@ export const useMerchantInfo = () => {
|
|||
|
||||
return {
|
||||
merchant, // Merchant details
|
||||
features, // Eligible merchant features
|
||||
verifyLoginStatus, // Callback
|
||||
};
|
||||
};
|
||||
|
|
|
@ -23,20 +23,36 @@ const defaultTransient = Object.freeze( {
|
|||
isSandbox: false,
|
||||
id: '',
|
||||
email: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
} ),
|
||||
|
||||
wooSettings: Object.freeze( {
|
||||
storeCountry: '',
|
||||
storeCurrency: '',
|
||||
} ),
|
||||
|
||||
features: Object.freeze( {
|
||||
save_paypal_and_venmo: {
|
||||
enabled: false,
|
||||
},
|
||||
advanced_credit_and_debit_cards: {
|
||||
enabled: false,
|
||||
},
|
||||
apple_pay: {
|
||||
enabled: false,
|
||||
},
|
||||
google_pay: {
|
||||
enabled: false,
|
||||
},
|
||||
} ),
|
||||
|
||||
webhooks: Object.freeze( [] ),
|
||||
} );
|
||||
|
||||
const defaultPersistent = Object.freeze( {
|
||||
useSandbox: false,
|
||||
useManualConnection: false,
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
webhooks: [],
|
||||
} );
|
||||
|
||||
// Reducer logic.
|
||||
|
@ -84,22 +100,25 @@ const commonReducer = createReducer( defaultTransient, defaultPersistent, {
|
|||
[ ACTION_TYPES.DO_REFRESH_MERCHANT ]: ( state ) => ( {
|
||||
...state,
|
||||
merchant: Object.freeze( { ...defaultTransient.merchant } ),
|
||||
features: Object.freeze( { ...defaultTransient.features } ),
|
||||
} ),
|
||||
|
||||
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) => {
|
||||
const newState = setPersistent( state, payload.data );
|
||||
|
||||
// Populate read-only properties.
|
||||
[ 'wooSettings', 'merchant' ].forEach( ( key ) => {
|
||||
if ( ! payload[ key ] ) {
|
||||
return;
|
||||
}
|
||||
[ 'wooSettings', 'merchant', 'features', 'webhooks' ].forEach(
|
||||
( key ) => {
|
||||
if ( ! payload[ key ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
newState[ key ] = Object.freeze( {
|
||||
...newState[ key ],
|
||||
...payload[ key ],
|
||||
} );
|
||||
} );
|
||||
newState[ key ] = Object.freeze( {
|
||||
...newState[ key ],
|
||||
...payload[ key ],
|
||||
} );
|
||||
}
|
||||
);
|
||||
|
||||
return newState;
|
||||
},
|
||||
|
|
|
@ -16,8 +16,14 @@ export const persistentData = ( state ) => {
|
|||
};
|
||||
|
||||
export const transientData = ( state ) => {
|
||||
const { data, merchant, wooSettings, ...transientState } =
|
||||
getState( state );
|
||||
const {
|
||||
data,
|
||||
merchant,
|
||||
features,
|
||||
wooSettings,
|
||||
webhooks,
|
||||
...transientState
|
||||
} = getState( state );
|
||||
return transientState || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
|
@ -30,6 +36,10 @@ export const merchant = ( state ) => {
|
|||
return getState( state ).merchant || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
export const features = ( state ) => {
|
||||
return getState( state ).features || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
export const wooSettings = ( state ) => {
|
||||
return getState( state ).wooSettings || EMPTY_OBJ;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,28 @@ export const setIsReady = ( isReady ) => ( {
|
|||
payload: { isReady },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Transient. Sets the "manualClientId" value.
|
||||
*
|
||||
* @param {string} manualClientId
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setManualClientId = ( manualClientId ) => ( {
|
||||
type: ACTION_TYPES.SET_TRANSIENT,
|
||||
payload: { manualClientId },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Transient. Sets the "manualClientSecret" value.
|
||||
*
|
||||
* @param {string} manualClientSecret
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setManualClientSecret = ( manualClientSecret ) => ( {
|
||||
type: ACTION_TYPES.SET_TRANSIENT,
|
||||
payload: { manualClientSecret },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Persistent.Set the "onboarding completed" flag which shows or hides the wizard.
|
||||
*
|
||||
|
|
|
@ -30,6 +30,8 @@ const useHooks = () => {
|
|||
setStep,
|
||||
setCompleted,
|
||||
setIsCasualSeller,
|
||||
setManualClientId,
|
||||
setManualClientSecret,
|
||||
setAreOptionalPaymentMethodsEnabled,
|
||||
setProducts,
|
||||
} = useDispatch( STORE_NAME );
|
||||
|
@ -43,6 +45,8 @@ const useHooks = () => {
|
|||
|
||||
// Transient accessors.
|
||||
const isReady = useTransient( 'isReady' );
|
||||
const manualClientId = useTransient( 'manualClientId' );
|
||||
const manualClientSecret = useTransient( 'manualClientSecret' );
|
||||
|
||||
// Persistent accessors.
|
||||
const step = usePersistent( 'step' );
|
||||
|
@ -73,6 +77,14 @@ const useHooks = () => {
|
|||
setIsCasualSeller: ( value ) => {
|
||||
return savePersistent( setIsCasualSeller, value );
|
||||
},
|
||||
manualClientId,
|
||||
setManualClientId: ( value ) => {
|
||||
return savePersistent( setManualClientId, value );
|
||||
},
|
||||
manualClientSecret,
|
||||
setManualClientSecret: ( value ) => {
|
||||
return savePersistent( setManualClientSecret, value );
|
||||
},
|
||||
areOptionalPaymentMethodsEnabled,
|
||||
setAreOptionalPaymentMethodsEnabled: ( value ) => {
|
||||
return savePersistent( setAreOptionalPaymentMethodsEnabled, value );
|
||||
|
@ -88,6 +100,22 @@ const useHooks = () => {
|
|||
};
|
||||
};
|
||||
|
||||
export const useManualConnectionForm = () => {
|
||||
const {
|
||||
manualClientId,
|
||||
setManualClientId,
|
||||
manualClientSecret,
|
||||
setManualClientSecret,
|
||||
} = useHooks();
|
||||
|
||||
return {
|
||||
manualClientId,
|
||||
setManualClientId,
|
||||
manualClientSecret,
|
||||
setManualClientSecret,
|
||||
};
|
||||
};
|
||||
|
||||
export const useBusiness = () => {
|
||||
const { isCasualSeller, setIsCasualSeller } = useHooks();
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import ACTION_TYPES from './action-types';
|
|||
|
||||
const defaultTransient = Object.freeze( {
|
||||
isReady: false,
|
||||
manualClientId: '',
|
||||
manualClientSecret: '',
|
||||
|
||||
// Read only values, provided by the server.
|
||||
flags: Object.freeze( {
|
||||
|
|
|
@ -52,9 +52,6 @@ export const determineProducts = ( state ) => {
|
|||
* The store uses the Express-checkout product.
|
||||
*/
|
||||
derivedProducts.push( 'EXPRESS_CHECKOUT' );
|
||||
|
||||
// TODO: Add the "BCDC" product/feature
|
||||
// Requirement: "EXPRESS_CHECKOUT with BCDC"
|
||||
} else {
|
||||
/**
|
||||
* Branch 3: Merchant is business, and can use CC payments.
|
||||
|
@ -64,8 +61,7 @@ export const determineProducts = ( state ) => {
|
|||
}
|
||||
|
||||
if ( canUseVaulting ) {
|
||||
// TODO: Add the "Vaulting" product/feature
|
||||
// Requirement: "... with Vault"
|
||||
derivedProducts.push( 'ADVANCED_VAULTING' );
|
||||
}
|
||||
|
||||
return derivedProducts;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue