Skip to content

Add caching for Stripe payment method configuration #4241

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

Merged
merged 15 commits into from
Apr 24, 2025

Conversation

daledupreez
Copy link
Contributor

@daledupreez daledupreez commented Apr 17, 2025

Fixes #4182
Fixes STRIPE-384

Changes proposed in this Pull Request:

It adds a cache layer (using a transient) when fetching Payment Method Configurations (PMCs) from the Stripe Configurations API.

Testing instructions

To easily test the cache edit the file includes/class-wc-stripe-api.php add a WC_Stripe_Logger::log( 'get_payment_method_configurations' ) to the function get_payment_method_configurations (line 473).

Or add a breakpoint on line 473 and enable Xdebug.

  1. Go to the plugin settings: WP-Admin > WooCommerce > Settings
  2. Go to Payments and open the Stripe Gateway details page
  3. Go to the Payment Methods tab
  4. Check that only one call to the Configurations API was made
  5. Reload the page, and check that a new Configurations API call was made (always get the latest data for the settings page)
  6. Go to the Store, add any product to the cart, go to the cart, and then go to the checkout
  7. Check that no new Configurations API call was made

  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Changelog entry

  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Comment

Comment

Post merge

…ove reset_primary_configuration in favor of clear_primary_configuration_cache
@Mayisha Mayisha mentioned this pull request Apr 17, 2025
@diegocurbelo diegocurbelo marked this pull request as ready for review April 21, 2025 16:26
@diegocurbelo diegocurbelo self-assigned this Apr 21, 2025
@diegocurbelo diegocurbelo requested review from a team and Mayisha and removed request for a team April 21, 2025 16:34
Copy link
Contributor Author

@daledupreez daledupreez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, things are looking OK from inspection, but I have two concerns (with one being less important):

  1. We are using the same cache for test and live mode, and I am concerned that we could end up with stale data and possibly weird behaviour if users switch between live and test mode. We should either have separate caches for each mode, or we should clear the cache when live/test mode is toggled.
  2. While I agree with making the naming more consistent, I would personally lean towards doing that across two PRs, as we're introducing a lot more testing and possible side effects in this PR, where we're adding caching and making some naming changes. I am still not too familiar with the code, though, so I may be overstating the testing impact.

I will start manual testing shortly.

Comment on lines 195 to 196
WC_Stripe_API::get_instance()->update_payment_method_configuration( $pmc->id, $updated_payment_methods );
self::clear_pmc_cache();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels risky to ignore the return value from update_payment_method_configuration(). We're clearing the cache despite us not confirming whether the operation succeeded.

This is a pre-existing feature of the code, but I think clearing the cache won't be majorly problematic, though it feels like it could be overly aggressive, and we may have downstream issues if we've cleared the cache, but can't communicate with the Stripe API for some reason.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a log entry in case of request failure, so we have the full context in the logs.

The proper solution would be to bubble-up the error message (and description) and show it to the merchant in the settings with a failure notice. But I think we should change that in another PR and keep this one focused on the cache. I think that until we refactor the save settings error notice it makes sense to clear the cache on failure, even in the case we can't communicate with the Stripe API, keeping the cache content won't help, as Intent creation will also fail, for example.

Copy link
Contributor Author

@daledupreez daledupreez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now tested, but had some minor difficulties getting exactly the same details right.

  1. Go to the Payment Methods tab
  2. Check that only one call to the Configurations API was made
  3. Reload the page, and check no new Configurations API call was made

My understanding is that this case should always trigger a new API call (which is what I am seeing).

  1. Check the transient with this WP-CLI
    wp transient list --search=wcstripe_payment_method_configuration_cache --unserialize --human-readable

The site I am testing with is using an object cache, so the wp transient list command shows the following warning, and doesn't show the transient we want:

Warning: Transients are stored in an external object cache, and this command only shows those stored in the database.

I can get the transient contents, but not the expiration time. (In this case, I am fairly confident the 10 minute timeout is being obeyed.)

  1. Delete the transient:
    wp transient delete wcstripe_payment_method_configuration_cache
  2. Refresh the checkout page. and check taht only one call was made to the Configurations API

