From b1aed56e4a8625553555baf7608629ab1ed743cd Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Thu, 16 Oct 2025 18:11:46 -0300 Subject: [PATCH 1/3] Improves the error message shown in checkout when a saved payment method is invalid --- changelog.txt | 1 + .../abstract-wc-stripe-payment-gateway.php | 16 ++++++++++++++ includes/class-wc-stripe-order-helper.php | 1 + includes/class-wc-stripe.php | 1 + .../class-wc-stripe-upe-payment-gateway.php | 14 ++++++++++++ includes/wc-stripe-functions.php | 22 +++++++++++++++++++ readme.txt | 1 + 7 files changed, 56 insertions(+) create mode 100644 includes/wc-stripe-functions.php diff --git a/changelog.txt b/changelog.txt index 4bfe86f61e..ef241bb031 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ *** Changelog *** = 10.1.0 - xxxx-xx-xx = +* Fix - Improves the error message shown in checkout when a saved payment method is no longer valid * Dev - Add track events when clicking the "Reconnect to Stripe" button (both in the settings page and the admin notice) * Update - Removes unnecessary legacy checkout gateway instantiations and UPE disablement code * Dev - Renames previous Order Helper class methods to use the `_id` suffix diff --git a/includes/abstracts/abstract-wc-stripe-payment-gateway.php b/includes/abstracts/abstract-wc-stripe-payment-gateway.php index baaf721506..2632169a89 100644 --- a/includes/abstracts/abstract-wc-stripe-payment-gateway.php +++ b/includes/abstracts/abstract-wc-stripe-payment-gateway.php @@ -21,6 +21,13 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC { use WC_Stripe_Subscriptions_Trait; use WC_Stripe_Pre_Orders_Trait; + /** + * Error string returned by Stripe when a PaymentMethod is detached. + * + * @var string + */ + protected const DETACHED_PAYMENT_METHOD_ERROR_STRING = 'The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment'; + /** * The delay between retries. * @@ -163,6 +170,15 @@ public function is_retryable_error( $error ) { return false; } + // Don't retry if the error indicates that a PaymentMethod is detached. + if ( isset( $error->type ) + && 'invalid_request_error' == $error->type + && isset( $error->message ) + && str_contains( $error->message, self::DETACHED_PAYMENT_METHOD_ERROR_STRING ) + ) { + return false; + } + return ( 'invalid_request_error' === $error->type || 'idempotency_error' === $error->type || diff --git a/includes/class-wc-stripe-order-helper.php b/includes/class-wc-stripe-order-helper.php index c363fd6981..74d7210816 100644 --- a/includes/class-wc-stripe-order-helper.php +++ b/includes/class-wc-stripe-order-helper.php @@ -863,6 +863,7 @@ public function validate_minimum_order_amount( WC_Order $order ): void { * @return bool A flag that indicates whether the order is already locked. */ public function lock_order_payment( WC_Order $order ): bool { + return false; if ( $this->is_order_payment_locked( $order ) ) { // If the order is already locked, return true. return true; diff --git a/includes/class-wc-stripe.php b/includes/class-wc-stripe.php index 4cae23488c..6d6331c22c 100644 --- a/includes/class-wc-stripe.php +++ b/includes/class-wc-stripe.php @@ -120,6 +120,7 @@ public function init() { require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-feature-flags.php'; } + require_once WC_STRIPE_PLUGIN_PATH . '/includes/wc-stripe-functions.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-upe-compatibility.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-co-branded-cc-compatibility.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-exception.php'; 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 7d2040708b..c7b83359b3 100644 --- a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php +++ b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php @@ -2463,6 +2463,20 @@ private function get_payment_intent_error_message( $payment_intent ) { ); } + // This error indicates that the saved payment method is no longer valid. + // This can happen if the payment method was removed in Stripe dashboard, or if it expired. + // In this case, we want to show a specific message to the user. + if ( isset( $payment_intent->error->type ) + && 'invalid_request_error' === $payment_intent->error->type + && isset( $payment_intent->error->message ) + && str_contains( $payment_intent->error->message, self::DETACHED_PAYMENT_METHOD_ERROR_STRING ) + ) { + return __( + 'This saved payment method is no longer valid. It might be expired, removed, or broken. Please choose a different payment method.', + 'woocommerce-gateway-stripe' + ); + } + return $payment_intent->error->message; } diff --git a/includes/wc-stripe-functions.php b/includes/wc-stripe-functions.php new file mode 100644 index 0000000000..d05d6989d0 --- /dev/null +++ b/includes/wc-stripe-functions.php @@ -0,0 +1,22 @@ + Date: Thu, 16 Oct 2025 18:15:43 -0300 Subject: [PATCH 2/3] Revert debug change --- includes/class-wc-stripe-order-helper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/class-wc-stripe-order-helper.php b/includes/class-wc-stripe-order-helper.php index 74d7210816..c363fd6981 100644 --- a/includes/class-wc-stripe-order-helper.php +++ b/includes/class-wc-stripe-order-helper.php @@ -863,7 +863,6 @@ public function validate_minimum_order_amount( WC_Order $order ): void { * @return bool A flag that indicates whether the order is already locked. */ public function lock_order_payment( WC_Order $order ): bool { - return false; if ( $this->is_order_payment_locked( $order ) ) { // If the order is already locked, return true. return true; From 44602b6e1196fe8e78b38fbb336e4ae8420fcdbb Mon Sep 17 00:00:00 2001 From: Wesley Rosa Date: Fri, 7 Nov 2025 18:17:47 -0300 Subject: [PATCH 3/3] Removing str_contains polyfill --- includes/class-wc-stripe.php | 1 - includes/wc-stripe-functions.php | 22 ---------------------- 2 files changed, 23 deletions(-) delete mode 100644 includes/wc-stripe-functions.php diff --git a/includes/class-wc-stripe.php b/includes/class-wc-stripe.php index f7a8e2b666..a92196e66e 100644 --- a/includes/class-wc-stripe.php +++ b/includes/class-wc-stripe.php @@ -120,7 +120,6 @@ public function init() { require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-feature-flags.php'; } - require_once WC_STRIPE_PLUGIN_PATH . '/includes/wc-stripe-functions.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-upe-compatibility.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-co-branded-cc-compatibility.php'; require_once WC_STRIPE_PLUGIN_PATH . '/includes/class-wc-stripe-exception.php'; diff --git a/includes/wc-stripe-functions.php b/includes/wc-stripe-functions.php deleted file mode 100644 index d05d6989d0..0000000000 --- a/includes/wc-stripe-functions.php +++ /dev/null @@ -1,22 +0,0 @@ -