Skip to content

Commit

Permalink
Avoid PMME init for unavailable BNPL use-cases (#10424)
Browse files Browse the repository at this point in the history
  • Loading branch information
timur27 authored Feb 21, 2025
1 parent 58a3f94 commit b5c7cf9
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 46 deletions.
4 changes: 4 additions & 0 deletions changelog/fix-redundant-pmme-init
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Avoid PMME init for unavailable BNPL use-cases.
9 changes: 9 additions & 0 deletions client/cart/blocks/product-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,21 @@ const ProductDetail = ( { cart, context } ) => {
wcSettings.currency.precision
);

if ( ! window.wcpayStripeSiteMessaging ) {
return null;
}

const {
country,
paymentMethods,
currencyCode,
shouldInitializePMME,
} = window.wcpayStripeSiteMessaging;

if ( ! shouldInitializePMME ) {
return null;
}

const amount = parseInt( cartTotal, 10 ) || 0;

const options = {
Expand Down
57 changes: 26 additions & 31 deletions client/product-details/bnpl-site-messaging/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ export const initializeBnplSiteMessaging = async () => {
paymentMethods,
currencyCode,
isCart,
isCartBlock,
cartTotal,
isBnplAvailable,
shouldShowPMME,
} = window.wcpayStripeSiteMessaging;

let amount;
Expand All @@ -64,48 +63,44 @@ export const initializeBnplSiteMessaging = async () => {
'payment-method-message'
);

if ( isCart || isCartBlock ) {
if ( isCart ) {
amount = parseInt( cartTotal, 10 ) || 0;
elementLocation = 'bnplClassicCart';
} else {
amount = parseInt( productVariations.base_product.amount, 10 ) || 0;

if ( ! isBnplAvailable ) {
if ( ! shouldShowPMME ) {
paymentMessageContainer.style.setProperty( 'display', 'none' );
}
}

let paymentMessageElement;

if ( ! isCartBlock ) {
const api = new WCPayAPI(
{
publishableKey: publishableKey,
accountId: accountId,
locale: locale,
},
apiRequest
);
const api = new WCPayAPI(
{
publishableKey: publishableKey,
accountId: accountId,
locale: locale,
},
apiRequest
);

const options = {
amount: amount,
currency: currencyCode || 'USD',
paymentMethodTypes: paymentMethods || [],
countryCode: country, // Customer's country or base country of the store.
};
const options = {
amount: amount,
currency: currencyCode || 'USD',
paymentMethodTypes: paymentMethods || [],
countryCode: country, // Customer's country or base country of the store.
};

const elementsOptions = {
appearance: await initializeAppearance( api, elementLocation ),
fonts: getFontRulesFromPage(),
};
const elementsOptions = {
appearance: await initializeAppearance( api, elementLocation ),
fonts: getFontRulesFromPage(),
};

const stripe = await api.getStripe();
const stripe = await api.getStripe();

paymentMessageElement = stripe
.elements( elementsOptions )
.create( 'paymentMethodMessaging', options );
paymentMessageElement.mount( '#payment-method-message' );
}
const paymentMessageElement = stripe
.elements( elementsOptions )
.create( 'paymentMethodMessaging', options );
paymentMessageElement.mount( '#payment-method-message' );

// This function converts relative units (rem/em) to pixels based on the current font size.
function convertToPixels( value, baseFontSize ) {
Expand Down
12 changes: 11 additions & 1 deletion client/product-details/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ jQuery( async function ( $ ) {
return;
}

const { shouldInitializePMME } = window.wcpayStripeSiteMessaging;

if ( ! shouldInitializePMME ) {
const paymentMessageContainer = document.getElementById(
'payment-method-message'
);
paymentMessageContainer.style.setProperty( 'display', 'none' );
return;
}

const {
productVariations,
productId,
Expand Down Expand Up @@ -81,7 +91,7 @@ jQuery( async function ( $ ) {
if ( totalAmount <= 0 || ! currency ) {
return;
}
bnplPaymentMessageElement.update( { amount: totalAmount, currency } );
bnplPaymentMessageElement?.update( { amount: totalAmount, currency } );
};

/**
Expand Down
29 changes: 15 additions & 14 deletions includes/class-wc-payments-payment-method-messaging-element.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,26 +126,27 @@ public function init() {
$country = empty( $billing_country ) ? $store_country : $billing_country;

$script_data = [
'productId' => 'base_product',
'productVariations' => $product_variations,
'country' => $country,
'locale' => WC_Payments_Utils::convert_to_stripe_locale( get_locale() ),
'accountId' => $this->account->get_stripe_account_id(),
'publishableKey' => $this->account->get_publishable_key( WC_Payments::mode()->is_test() ),
'paymentMethods' => array_values( $bnpl_payment_methods ),
'currencyCode' => $currency_code,
'isCart' => is_cart(),
'isCartBlock' => $is_cart_block,
'cartTotal' => WC_Payments_Utils::prepare_amount( $cart_total, $currency_code ),
'nonce' => [
'productId' => 'base_product',
'productVariations' => $product_variations,
'country' => $country,
'locale' => WC_Payments_Utils::convert_to_stripe_locale( get_locale() ),
'accountId' => $this->account->get_stripe_account_id(),
'publishableKey' => $this->account->get_publishable_key( WC_Payments::mode()->is_test() ),
'paymentMethods' => array_values( $bnpl_payment_methods ),
'currencyCode' => $currency_code,
'isCart' => is_cart(),
'isCartBlock' => $is_cart_block,
'cartTotal' => WC_Payments_Utils::prepare_amount( $cart_total, $currency_code ),
'nonce' => [
'get_cart_total' => wp_create_nonce( 'wcpay-get-cart-total' ),
'is_bnpl_available' => wp_create_nonce( 'wcpay-is-bnpl-available' ),
],
'wcAjaxUrl' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
'wcAjaxUrl' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
'shouldInitializePMME' => WC_Payments_Utils::is_any_bnpl_supporting_country( array_values( $bnpl_payment_methods ), $country, $currency_code ),
];

if ( $product ) {
$script_data['isBnplAvailable'] = WC_Payments_Utils::is_any_bnpl_method_available( array_values( $bnpl_payment_methods ), $country, $currency_code, $product_price );
$script_data['shouldShowPMME'] = WC_Payments_Utils::is_any_bnpl_method_available( array_values( $bnpl_payment_methods ), $country, $currency_code, $product_price );
}

// Create script tag with config.
Expand Down
19 changes: 19 additions & 0 deletions includes/class-wc-payments-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,25 @@ public static function is_any_bnpl_method_available( array $enabled_methods, str
return false;
}

/**
* Check if any BNPL method is available for a given country.
*
* @param array $enabled_methods Array of enabled BNPL methods.
* @param string $country_code Country code.
* @param string $currency_code Currency code.
* @return bool True if any BNPL method is available, false otherwise.
*/
public static function is_any_bnpl_supporting_country( array $enabled_methods, string $country_code, string $currency_code ): bool {
foreach ( $enabled_methods as $method ) {
$limits = self::get_bnpl_limits_per_currency( $method );
if ( isset( $limits[ $currency_code ][ $country_code ] ) ) {
return true;
}
}

return false;
}

/**
* Saves the minimum amount required for transactions in a given currency.
*
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/test-class-wc-payments-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,35 @@ public function test_is_store_api_request_with_url_with_no_path() {
$this->assertFalse( WC_Payments_Utils::is_store_api_request() );
}

public function test_is_any_bnpl_supporting_country() {
// Test supported country and currency combination (US with USD).
$this->assertTrue(
WC_Payments_Utils::is_any_bnpl_supporting_country(
[ 'afterpay_clearpay', 'klarna' ],
'US',
'USD'
)
);

// Test unsupported country and currency combination.
$this->assertFalse(
WC_Payments_Utils::is_any_bnpl_supporting_country(
[ 'afterpay_clearpay', 'klarna' ],
'CN',
'CNY'
)
);

// Test with empty enabled methods.
$this->assertFalse(
WC_Payments_Utils::is_any_bnpl_supporting_country(
[],
'US',
'USD'
)
);
}

public function test_is_any_bnpl_method_available() {
// Price within range for Afterpay/Clearpay in the US.
$this->assertTrue(
Expand Down

0 comments on commit b5c7cf9

Please sign in to comment.