Merge pull request #3182 from woocommerce/PCP-4232-change-onboarding-flags

Change onboarding flags (4232)
This commit is contained in:
Emili Castells 2025-03-06 09:46:36 +01:00 committed by GitHub
commit fad93e3e81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 613 additions and 147 deletions

View file

@ -5,7 +5,7 @@
* @package WooCommerce\PayPalCommerce\ApiClient\Repository
*/
declare(strict_types=1);
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\ApiClient\Repository;
@ -18,43 +18,21 @@ class PartnerReferralsData {
/**
* The DCC Applies Helper object.
*
* @deprecated Deprecates with the new UI. In this class, the products are
* always explicit, and should not be deducted from the
* DccApplies state at this point.
* Remove this with the legacy UI code.
* @var DccApplies
*/
private $dcc_applies;
/**
* The list of products ('PPCP', 'EXPRESS_CHECKOUT').
*
* @var string[]
*/
private $products;
private DccApplies $dcc_applies;
/**
* PartnerReferralsData constructor.
*
* @param DccApplies $dcc_applies The DCC Applies helper.
*/
public function __construct(
DccApplies $dcc_applies
) {
public function __construct( DccApplies $dcc_applies ) {
$this->dcc_applies = $dcc_applies;
$this->products = array(
$this->dcc_applies->for_country_currency() ? 'PPCP' : 'EXPRESS_CHECKOUT',
);
}
/**
* Returns a new copy of this object with the given value set.
*
* @param string[] $products The list of products ('PPCP', 'EXPRESS_CHECKOUT').
* @return static
*/
public function with_products( array $products ): self {
$obj = clone $this;
$obj->products = $products;
return $obj;
}
/**
@ -62,82 +40,119 @@ class PartnerReferralsData {
*
* @return string
*/
public function nonce(): string {
public function nonce() : string {
return 'a1233wtergfsdt4365tzrshgfbaewa36AGa1233wtergfsdt4365tzrshgfbaewa36AG';
}
/**
* Returns the data.
*
* @param string[] $products The list of products to use ('PPCP', 'EXPRESS_CHECKOUT').
* Default is based on DCC availability.
* @param string $onboarding_token A security token to finalize the onboarding process.
* @param bool $use_subscriptions If the merchant requires subscription features.
* @param bool $use_card_payments If the merchant wants to process credit card payments.
* @return array
*/
public function data(): array {
public function data( array $products = array(), string $onboarding_token = '', bool $use_subscriptions = null, bool $use_card_payments = true ) : array {
if ( ! $products ) {
$products = array(
$this->dcc_applies->for_country_currency() ? 'PPCP' : 'EXPRESS_CHECKOUT',
);
}
/**
* Returns the partners referrals data.
* Filter the return-URL, which is called at the end of the OAuth onboarding
* process, when the merchant clicks the "Return to your shop" button.
*/
return apply_filters(
'ppcp_partner_referrals_data',
array(
'partner_config_override' => array(
/**
* Returns the URL which will be opened at the end of onboarding.
*/
'return_url' => apply_filters(
'woocommerce_paypal_payments_partner_config_override_return_url',
admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway' )
),
/**
* Returns the description of the URL which will be opened at the end of onboarding.
*/
'return_url_description' => apply_filters(
'woocommerce_paypal_payments_partner_config_override_return_url_description',
__( 'Return to your shop.', 'woocommerce-paypal-payments' )
),
'show_add_credit_card' => true,
$return_url = apply_filters(
'woocommerce_paypal_payments_partner_config_override_return_url',
admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway' )
);
/**
* Filter the label of the "Return to your shop" button.
* It's displayed on the very last page of the onboarding popup.
*/
$return_url_label = apply_filters(
'woocommerce_paypal_payments_partner_config_override_return_url_description',
__( 'Return to your shop.', 'woocommerce-paypal-payments' )
);
$capabilities = array();
$first_party_features = array(
'PAYMENT',
'REFUND',
'ADVANCED_TRANSACTIONS_SEARCH',
'TRACKING_SHIPMENT_READWRITE',
);
if ( true === $use_subscriptions ) {
$capabilities[] = 'PAYPAL_WALLET_VAULTING_ADVANCED';
}
// Backwards compatibility. Keep those features in the legacy UI (null-value).
// Move this into the previous condition, once legacy code is removed.
if ( false !== $use_subscriptions ) {
$first_party_features[] = 'FUTURE_PAYMENT';
$first_party_features[] = 'VAULT';
}
if ( false === $use_subscriptions ) {
// Only use "ADVANCED_VAULTING" product for onboarding with subscriptions.
$products = array_filter(
$products,
static fn( $product ) => $product !== 'ADVANCED_VAULTING'
);
}
$payload = array(
'partner_config_override' => array(
'return_url' => $return_url,
'return_url_description' => $return_url_label,
'show_add_credit_card' => $use_card_payments,
),
'products' => $products,
'capabilities' => $capabilities,
'legal_consents' => array(
array(
'type' => 'SHARE_DATA_CONSENT',
'granted' => true,
),
'products' => $this->products,
'legal_consents' => array(
array(
'type' => 'SHARE_DATA_CONSENT',
'granted' => true,
),
),
'operations' => array(
array(
'operation' => 'API_INTEGRATION',
'api_integration_preference' => array(
'rest_api_integration' => array(
'integration_method' => 'PAYPAL',
'integration_type' => 'FIRST_PARTY',
'first_party_details' => array(
'features' => array(
'PAYMENT',
'FUTURE_PAYMENT',
'REFUND',
'ADVANCED_TRANSACTIONS_SEARCH',
'VAULT',
'TRACKING_SHIPMENT_READWRITE',
),
'seller_nonce' => $this->nonce(),
),
),
'operations' => array(
array(
'operation' => 'API_INTEGRATION',
'api_integration_preference' => array(
'rest_api_integration' => array(
'integration_method' => 'PAYPAL',
'integration_type' => 'FIRST_PARTY',
'first_party_details' => array(
'features' => $first_party_features,
'seller_nonce' => $this->nonce(),
),
),
),
),
)
),
);
}
/**
* Append the validation token to the return_url
*
* @param array $data The referral data.
* @param string $token The token to be appended.
* @return array
*/
public function append_onboarding_token( array $data, string $token ): array {
$data['partner_config_override']['return_url'] =
add_query_arg( 'ppcpToken', $token, $data['partner_config_override']['return_url'] );
return $data;
/**
* Filter the final partners referrals data collection.
*/
$payload = apply_filters( 'ppcp_partner_referrals_data', $payload );
// An empty array is not permitted.
if ( isset( $payload['capabilities'] ) && ! $payload['capabilities'] ) {
unset( $payload['capabilities'] );
}
// Add the nonce in the end, to maintain backwards compatibility of filters.
$payload['partner_config_override']['return_url'] = add_query_arg(
array( 'ppcpToken' => $onboarding_token ),
$payload['partner_config_override']['return_url']
);
return $payload;
}
}

View file

@ -103,12 +103,8 @@ class OnboardingRenderer {
'displayMode' => 'minibrowser',
);
$data = $this->partner_referrals_data
->with_products( $products )
->data();
$environment = $is_production ? 'production' : 'sandbox';
$product = 'PPCP' === $data['products'][0] ? 'ppcp' : 'express_checkout';
$product = strtolower( $products[0] ?? 'express_checkout' );
$cache_key = $environment . '-' . $product;
$onboarding_url = new OnboardingUrl( $this->cache, $cache_key, get_current_user_id() );
@ -122,8 +118,7 @@ class OnboardingRenderer {
$onboarding_url->init();
$data = $this->partner_referrals_data
->append_onboarding_token( $data, $onboarding_url->token() ?: '' );
$data = $this->partner_referrals_data->data( $products, $onboarding_url->token() ?: '' );
$url = $is_production ? $this->production_partner_referrals->signup_link( $data ) : $this->sandbox_partner_referrals->signup_link( $data );
$url = add_query_arg( $args, $url );

View file

@ -68,10 +68,11 @@ export function sandboxOnboardingUrl() {
/**
* Side effect. Fetches the ISU-login URL for a production account.
*
* @param {string[]} products Which products/features to display in the ISU popup.
* @param {string[]} [products=[]] Which products/features to display in the ISU popup.
* @param {Object} [options={}] Options to customize the onboarding workflow.
* @return {Function} The thunk function.
*/
export function productionOnboardingUrl( products = [] ) {
export function productionOnboardingUrl( products = [], options = {} ) {
return async () => {
try {
return apiFetch( {
@ -80,6 +81,7 @@ export function productionOnboardingUrl( products = [] ) {
data: {
useSandbox: false,
products,
options,
},
} );
} catch ( e ) {

View file

@ -41,8 +41,6 @@ const useHooks = () => {
const { useTransient, usePersistent, dispatch, select } = useStoreData();
const {
persist,
sandboxOnboardingUrl,
productionOnboardingUrl,
authenticateWithCredentials,
authenticateWithOAuth,
startWebhookSimulation,
@ -53,7 +51,6 @@ const useHooks = () => {
const [ activeModal, setActiveModal ] = useTransient( 'activeModal' );
// Persistent accessors.
const [ isSandboxMode, setSandboxMode ] = usePersistent( 'useSandbox' );
const [ isManualConnectionMode, setManualConnectionMode ] = usePersistent(
'useManualConnection'
);
@ -71,16 +68,10 @@ const useHooks = () => {
return {
activeModal,
setActiveModal,
isSandboxMode,
setSandboxMode: ( state ) => {
return savePersistent( setSandboxMode, state );
},
isManualConnectionMode,
setManualConnectionMode: ( state ) => {
return savePersistent( setManualConnectionMode, state );
},
sandboxOnboardingUrl,
productionOnboardingUrl,
authenticateWithCredentials,
authenticateWithOAuth,
wooSettings,
@ -105,13 +96,23 @@ export const useStore = () => {
};
export const useSandbox = () => {
const { isSandboxMode, setSandboxMode, sandboxOnboardingUrl } = useHooks();
const { dispatch, usePersistent } = useStoreData();
const [ isSandboxMode, setSandboxMode ] = usePersistent( 'useSandbox' );
const { sandboxOnboardingUrl, persist } = dispatch;
return { isSandboxMode, setSandboxMode, sandboxOnboardingUrl };
return {
isSandboxMode,
setSandboxMode: ( state ) => {
setSandboxMode( state );
return persist();
},
sandboxOnboardingUrl,
};
};
export const useProduction = () => {
const { productionOnboardingUrl } = useHooks();
const { dispatch } = useStoreData();
const { productionOnboardingUrl } = dispatch;
return { productionOnboardingUrl };
};

View file

@ -24,3 +24,9 @@ export const PRODUCT_TYPES = {
PHYSICAL: 'physical',
SUBSCRIPTIONS: 'subscriptions',
};
export const PAYPAL_PRODUCTS = {
ACDC: 'PPCP',
BCDC: 'EXPRESS_CHECKOUT',
VAULTING: 'ADVANCED_VAULTING',
};

View file

@ -19,10 +19,6 @@ const useHooks = () => {
// Read-only flags and derived state.
const flags = useSelect( ( select ) => select( STORE_NAME ).flags(), [] );
const determineProducts = useSelect(
( select ) => select( STORE_NAME ).determineProducts(),
[]
);
// Transient accessors.
const [ isReady ] = useTransient( 'isReady' );
@ -80,7 +76,6 @@ const useHooks = () => {
);
return savePersistent( setProducts, validProducts );
},
determineProducts,
};
};
@ -141,9 +136,9 @@ export const useNavigationState = () => {
};
export const useDetermineProducts = () => {
const { determineProducts } = useHooks();
return determineProducts;
return useSelect( ( select ) => {
return select( STORE_NAME ).determineProductsAndCaps();
}, [] );
};
export const useFlags = () => {

View file

@ -7,6 +7,8 @@
* @file
*/
import { PAYPAL_PRODUCTS, PRODUCT_TYPES } from './configuration';
const EMPTY_OBJ = Object.freeze( {} );
const getState = ( state ) => state || EMPTY_OBJ;
@ -25,44 +27,71 @@ export const flags = ( state ) => {
};
/**
* Returns the products that we use for the production login link in the last onboarding step.
* Returns details about products and capabilities to use for the production login link in
* the last onboarding step.
*
* This selector does not return state-values, but uses the state to derive the products-array
* that should be returned.
*
* @param {{}} state
* @return {string[]} The ISU products, based on choices made in the onboarding wizard.
* @return {{products:string[], options:{}}} The ISU products, based on choices made in the onboarding wizard.
*/
export const determineProducts = ( state ) => {
const derivedProducts = [];
export const determineProductsAndCaps = ( state ) => {
/**
* An array of product-names that are used to build an onboarding URL via the
* PartnerReferrals API. To avoid confusion with the "products" property from the
* Redux store, this collection has a distinct name.
*
* On server-side, this value is referred to as "products" again.
*/
const apiModules = [];
const { isCasualSeller, areOptionalPaymentMethodsEnabled } =
/**
* Internal options that are parsed by the PartnerReferrals class to customize
* the API payload.
*/
const options = {
useSubscriptions: false,
useCardPayments: false,
};
const { isCasualSeller, areOptionalPaymentMethodsEnabled, products } =
persistentData( state );
const { canUseVaulting, canUseCardPayments } = flags( state );
const cardPaymentsEligibleAndSelected =
canUseCardPayments && areOptionalPaymentMethodsEnabled;
if ( ! canUseCardPayments || ! areOptionalPaymentMethodsEnabled ) {
if ( ! cardPaymentsEligibleAndSelected ) {
/**
* Branch 1: Credit Card Payments not available.
* The store uses the Express-checkout product.
*/
derivedProducts.push( 'EXPRESS_CHECKOUT' );
apiModules.push( PAYPAL_PRODUCTS.BCDC );
} else if ( isCasualSeller ) {
/**
* Branch 2: Merchant has no business.
* The store uses the Express-checkout product.
*/
derivedProducts.push( 'EXPRESS_CHECKOUT' );
apiModules.push( PAYPAL_PRODUCTS.BCDC );
} else {
/**
* Branch 3: Merchant is business, and can use CC payments.
* The store uses the advanced PPCP product.
*
* This is the only branch that can use subscriptions.
*/
derivedProducts.push( 'PPCP' );
apiModules.push( PAYPAL_PRODUCTS.ACDC );
if ( products?.includes( PRODUCT_TYPES.SUBSCRIPTIONS ) ) {
options.useSubscriptions = true;
}
if ( canUseVaulting ) {
apiModules.push( PAYPAL_PRODUCTS.VAULTING );
}
}
if ( canUseVaulting ) {
derivedProducts.push( 'ADVANCED_VAULTING' );
}
options.useCardPayments = cardPaymentsEligibleAndSelected;
return derivedProducts;
return { products: apiModules, options };
};

View file

@ -0,0 +1,181 @@
import '@testing-library/jest-dom';
import { PRODUCT_TYPES } from './configuration';
import { determineProductsAndCaps } from './selectors';
describe( 'determineProductsAndCaps selector [casual seller]', () => {
const testCases = [
{
name: 'should return EXPRESS_CHECKOUT when card payments are not available',
state: {
data: {
isCasualSeller: true,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: false, canUseVaulting: false },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should return EXPRESS_CHECKOUT when optional payment methods are disabled',
state: {
data: {
isCasualSeller: true,
areOptionalPaymentMethodsEnabled: false,
},
flags: { canUseCardPayments: true, canUseVaulting: false },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should return EXPRESS_CHECKOUT for casual sellers with card payments',
state: {
data: {
isCasualSeller: true,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: true, canUseVaulting: false },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: true },
},
},
{
name: 'should return EXPRESS_CHECKOUT and ADVANCED_VAULTING when card payments are not available but vaulting is',
state: {
data: {
isCasualSeller: true,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: false, canUseVaulting: true },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should ignore SUBSCRIPTION product for casual sellers',
state: {
data: {
isCasualSeller: true,
areOptionalPaymentMethodsEnabled: true,
products: [ PRODUCT_TYPES.SUBSCRIPTIONS ],
},
flags: { canUseCardPayments: false, canUseVaulting: true },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
];
test.each( testCases )( '$name', ( { state, expected } ) => {
const result = determineProductsAndCaps( state );
expect( result ).toEqual( expected );
} );
} );
describe( 'determineProductsAndCaps selector [business seller]', () => {
const testCases = [
{
name: 'should return EXPRESS_CHECKOUT when card payments are not available',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: false, canUseVaulting: false },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should return EXPRESS_CHECKOUT when optional payment methods are disabled',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: false,
},
flags: { canUseCardPayments: true, canUseVaulting: false },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should return PPCP for business merchants with card payments',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: true, canUseVaulting: false },
},
expected: {
products: [ 'PPCP' ],
options: { useSubscriptions: false, useCardPayments: true },
},
},
{
name: 'should include ADVANCED_VAULTING when vaulting is available',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: true,
},
flags: { canUseCardPayments: true, canUseVaulting: true },
},
expected: {
products: [ 'PPCP', 'ADVANCED_VAULTING' ],
options: { useSubscriptions: false, useCardPayments: true },
},
},
{
name: 'should return EXPRESS_CHECKOUT and ADVANCED_VAULTING when card payments are not available but vaulting is',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: true,
products: [ PRODUCT_TYPES.VIRTUAL ],
},
flags: { canUseCardPayments: false, canUseVaulting: true },
},
expected: {
products: [ 'EXPRESS_CHECKOUT' ],
options: { useSubscriptions: false, useCardPayments: false },
},
},
{
name: 'should enable the SUBSCRIPTIONS option when a business seller selects the subscriptions-product',
state: {
data: {
isCasualSeller: false,
areOptionalPaymentMethodsEnabled: true,
products: [ PRODUCT_TYPES.SUBSCRIPTIONS ],
},
flags: { canUseCardPayments: true, canUseVaulting: true },
},
expected: {
products: [ 'PPCP', 'ADVANCED_VAULTING' ],
options: { useSubscriptions: true, useCardPayments: true },
},
},
];
test.each( testCases )( '$name', ( { state, expected } ) => {
const result = determineProductsAndCaps( state );
expect( result ).toEqual( expected );
} );
} );

View file

@ -30,7 +30,7 @@ const ACTIVITIES = {
export const useHandleOnboardingButton = ( isSandbox ) => {
const { sandboxOnboardingUrl } = CommonHooks.useSandbox();
const { productionOnboardingUrl } = CommonHooks.useProduction();
const products = OnboardingHooks.useDetermineProducts();
const { products, options } = OnboardingHooks.useDetermineProducts();
const { startActivity } = CommonHooks.useBusyState();
const { authenticateWithOAuth } = CommonHooks.useAuthentication();
const [ onboardingUrl, setOnboardingUrl ] = useState( '' );
@ -43,7 +43,7 @@ export const useHandleOnboardingButton = ( isSandbox ) => {
if ( isSandbox ) {
res = await sandboxOnboardingUrl();
} else {
res = await productionOnboardingUrl( products );
res = await productionOnboardingUrl( products, options );
}
if ( res.success && res.data ) {

View file

@ -82,6 +82,16 @@ class LoginLinkRestEndpoint extends RestEndpoint {
return array_map( 'sanitize_text_field', $products );
},
),
'options' => array(
'requires' => false,
'type' => 'array',
'items' => array(
'type' => 'bool',
),
'sanitize_callback' => function ( $flags ) {
return array_map( array( $this, 'to_boolean' ), $flags );
},
),
),
)
);
@ -97,9 +107,10 @@ class LoginLinkRestEndpoint extends RestEndpoint {
public function get_login_url( WP_REST_Request $request ) : WP_REST_Response {
$use_sandbox = $request->get_param( 'useSandbox' );
$products = $request->get_param( 'products' );
$flags = (array) $request->get_param( 'options' );
try {
$url = $this->url_generator->generate( $products, $use_sandbox );
$url = $this->url_generator->generate( $products, $flags, $use_sandbox );
return $this->return_success( $url );
} catch ( \Exception $e ) {

View file

@ -82,12 +82,13 @@ class ConnectionUrlGenerator {
*
* @param array $products An array of product identifiers to include in the sign-up process.
* These determine the PayPal onboarding experience.
* @param array $flags Onboarding choices that will customize the ISU payload.
* @param bool $use_sandbox Whether to generate a sandbox URL.
*
* @return string The generated PayPal onboarding URL.
*/
public function generate( array $products = array(), bool $use_sandbox = false ) : string {
$cache_key = $this->cache_key( $products, $use_sandbox );
public function generate( array $products = array(), array $flags = array(), bool $use_sandbox = false ) : string {
$cache_key = $this->cache_key( $products, $flags, $use_sandbox );
$user_id = get_current_user_id();
$onboarding_url = $this->url_manager->get( $cache_key, $user_id );
$cached_url = $this->try_get_from_cache( $onboarding_url, $cache_key );
@ -100,7 +101,7 @@ class ConnectionUrlGenerator {
$this->logger->info( 'Generating onboarding URL for: ' . $cache_key );
$url = $this->generate_new_url( $use_sandbox, $products, $onboarding_url, $cache_key );
$url = $this->generate_new_url( $use_sandbox, $products, $flags, $onboarding_url, $cache_key );
if ( $url ) {
$this->persist_url( $onboarding_url, $url );
@ -112,18 +113,28 @@ class ConnectionUrlGenerator {
/**
* Generates a cache key from the environment and sorted product array.
*
* Q: Why do we cache the connection URL?
* A: The URL is generated by a partner-referrals API, i.e. it requires a
* remote request; caching the response avoids unnecessary API calls.
*
* @param array $products Product identifiers that are part of the cache key.
* @param array $flags Onboarding flags.
* @param bool $for_sandbox Whether the cache contains a sandbox URL.
*
* @return string The cache key, defining the product list and environment.
*/
protected function cache_key( array $products, bool $for_sandbox ) : string {
protected function cache_key( array $products, array $flags, bool $for_sandbox ) : string {
$environment = $for_sandbox ? 'sandbox' : 'production';
// Sort products alphabetically, to improve cache implementation.
sort( $products );
return $environment . '-' . implode( '-', $products );
// Extract the names of active flags.
$active_flags = array_keys( array_filter( $flags ) );
return strtolower(
$environment . '-' . implode( '-', $products ) . '-' . implode( '-', $active_flags )
);
}
/**
@ -162,12 +173,13 @@ class ConnectionUrlGenerator {
*
* @param bool $for_sandbox Whether to generate a sandbox URL.
* @param array $products The products array.
* @param array $flags Onboarding flags.
* @param OnboardingUrl $onboarding_url The OnboardingUrl object.
* @param string $cache_key The cache key.
*
* @return string The generated URL or an empty string on failure.
*/
protected function generate_new_url( bool $for_sandbox, array $products, OnboardingUrl $onboarding_url, string $cache_key ) : string {
protected function generate_new_url( bool $for_sandbox, array $products, array $flags, OnboardingUrl $onboarding_url, string $cache_key ) : string {
$query_args = array( 'displayMode' => 'minibrowser' );
$onboarding_url->init();
@ -179,7 +191,7 @@ class ConnectionUrlGenerator {
return '';
}
$data = $this->prepare_referral_data( $products, $onboarding_token );
$data = $this->prepare_referral_data( $products, $flags, $onboarding_token );
try {
$referral = $this->partner_referrals->get_value( $for_sandbox );
@ -197,16 +209,18 @@ class ConnectionUrlGenerator {
* Prepares the referral data.
*
* @param array $products The products array.
* @param array $flags Onboarding flags.
* @param string $onboarding_token The onboarding token.
*
* @return array The prepared referral data.
*/
protected function prepare_referral_data( array $products, string $onboarding_token ) : array {
$data = $this->referrals_data
->with_products( $products )
->data();
return $this->referrals_data->append_onboarding_token( $data, $onboarding_token );
protected function prepare_referral_data( array $products, array $flags, string $onboarding_token ) : array {
return $this->referrals_data->data(
$products,
$onboarding_token,
(bool) ( $flags['useSubscriptions'] ?? false ),
(bool) ( $flags['useCardPayments'] ?? false )
);
}
/**