diff --git a/changelog.txt b/changelog.txt
index 8ed1b7b8d..be8ab0db8 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -10,6 +10,8 @@
* Fix - Prevent marking orders on-hold with order note "Process order to take payment" when the payment has failed.
* Fix - Fix payment methods count on settings page.
* Tweak - Add error logging in ECE critical Ajax requests.
+* Add - Add support for Stripe Link payments via the new Stripe Checkout Element on the block cart and block checkout pages.
+* Add - Add support for Stripe Link payments via the new Stripe Checkout Element on the product, cart, checkout and pay for order pages.
= 8.8.0 - 2024-10-17 =
* Fix - Update URL and path constants to support use of symlinked plugin.
diff --git a/client/blocks/express-checkout/express-checkout-container.js b/client/blocks/express-checkout/express-checkout-container.js
index c861948e7..ace659c7c 100644
--- a/client/blocks/express-checkout/express-checkout-container.js
+++ b/client/blocks/express-checkout/express-checkout-container.js
@@ -1,14 +1,18 @@
import React from 'react';
import { Elements } from '@stripe/react-stripe-js';
import ExpressCheckoutComponent from './express-checkout-component';
+import { getPaymentMethodTypesForExpressMethod } from 'wcstripe/express-checkout/utils';
export const ExpressCheckoutContainer = ( props ) => {
- const { stripe, billing } = props;
+ const { stripe, billing, expressPaymentMethod } = props;
const options = {
mode: 'payment',
paymentMethodCreation: 'manual',
amount: billing.cartTotal.value,
currency: billing.currency.code.toLowerCase(),
+ paymentMethodTypes: getPaymentMethodTypesForExpressMethod(
+ expressPaymentMethod
+ ),
};
return (
diff --git a/client/blocks/express-checkout/index.js b/client/blocks/express-checkout/index.js
index 24c642046..18aafc81b 100644
--- a/client/blocks/express-checkout/index.js
+++ b/client/blocks/express-checkout/index.js
@@ -4,6 +4,7 @@ import { PAYMENT_METHOD_EXPRESS_CHECKOUT_ELEMENT } from './constants';
import { ExpressCheckoutContainer } from './express-checkout-container';
import ApplePayPreview from './apple-pay-preview';
import GooglePayPreview from './google-pay-preview';
+import StripeLinkPreview from './stripe-link-preview';
import { loadStripe } from 'wcstripe/blocks/load-stripe';
import { getBlocksConfiguration } from 'wcstripe/blocks/utils';
import { checkPaymentMethodIsAvailable } from 'wcstripe/express-checkout/utils/check-payment-method-availability';
@@ -66,4 +67,34 @@ const expressCheckoutElementsApplePay = ( api ) => ( {
},
} );
-export { expressCheckoutElementsGooglePay, expressCheckoutElementsApplePay };
+const expressCheckoutElementsStripeLink = ( api ) => ( {
+ name: PAYMENT_METHOD_EXPRESS_CHECKOUT_ELEMENT + '_link',
+ content: (
+
+ ),
+ edit: ,
+ canMakePayment: ( { cart } ) => {
+ // eslint-disable-next-line camelcase
+ if ( typeof wc_stripe_express_checkout_params === 'undefined' ) {
+ return false;
+ }
+
+ return new Promise( ( resolve ) => {
+ checkPaymentMethodIsAvailable( 'link', api, cart, resolve );
+ } );
+ },
+ paymentMethodId: PAYMENT_METHOD_EXPRESS_CHECKOUT_ELEMENT,
+ supports: {
+ features: getBlocksConfiguration()?.supports ?? [],
+ },
+} );
+
+export {
+ expressCheckoutElementsGooglePay,
+ expressCheckoutElementsApplePay,
+ expressCheckoutElementsStripeLink,
+};
diff --git a/client/blocks/express-checkout/stripe-link-preview/icon.svg b/client/blocks/express-checkout/stripe-link-preview/icon.svg
new file mode 100644
index 000000000..f9f427828
--- /dev/null
+++ b/client/blocks/express-checkout/stripe-link-preview/icon.svg
@@ -0,0 +1,9 @@
+
diff --git a/client/blocks/express-checkout/stripe-link-preview/index.js b/client/blocks/express-checkout/stripe-link-preview/index.js
new file mode 100644
index 000000000..c71eb7e81
--- /dev/null
+++ b/client/blocks/express-checkout/stripe-link-preview/index.js
@@ -0,0 +1,11 @@
+/* eslint-disable max-len */
+import icon from './icon.svg';
+import './style.scss';
+
+const useStripeLinkPreview = () => (
+
+
+
+);
+
+export default useStripeLinkPreview;
diff --git a/client/blocks/express-checkout/stripe-link-preview/style.scss b/client/blocks/express-checkout/stripe-link-preview/style.scss
new file mode 100644
index 000000000..0aa7f3826
--- /dev/null
+++ b/client/blocks/express-checkout/stripe-link-preview/style.scss
@@ -0,0 +1,12 @@
+.stripe-link-preview {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-color: #00d66f;
+ border-radius: 5px;
+ height: 40px;
+ &:hover {
+ cursor: pointer;
+ filter: opacity(0.7);
+ }
+}
diff --git a/client/blocks/upe/index.js b/client/blocks/upe/index.js
index 7afa5306d..189fed2ca 100644
--- a/client/blocks/upe/index.js
+++ b/client/blocks/upe/index.js
@@ -11,6 +11,7 @@ import paymentRequestPaymentMethod from 'wcstripe/blocks/payment-request';
import {
expressCheckoutElementsGooglePay,
expressCheckoutElementsApplePay,
+ expressCheckoutElementsStripeLink,
} from 'wcstripe/blocks/express-checkout';
import WCStripeAPI from 'wcstripe/api';
import { getBlocksConfiguration } from 'wcstripe/blocks/utils';
@@ -97,6 +98,7 @@ if ( getBlocksConfiguration()?.isECEEnabled ) {
// Register Express Checkout Element.
registerExpressPaymentMethod( expressCheckoutElementsGooglePay( api ) );
registerExpressPaymentMethod( expressCheckoutElementsApplePay( api ) );
+ registerExpressPaymentMethod( expressCheckoutElementsStripeLink( api ) );
} else {
// Register Stripe Payment Request.
registerExpressPaymentMethod( paymentRequestPaymentMethod );
diff --git a/client/entrypoints/express-checkout/index.js b/client/entrypoints/express-checkout/index.js
index 22a7b4503..64633975c 100644
--- a/client/entrypoints/express-checkout/index.js
+++ b/client/entrypoints/express-checkout/index.js
@@ -621,7 +621,11 @@ jQuery( function ( $ ) {
};
// We don't need to initialize ECE on the checkout page now because it will be initialized by updated_checkout event.
- if ( ! getExpressCheckoutData( 'is_checkout_page' ) ) {
+ if (
+ getExpressCheckoutData( 'is_product_page' ) ||
+ getExpressCheckoutData( 'is_pay_for_order' ) ||
+ getExpressCheckoutData( 'is_cart_page' )
+ ) {
wcStripeECE.init();
}
diff --git a/client/express-checkout/utils/check-payment-method-availability.js b/client/express-checkout/utils/check-payment-method-availability.js
index b52bf23b3..a75a8aa14 100644
--- a/client/express-checkout/utils/check-payment-method-availability.js
+++ b/client/express-checkout/utils/check-payment-method-availability.js
@@ -1,6 +1,7 @@
import ReactDOM from 'react-dom';
import { ExpressCheckoutElement, Elements } from '@stripe/react-stripe-js';
import { memoize } from 'lodash';
+import { getPaymentMethodTypesForExpressMethod } from 'wcstripe/express-checkout/utils';
export const checkPaymentMethodIsAvailable = memoize(
( paymentMethod, api, cart, resolve ) => {
@@ -22,6 +23,9 @@ export const checkPaymentMethodIsAvailable = memoize(
paymentMethodCreation: 'manual',
amount: Number( cart.cartTotals.total_price ),
currency: cart.cartTotals.currency_code.toLowerCase(),
+ paymentMethodTypes: getPaymentMethodTypesForExpressMethod(
+ paymentMethod
+ ),
} }
>
{
* @param {string} paymentMethodType Payment method type Stripe ID.
* @return {Array} Array of payment method types to use with intent, for Express Checkout.
*/
-export const getExpressPaymentMethodTypes = ( paymentMethodType = null ) =>
- getPaymentMethodTypes( paymentMethodType ).filter( ( type ) =>
- [ 'link', 'paypal', 'amazon_pay', 'card' ].includes( type )
- );
+export const getExpressPaymentMethodTypes = ( paymentMethodType = null ) => {
+ const expressPaymentMethodTypes = getPaymentMethodTypes(
+ paymentMethodType
+ ).filter( ( type ) => [ 'paypal', 'amazon_pay', 'card' ].includes( type ) );
+
+ if ( isLinkEnabled() ) {
+ expressPaymentMethodTypes.push( 'link' );
+ }
+
+ return expressPaymentMethodTypes;
+};
+
+/**
+ * Fetches the payment method types required to process a payment for an Express method.
+ *
+ * @see https://docs.stripe.com/elements/express-checkout-element/accept-a-payment#enable-payment-methods - lists the method types
+ * supported and which ones are required by each Express Checkout method.
+ *
+ * @param {*} paymentMethodType The express payment method type. eg 'link', 'googlePay', or 'applePay'.
+ * @return {Array} Array of payment method types necessary to process a payment for an Express method.
+ */
+export const getPaymentMethodTypesForExpressMethod = ( paymentMethodType ) => {
+ const paymentMethodsConfig = getBlocksConfiguration()?.paymentMethodsConfig;
+ const paymentMethodTypes = [];
+
+ if ( ! paymentMethodsConfig ) {
+ return paymentMethodTypes;
+ }
+
+ // All express payment methods require 'card' payments. Add it if it's enabled.
+ if ( paymentMethodsConfig?.card !== undefined ) {
+ paymentMethodTypes.push( 'card' );
+ }
+
+ // Add 'link' payment method type if enabled and requested.
+ if (
+ paymentMethodType === 'link' &&
+ isLinkEnabled( paymentMethodsConfig )
+ ) {
+ paymentMethodTypes.push( 'link' );
+ }
+
+ return paymentMethodTypes;
+};
diff --git a/client/stripe-utils/utils.js b/client/stripe-utils/utils.js
index 302d388bf..8611acdd3 100644
--- a/client/stripe-utils/utils.js
+++ b/client/stripe-utils/utils.js
@@ -220,6 +220,8 @@ export { getStripeServerData, getErrorMessageForTypeAndCode };
* @return {boolean} True, if enabled; false otherwise.
*/
export const isLinkEnabled = ( paymentMethodsConfig ) => {
+ paymentMethodsConfig =
+ paymentMethodsConfig || getStripeServerData()?.paymentMethodsConfig;
return (
paymentMethodsConfig?.link !== undefined &&
paymentMethodsConfig?.card !== undefined
diff --git a/includes/payment-methods/class-wc-stripe-express-checkout-element.php b/includes/payment-methods/class-wc-stripe-express-checkout-element.php
index e760b4a90..007b2cd2e 100644
--- a/includes/payment-methods/class-wc-stripe-express-checkout-element.php
+++ b/includes/payment-methods/class-wc-stripe-express-checkout-element.php
@@ -214,6 +214,7 @@ public function javascript_params() {
'is_product_page' => $this->express_checkout_helper->is_product(),
'is_checkout_page' => $this->express_checkout_helper->is_checkout(),
'product' => $this->express_checkout_helper->get_product_data(),
+ 'is_cart_page' => is_cart(),
];
}
diff --git a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php
index 6b7503be3..a479eec51 100644
--- a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php
+++ b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php
@@ -1620,9 +1620,17 @@ public function set_payment_method_title_for_order( $order, $payment_method_type
if ( ! isset( $this->payment_methods[ $payment_method_type ] ) ) {
return;
}
- $payment_method = $this->payment_methods[ $payment_method_type ];
- $payment_method_title = $payment_method->get_title( $stripe_payment_method );
- $payment_method_id = $payment_method instanceof WC_Stripe_UPE_Payment_Method_CC ? $this->id : $payment_method->id;
+
+ $payment_method = $this->payment_methods[ $payment_method_type ];
+ $payment_method_id = $payment_method instanceof WC_Stripe_UPE_Payment_Method_CC ? $this->id : $payment_method->id;
+ $is_stripe_link = isset( $stripe_payment_method->type ) && WC_Stripe_Payment_Methods::LINK === $stripe_payment_method->type;
+
+ // Stripe Link uses the main gateway to process payments, however Link payments should use the title of the Link payment method.
+ if ( $is_stripe_link && isset( $this->payment_methods[ WC_Stripe_Payment_Methods::LINK ] ) ) {
+ $payment_method_title = $this->payment_methods[ WC_Stripe_Payment_Methods::LINK ]->get_title( $stripe_payment_method );
+ } else {
+ $payment_method_title = $payment_method->get_title( $stripe_payment_method );
+ }
$order->set_payment_method( $payment_method_id );
$order->set_payment_method_title( $payment_method_title );
diff --git a/readme.txt b/readme.txt
index a9e2a3df3..df8f10d0c 100644
--- a/readme.txt
+++ b/readme.txt
@@ -120,5 +120,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
* Fix - Prevent marking orders on-hold with order note "Process order to take payment" when the payment has failed.
* Fix - Fix payment methods count on settings page.
* Tweak - Add error logging in ECE critical Ajax requests.
+* Add - Add support for Stripe Link payments via the new Stripe Checkout Element on the block cart and block checkout pages.
+* Add - Add support for Stripe Link payments via the new Stripe Checkout Element on the product, cart, checkout and pay for order pages.
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).