I am seeing another call to fetch the configuration before I reload the checkout page. But I can confirm we're only making one API call. I am not 100% sure where/how the call is being triggered, but I think that's less relevant as long as it is not forcing a refresh from Stripe and bypassing the cache.

  1. Check the transient again and verify the expiration:
    wp transient list --search=wcstripe_payment_method_configuration_cache --unserialize --human-readable

I wasn't able to check this aspect. I was using wp transient get wcstripe_payment_method_configuration_cache almost immediately, but I suspect something in the code loading was fetching the configuration from Stripe, as running the delete and then get commands from the CLI was giving me data. (I suspected the delete might not be working, but I was seeing a new fetch command in the log each time.)

Given the behaviour of transients when we have an object cache in place, it may be worth storing a timestamp in the cached data, and using a cache format that includes some wrapper information around what we're actually caching. But that may be overkill for this first iteration.

@wjrosa
Copy link
Contributor

wjrosa commented Apr 22, 2025

Don't forget to change the base branch to release/9.4.2 (or to cherry pick later)

@diegocurbelo
Copy link
Member

  1. We are using the same cache for test and live mode, and I am concerned that we could end up with stale data and possibly weird behaviour if users switch between live and test mode. We should either have separate caches for each mode, or we should clear the cache when live/test mode is toggled.

Fixed in 76f3398

  1. While I agree with making the naming more consistent, I would personally lean towards doing that across two PRs, as we're introducing a lot more testing and possible side effects in this PR, where we're adding caching and making some naming changes. I am still not too familiar with the code, though, so I may be overstating the testing impact.

Reverted those changes, and will create a new PR for them.

@diegocurbelo
Copy link
Member

I've now tested, but had some minor difficulties getting exactly the same details right.

  1. Go to the Payment Methods tab
  2. Check that only one call to the Configurations API was made
  3. Reload the page, and check no new Configurations API call was made

My understanding is that this case should always trigger a new API call (which is what I am seeing).

Correct, I updated the testing instructions... and removed the transient wp-cli commands, as those would be testing how the transients work; as you said, we are fairly confident the 10-minute timeout is being obeyed... are we OK with 10 minutes? Or should we be more aggressive and use 1 hour, for example?

Copy link
Contributor

@Mayisha Mayisha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good to me. The main focus of the PR; the caching mechanism is working well.

✅ On the settings page, payment method configuration is always retrieved from Stripe.
✅ On checkout and other pages, cached data is used.
✅ Cache is cleared after 10 minutes and payment method configuration is always retrieved from Stripe again.

In develop branch, just loading any page would make a API request to /payment_method_configurations.

develop logs.log

In this branch, only one API request is sent. Extra requests are sent when the settings page is loaded or if the cache is empty.

fix branch logs.log

⚠️ I found 2 issues, but unrelated to the cache implementation.

  • On the plugin settings page, we are still showing the available payment methods based on the capabilities object and the is_available_for_account_country function, instead of the data received from the payment method configuration API.
  • When the store currency is USD, update_payment_method_configuration fails with the error -
    'amazon_pay' is not available to this merchant

@daledupreez daledupreez merged commit b1d1a54 into develop Apr 24, 2025
51 checks passed
@daledupreez daledupreez deleted the fix/add-caching-for-stripe-configuration branch April 24, 2025 10:20
@daledupreez
Copy link
Contributor Author

@diegocurbelo, I went ahead and merged this as I was seeing too much noise in my logs from the API calls when testing a different issue.

Copy link

📈 PHP Unit Code Coverage Report

Package Line Rate Health
includes/abstracts/abstract-wc-stripe-payment-gateway.php 48%
includes/admin/class-wc-rest-stripe-settings-controller.php 81%
includes/class-wc-stripe-payment-method-configurations.php 95%
includes/payment-methods/class-wc-stripe-upe-payment-gateway.php 49%
Summary 44% (7218 / 16242)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Settings Synchronization: Cache enabled payment methods for non-admin pages
4 participants