-
Notifications
You must be signed in to change notification settings - Fork 216
Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() #4568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Refactor WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method() #4568
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the subscription payment method rendering logic to reduce unnecessary Stripe API calls. Instead of iterating through all payment method types and making multiple API calls to find a matching payment method, it now makes a single direct API call to retrieve the specific payment method details.
- Replaces loop-based payment method retrieval with direct API call using customer ID and payment method ID
- Extracts payment method display logic into separate helper methods for better maintainability
- Adds comprehensive test coverage for various payment method types
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
includes/compat/trait-wc-stripe-subscriptions.php | Refactors maybe_render_subscription_payment_method() to use direct API calls and extracts display logic into helper methods |
tests/phpunit/WC_Stripe_Payment_Gateway_Test.php | Replaces simple test with comprehensive data provider covering multiple payment method types |
readme.txt | Adds changelog entry for the optimization |
changelog.txt | Adds changelog entry for the optimization |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
} | ||
|
||
if ( isset( $cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ] ) ) { | ||
return $cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a static variable for caching in a web environment can lead to data leakage between requests or users. Consider using WordPress transients or object cache instead for safer caching that respects request boundaries.
return $cached_payment_methods[ $stripe_customer_id ][ $payment_method_id ]; | |
if ( empty( $stripe_customer_id ) || empty( $payment_method_id ) ) { | |
return null; | |
} | |
$cache_key = 'stripe_sub_pm_' . md5( $stripe_customer_id . '|' . $payment_method_id ); | |
$cache_group = 'stripe_payment_methods'; | |
$saved_payment_method = wp_cache_get( $cache_key, $cache_group ); | |
if ( false !== $saved_payment_method ) { | |
return $saved_payment_method; |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this use case, I think it's OK to use a static variable, due to us using the customer ID and payment method ID in the path, but I'd be happy to switch to a transient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally it is working as described. I see only one request to customers/cus_abc/payment_methods/pm_xyz
in my logs 🎉
/** | ||
* Helper function to get the descriptive text for a payment method or source. | ||
* | ||
* @param object $source The payment method or source object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: My preference would be to call it a payment_method
in all the new methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Updated in 9e6ebdd
|
||
$encoded_customer_id = rawurlencode( $stripe_customer_id ); | ||
$encoded_payment_method_id = rawurlencode( $payment_method_id ); | ||
$api_path = "customers/{$encoded_customer_id}/payment_methods/{$encoded_payment_method_id}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an alternate approach which would cover this related to the open question as well,
I am not sure how/if we need to handle older src_* sources. I don't know how Stripe handles those via the payment_methods APIs.
we can retrieve the payment method or source using the get_payment_method method and check if payment_method->customer
matches the $stripe_customer_id
.
AFAIK, /payment_methods/src_xyz
fails so customers/customer_abc/payment_methods/src_xyz
might also fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. I've switched that over in 3aecb6c.
} | ||
|
||
/** | ||
* Helper function to get and temporarily cache the payment method details for a customer and payment method ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: we can move this helper method to WC_Stripe_Subscriptions_Helper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is also a good suggestion. Done in 2920871.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good, and it tests well 🚢

I don't know if it's worth using a transient for the payment method caching, or whether we should just cache the payment method without the customer ID dimension. I think both should be unique.
I like the transient idea, I think is consistent with how we are caching other things.. but we cal also improve this later, after we add a auto-cleanup mechanism to the DB cache.
Changes proposed in this Pull Request:
This PR refactors the code in
WC_Stripe_Subscriptions_Trait->maybe_render_subscription_payment_method()
. There are a few aspects to the refactor that are worth capturing in more detail:WC_Stripe_API::get_payment_method()
API so we can handle oldersrc_
IDs.Open questions
I am not sure how/if we need to handle olderAs per this suggestion from @Mayisha, I've switched to callingsrc_*
sources. I don't know how Stripe handles those via thepayment_methods
APIs.WC_Stripe_API::get_payment_method()
and then check the customer ID afterwards.Testing instructions
develop
, navigate to My account > Subscriptions > Your just-purchased subscription (or My Subscription if you only have one subscription)/v1/payment_methods
APIgit checkout refactor/subscriptions-trait-payment-method-rendering
/v1/payment_methods/:payment_method_id
endpointsrc_*
payment method ID, it would be good to test that, too!Changelog entry
Changelog Entry Comment
Comment
Post merge