Skip to content

Commit 2790e66

Browse files
authored
Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() (#4568)
* Basic get_all_payment_methods() implementation * Ensure we clear the new _all payment methods cache * Always send expand flags for SEPA * Refactor logic to get customer UPE tokens * Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() to use get_all_payment_methods() * Revert "Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() to use get_all_payment_methods()" This reverts commit c622d76. * Reapply "Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() to use get_all_payment_methods()" This reverts commit 2e20c28. * Update unit test to use new cache * Switch to single call to fetch payment method and add static variable cache * Make API construction more declarative * Changelog * Update and expand unit tests * Change parameter to $payment_method instead of $source * Move payment method fetch to WC_Stripe_Subscriptions_Helper * Switch to WC_Stripe_API::get_payment_method() to support src_ IDs * Update unit tests * Use counter for IDs
1 parent ddfbdcf commit 2790e66

File tree

5 files changed

+276
-106
lines changed

5 files changed

+276
-106
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* Fix - Relax customer validation that was preventing payments from the pay for order page
1616
* Fix - Prevent the PMC migration to run when the plugin is not connected to Stripe
1717
* Fix - Fixes a fatal error in the OC inbox note when the new checkout is disabled
18+
* Fix - Fix unnecessary Stripe API calls when rendering subscription details
1819

1920
= 9.8.0 - 2025-08-11 =
2021
* Add - Adds the current setting value for the Optimized Checkout to the Stripe System Status Report data

includes/compat/class-wc-stripe-subscriptions-helper.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,4 +297,41 @@ public static function build_subscription_detached_message( $subscription ) {
297297
$customer_stripe_page
298298
);
299299
}
300+
301+
/**
302+
* Helper function to get and temporarily cache the payment method details for a customer and payment method ID.
303+
*
304+
* @param string $stripe_customer_id The Stripe customer ID.
305+
* @param string $payment_method_id The Stripe payment method ID. This may be a source ID or a payment method ID.
306+
* @return object|null The payment method details or null if the payment method is not found.
307+
*/
308+
public static function get_subscription_payment_method_details( string $stripe_customer_id, string $payment_method_id ): ?object {
309+
static $cached_payment_methods = [];
310+
311+
if ( empty( $stripe_customer_id ) || empty( $payment_method_id ) ) {
312+
return null;
313+
}
314+
315+
if ( isset( $cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ] ) ) {
316+
return $cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ];
317+
}
318+
319+
$saved_payment_method = WC_Stripe_API::get_payment_method( $payment_method_id );
320+
if ( is_wp_error( $saved_payment_method ) ) {
321+
return null;
322+
}
323+
324+
if ( isset( $saved_payment_method->error ) || empty( $saved_payment_method->id ) || empty( $saved_payment_method->customer ) || $saved_payment_method->customer !== $stripe_customer_id ) {
325+
$saved_payment_method = null;
326+
}
327+
328+
// Make sure we build the array tree.
329+
if ( ! isset( $cached_payment_methods[ $stripe_customer_id ] ) ) {
330+
$cached_payment_methods[ $stripe_customer_id ] = [];
331+
}
332+
333+
$cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ] = $saved_payment_method;
334+
335+
return $saved_payment_method;
336+
}
300337
}

includes/compat/trait-wc-stripe-subscriptions.php

Lines changed: 69 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,6 @@ public function maybe_render_subscription_payment_method( $payment_method_to_dis
977977
$subscription->save();
978978
}
979979

980-
$stripe_customer = new WC_Stripe_Customer();
981980
$stripe_customer_id = $subscription->get_meta( '_stripe_customer_id', true );
982981

983982
// If we couldn't find a Stripe customer linked to the subscription, fallback to the user meta data.
@@ -1011,82 +1010,83 @@ public function maybe_render_subscription_payment_method( $payment_method_to_dis
10111010
}
10121011
}
10131012

