Skip to content

Commit f34c48c

Browse files
asumaranbborman22
andauthored
Check payment method is available before rendering it (#9378)
Co-authored-by: Brian Borman <[email protected]>
1 parent f87ea8e commit f34c48c

File tree

6 files changed

+153
-27
lines changed

6 files changed

+153
-27
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: fix
3+
4+
Check payment method is available before rendering it.

client/express-checkout/blocks/components/express-checkout-component.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,7 @@ const adjustButtonHeights = ( buttonOptions, expressPaymentMethod ) => {
4040
// Apple Pay has a nearly imperceptible height difference. We increase it by 1px here.
4141
if ( buttonOptions.buttonTheme.applePay === 'black' ) {
4242
if ( expressPaymentMethod === 'applePay' ) {
43-
// The maximum allowed size is 55px.
44-
buttonOptions.buttonHeight = Math.min(
45-
buttonOptions.buttonHeight + 0.4,
46-
55
47-
);
43+
buttonOptions.buttonHeight = buttonOptions.buttonHeight + 0.4;
4844
}
4945
}
5046

@@ -56,6 +52,11 @@ const adjustButtonHeights = ( buttonOptions, expressPaymentMethod ) => {
5652
buttonOptions.buttonHeight = buttonOptions.buttonHeight - 2;
5753
}
5854

55+
// Clamp the button height to the allowed range 40px to 55px.
56+
buttonOptions.buttonHeight = Math.max(
57+
40,
58+
Math.min( buttonOptions.buttonHeight, 55 )
59+
);
5960
return buttonOptions;
6061
};
6162

client/express-checkout/blocks/express-checkout-element.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@
1414
margin: 24px 0 !important;
1515
height: 20px;
1616
}
17+
18+
.wc-block-components-express-payment
19+
.wc-block-components-express-payment__event-buttons
20+
> li {
21+
margin-left: 1px !important;
22+
width: 99% !important;
23+
}

client/express-checkout/blocks/index.js

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getConfig } from 'wcpay/utils/checkout';
66
import ApplePayPreview from './components/apple-pay-preview';
77
import ExpressCheckoutContainer from './components/express-checkout-container';
88
import GooglePayPreview from './components/google-pay-preview';
9+
import { checkPaymentMethodIsAvailable } from '../utils/checkPaymentMethodIsAvailable';
910