1014-
$stripe_customer->set_id( $stripe_customer_id );
1015-
1016-
$payment_method_to_display = __( 'N/A', 'woocommerce-gateway-stripe' );
1017-
10181013
try {
1019-
// Retrieve all possible payment methods for subscriptions.
1020-
foreach ( WC_Stripe_Customer::STRIPE_PAYMENT_METHODS as $payment_method_type ) {
1021-
foreach ( $stripe_customer->get_payment_methods( $payment_method_type ) as $source ) {
1022-
if ( $source->id !== $stripe_source_id ) {
1023-
continue;
1024-
}
1014+
$saved_payment_method = WC_Stripe_Subscriptions_Helper::get_subscription_payment_method_details( $stripe_customer_id, $stripe_source_id );
10251015

1026-
// Legacy handling for Stripe Card objects. ref: https://docs.stripe.com/api/cards/object
1027-
if ( isset( $source->object ) && WC_Stripe_Payment_Methods::CARD === $source->object ) {
1028-
/* translators: 1) card brand 2) last 4 digits */
1029-
$payment_method_to_display = sprintf( __( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ), ( isset( $source->brand ) ? wc_get_credit_card_type_label( $source->brand ) : __( 'N/A', 'woocommerce-gateway-stripe' ) ), $source->last4 );
1030-
break 2;
1031-
}
1032-
1033-
switch ( $source->type ) {
1034-
case WC_Stripe_Payment_Methods::CARD:
1035-
/* translators: 1) card brand 2) last 4 digits */
1036-
$payment_method_to_display = sprintf( __( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ), ( isset( $source->card->brand ) ? wc_get_credit_card_type_label( $source->card->brand ) : __( 'N/A', 'woocommerce-gateway-stripe' ) ), $source->card->last4 );
1037-
break 3;
1038-
case WC_Stripe_Payment_Methods::SEPA_DEBIT:
1039-
/* translators: 1) last 4 digits of SEPA Direct Debit */
1040-
$payment_method_to_display = sprintf( __( 'Via SEPA Direct Debit ending in %1$s', 'woocommerce-gateway-stripe' ), $source->sepa_debit->last4 );
1041-
break 3;
1042-
case WC_Stripe_Payment_Methods::CASHAPP_PAY:
1043-
/* translators: 1) Cash App Cashtag */
1044-
$payment_method_to_display = sprintf( __( 'Via Cash App Pay (%1$s)', 'woocommerce-gateway-stripe' ), $source->cashapp->cashtag );
1045-
break 3;
1046-
case WC_Stripe_Payment_Methods::LINK:
1047-
/* translators: 1) email address associated with the Stripe Link payment method */
1048-
$payment_method_to_display = sprintf( __( 'Via Stripe Link (%1$s)', 'woocommerce-gateway-stripe' ), $source->link->email );
1049-
break 3;
1050-
case WC_Stripe_Payment_Methods::ACH:
1051-
$payment_method_to_display = sprintf(
1052-
/* translators: 1) account type (checking, savings), 2) last 4 digits of account. */
1053-
__( 'Via %1$s Account ending in %2$s', 'woocommerce-gateway-stripe' ),
1054-
ucfirst( $source->us_bank_account->account_type ),
1055-
$source->us_bank_account->last4
1056-
);
1057-
break 3;
1058-
case WC_Stripe_Payment_Methods::BECS_DEBIT:
1059-
$payment_method_to_display = sprintf(
1060-
/* translators: last 4 digits of account. */
1061-
__( 'BECS Direct Debit ending in %s', 'woocommerce-gateway-stripe' ),
1062-
$source->au_becs_debit->last4
1063-
);
1064-
break 3;
1065-
case WC_Stripe_Payment_Methods::ACSS_DEBIT:
1066-
$payment_method_to_display = sprintf(
1067-
/* translators: 1) bank name, 2) last 4 digits of account. */
1068-
__( 'Via %1$s ending in %2$s', 'woocommerce-gateway-stripe' ),
1069-
$source->acss_debit->bank_name,
1070-
$source->acss_debit->last4
1071-
);
1072-
break 3;
1073-
case WC_Stripe_Payment_Methods::BACS_DEBIT:
1074-
/* translators: 1) the Bacs Direct Debit payment method's last 4 numbers */
1075-
$payment_method_to_display = sprintf( __( 'Via Bacs Direct Debit ending in (%1$s)', 'woocommerce-gateway-stripe' ), $source->bacs_debit->last4 );
1076-
break 3;
1077-
case WC_Stripe_Payment_Methods::AMAZON_PAY:
1078-
/* translators: 1) the Amazon Pay payment method's email */
1079-
$payment_method_to_display = sprintf( __( 'Via Amazon Pay (%1$s)', 'woocommerce-gateway-stripe' ), $source->billing_details->email ?? '' );
1080-
break 3;
1081-
}
1082-
}
1016+
if ( null !== $saved_payment_method ) {
1017+
return $this->get_payment_method_to_display_for_payment_method( $saved_payment_method );
10831018
}
10841019
} catch ( WC_Stripe_Exception $e ) {
10851020
wc_add_notice( $e->getLocalizedMessage(), 'error' );
10861021
WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
10871022
}
10881023

1089-
return $payment_method_to_display;
1024+
return __( 'N/A', 'woocommerce-gateway-stripe' );
1025+
}
1026+
1027+
/**
1028+
* Helper function to get the descriptive text for a payment method or source.
1029+
*
1030+
* @param object $payment_method The payment method or source object.
1031+
* @return string The descriptive text for the payment method or source.
1032+
*/
1033+
protected function get_payment_method_to_display_for_payment_method( object $payment_method ): string {
1034+
// Legacy handling for Stripe Card objects. ref: https://docs.stripe.com/api/cards/object
1035+
if ( isset( $payment_method->object ) && WC_Stripe_Payment_Methods::CARD === $payment_method->object ) {
1036+
return sprintf(
1037+
/* translators: 1) card brand 2) last 4 digits */
1038+
__( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ),
1039+
( isset( $payment_method->brand ) ? wc_get_credit_card_type_label( $payment_method->brand ) : __( 'N/A', 'woocommerce-gateway-stripe' ) ),
1040+
$payment_method->last4
1041+
);
1042+
}
1043+
1044+
switch ( $payment_method->type ) {
1045+
case WC_Stripe_Payment_Methods::CARD:
1046+
return sprintf(
1047+
/* translators: 1) card brand 2) last 4 digits */
1048+
__( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ),
1049+
( isset( $payment_method->card->brand ) ? wc_get_credit_card_type_label( $payment_method->card->brand ) : __( 'N/A', 'woocommerce-gateway-stripe' ) ),
1050+
$payment_method->card->last4
1051+
);
1052+
case WC_Stripe_Payment_Methods::SEPA_DEBIT:
1053+
/* translators: 1) last 4 digits of SEPA Direct Debit */
1054+
return sprintf( __( 'Via SEPA Direct Debit ending in %1$s', 'woocommerce-gateway-stripe' ), $payment_method->sepa_debit->last4 );
1055+
case WC_Stripe_Payment_Methods::CASHAPP_PAY:
1056+
/* translators: 1) Cash App Cashtag */
1057+
return sprintf( __( 'Via Cash App Pay (%1$s)', 'woocommerce-gateway-stripe' ), $payment_method->cashapp->cashtag );
1058+
case WC_Stripe_Payment_Methods::LINK:
1059+
/* translators: 1) email address associated with the Stripe Link payment method */
1060+
return sprintf( __( 'Via Stripe Link (%1$s)', 'woocommerce-gateway-stripe' ), $payment_method->link->email );
1061+
case WC_Stripe_Payment_Methods::ACH:
1062+
return sprintf(
1063+
/* translators: 1) account type (checking, savings), 2) last 4 digits of account. */
1064+
__( 'Via %1$s Account ending in %2$s', 'woocommerce-gateway-stripe' ),
1065+
ucfirst( $payment_method->us_bank_account->account_type ),
1066+
$payment_method->us_bank_account->last4
1067+
);
1068+
case WC_Stripe_Payment_Methods::BECS_DEBIT:
1069+
return sprintf(
1070+
/* translators: last 4 digits of account. */
1071+
__( 'BECS Direct Debit ending in %s', 'woocommerce-gateway-stripe' ),
1072+
$payment_method->au_becs_debit->last4
1073+
);
1074+
case WC_Stripe_Payment_Methods::ACSS_DEBIT:
1075+
return sprintf(
1076+
/* translators: 1) bank name, 2) last 4 digits of account. */
1077+
__( 'Via %1$s ending in %2$s', 'woocommerce-gateway-stripe' ),
1078+
$payment_method->acss_debit->bank_name,
1079+
$payment_method->acss_debit->last4
1080+
);
1081+
case WC_Stripe_Payment_Methods::BACS_DEBIT:
1082+
/* translators: 1) the Bacs Direct Debit payment method's last 4 numbers */
1083+
return sprintf( __( 'Via Bacs Direct Debit ending in (%1$s)', 'woocommerce-gateway-stripe' ), $payment_method->bacs_debit->last4 );
1084+
case WC_Stripe_Payment_Methods::AMAZON_PAY:
1085+
/* translators: 1) the Amazon Pay payment method's email */
1086+
return sprintf( __( 'Via Amazon Pay (%1$s)', 'woocommerce-gateway-stripe' ), $payment_method->billing_details->email ?? '' );
1087+
}
1088+
1089+
return __( 'N/A', 'woocommerce-gateway-stripe' );
10901090
}
10911091

10921092
/**

readme.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,6 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
119119
* Fix - Ensure all Javascript strings use the correct text domain for translation
120120
* Tweak - Use more specific selector in express checkout e2e tests
121121
* Tweak - Small improvements to e2e tests
122+
* Fix - Fix unnecessary Stripe API calls when rendering subscription details
122123

123124
[See changelog for full details across versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).

0 commit comments

Comments
 (0)