1011
const expressCheckoutElementApplePay = ( api ) => ( {
1112
paymentMethodId: PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT,
@@ -17,35 +18,41 @@ const expressCheckoutElementApplePay = ( api ) => ( {
1718
supports: {
1819
features: getConfig( 'features' ),
1920
},
20-
canMakePayment: () => {
21+
canMakePayment: ( { cart } ) => {
2122
if ( typeof wcpayExpressCheckoutParams === 'undefined' ) {
2223
return false;
2324
}
2425

25-
return true;
26+
return new Promise( ( resolve ) => {
27+
checkPaymentMethodIsAvailable( 'applePay', cart, resolve );
28+
} );
2629
},
2730
} );
2831

29-
const expressCheckoutElementGooglePay = ( api ) => ( {
30-
paymentMethodId: PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT,
31-
name: PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT + '_googlePay',
32-
content: (
33-
<ExpressCheckoutContainer
34-
api={ api }
35-
expressPaymentMethod="googlePay"
36-
/>
37-
),
38-
edit: <GooglePayPreview />,
39-
supports: {
40-
features: getConfig( 'features' ),
41-
},
42-
canMakePayment: () => {
43-
if ( typeof wcpayExpressCheckoutParams === 'undefined' ) {
44-
return false;
45-
}
32+
const expressCheckoutElementGooglePay = ( api ) => {
33+
return {
34+
paymentMethodId: PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT,
35+
name: PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT + '_googlePay',
36+
content: (
37+
<ExpressCheckoutContainer
38+
api={ api }
39+
expressPaymentMethod="googlePay"
40+
/>
41+
),
42+
edit: <GooglePayPreview />,
43+
supports: {
44+
features: getConfig( 'features' ),
45+
},
46+
canMakePayment: ( { cart } ) => {
47+
if ( typeof wcpayExpressCheckoutParams === 'undefined' ) {
48+
return false;
49+
}
4650

47-
return true;
48-
},
49-
} );
51+
return new Promise( ( resolve ) => {
52+
checkPaymentMethodIsAvailable( 'googlePay', cart, resolve );
53+
} );
54+
},
55+
};
56+
};
5057

5158
export { expressCheckoutElementApplePay, expressCheckoutElementGooglePay };
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import ReactDOM from 'react-dom';
5+
import { ExpressCheckoutElement, Elements } from '@stripe/react-stripe-js';
6+
import { memoize } from 'lodash';
7+
8+
/**
9+
* Internal dependencies
10+
*/
11+
import { isLinkEnabled } from 'wcpay/checkout/utils/upe';
12+
import request from 'wcpay/checkout/utils/request';
13+
import WCPayAPI from 'wcpay/checkout/api';
14+
import { getUPEConfig } from 'wcpay/utils/checkout';
15+
16+
export const checkPaymentMethodIsAvailable = memoize(
17+
( paymentMethod, cart, resolve ) => {
18+
const root = ReactDOM.createRoot(
19+
document.getElementById(
20+
`express-checkout-check-availability-container-${ paymentMethod }`
21+
)
22+
);
23+
24+
const api = new WCPayAPI(
25+
{
26+
publishableKey: getUPEConfig( 'publishableKey' ),
27+
accountId: getUPEConfig( 'accountId' ),
28+
forceNetworkSavedCards: getUPEConfig(
29+
'forceNetworkSavedCards'
30+
),
31+
locale: getUPEConfig( 'locale' ),
32+
isStripeLinkEnabled: isLinkEnabled(
33+
getUPEConfig( 'paymentMethodsConfig' )
34+
),
35+
},
36+
request
37+
);
38+
39+
root.render(
40+
<Elements
41+
stripe={ api.loadStripe() }
42+
options={ {
43+
mode: 'payment',
44+
paymentMethodCreation: 'manual',
45+
amount: Number( cart.cartTotals.total_price ),
46+
currency: cart.cartTotals.currency_code.toLowerCase(),
47+
} }
48+
>
49+
<ExpressCheckoutElement
50+
options={ {
51+
paymentMethods: {
52+
amazonPay: 'never',
53+
applePay:
54+
paymentMethod === 'applePay'
55+
? 'always'
56+
: 'never',
57+
googlePay:
58+
paymentMethod === 'googlePay'
59+
? 'always'
60+
: 'never',
61+
link: 'never',
62+
paypal: 'never',
63+
},
64+
} }
65+
onReady={ ( event ) => {
66+
let canMakePayment = false;
67+
if ( event.availablePaymentMethods ) {
68+
canMakePayment =
69+
event.availablePaymentMethods[ paymentMethod ];
70+
}
71+
resolve( canMakePayment );
72+
root.unmount();
73+
} }
74+
/>
75+
</Elements>
76+
);
77+
}
78+
);

includes/express-checkout/class-wc-payments-express-checkout-button-display-handler.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ public function init() {
9595
$is_woopay_enabled = WC_Payments_Features::is_woopay_enabled();
9696
$is_payment_request_enabled = 'yes' === $this->gateway->get_option( 'payment_request' );
9797

98+
if ( $is_payment_request_enabled ) {
99+
$this->add_html_container_for_test_express_checkout_buttons();
100+
}
101+
98102
if ( $is_woopay_enabled || $is_payment_request_enabled ) {
99103
add_action( 'wc_ajax_wcpay_add_to_cart', [ $this->express_checkout_ajax_handler, 'ajax_add_to_cart' ] );
100104
add_action( 'wc_ajax_wcpay_empty_cart', [ $this->express_checkout_ajax_handler, 'ajax_empty_cart' ] );
@@ -174,6 +178,31 @@ public function add_order_attribution_inputs() {
174178
echo '<wc-order-attribution-inputs id="wcpay-express-checkout__order-attribution-inputs"></wc-order-attribution-inputs>';
175179
}
176180

181+
182+
/**
183+
* Add HTML containers to be used by the Express Checkout buttons that check if the payment method is available.
184+
*
185+
* @return void
186+
*/
187+
private function add_html_container_for_test_express_checkout_buttons() {
188+
add_filter(
189+
'the_content',
190+
function ( $content ) {
191+
$supported_payment_methods = [ 'applePay' , 'googlePay' ];
192+
// Restrict adding these HTML containers to only the necessary pages.
193+
if ( $this->express_checkout_helper->is_checkout() || $this->express_checkout_helper->is_cart() ) {
194+
foreach ( $supported_payment_methods as $value ) {
195+
// The inline styles ensure that the HTML elements don't occupy space on the page.
196+
$content = '<div id="express-checkout-check-availability-container-' . $value . '" style="height: 0; float:left; opacity: 0; pointer-events: none;"></div>' . $content;
197+
}
198+
}
199+
return $content;
200+
},
201+
10,
202+
1
203+
);
204+
}
205+
177206
/**
178207
* Check if the pay-for-order flow is supported.
179208
*

0 commit comments

Comments
 (0)