Skip to content

Enforce plugin rate limit when Stripe returns 429 errors #4327

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

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

daledupreez
Copy link
Contributor

Relates to STRIPE-445
Relates to:

Changes proposed in this Pull Request:

This PR implements some post-request checks to detect when we receive an HTTP 429 response from Stripe, and then impose a 30 second period where we won't make further GET requests via WC_Stripe_API::retrieve(). When we enter into a rate-limited mode, we'll take the following actions:

  • Log an error via WC_Stripe_Logger
  • Log an error to the PHP error log via error_log()
  • Add the expiry time for the current rate limit to the respective wc_stripe_live_api_rate_limit or wc_stripe_test_api_rate_limit option
  • Add details for the current rate limit period to the appropriate wc_stripe_live_api_rate_limit_history or wc_stripe_test_api_rate_limit_history option (but we'll only retain 20 of these to avoid unnecessary option size).

When WC_Stripe_API::retrieve() is called while the rate limit is in effect, we'll return a null response immediately, without logging anything extra.

When WC_Stripe_API::retrieve() is called after the rate limit expires, we'll remove the previous rate limit entry from the appropriate option, and proceed.

There are some possible nuances we may want to handle differently:

  • I am not yet pushing up a notice when this occurs -- I think we should add one
  • The logic for detecting error responses will now detect all 4xx and 5xx response codes, where we would only treat responses with an empty body as an error before
  • The rate limit period is only 30 seconds - this may need to be shorter or longer
  • I don't know how useful the history is/will be, but I think it's a good idea
    • This may be useful for triggering an email after 2 rate limits within a period of time, for example.
  • The logic has a lot of overlap with the work @diegocurbelo is doing in Prevent Stripe API calls after detecting the API keys are not valid (401 response from API) #4323 - we will need to confirm our approach

Testing instructions

  • Create a build using the code from this branch, install it on a site, and ensure that you have a Stripe connection configured
  • Add a plugin or tool that allows you to run snippets of PHP code
  • Set up the following code to run on your site - it modifies an HTTP response from Stripe to simulate an HTTP 429 response:
function simulate_http_429_from_stripe_api( $response, $parsed_args, $url ) {
	if ( ! str_starts_with( $url, 'https://api.stripe.com/v1/' ) ) {
		return $response;
	}
	
	if ( is_array( $response ) && isset( $response['response'] ) && is_array( $response['response'] ) && isset( $response['response']['code'] ) ) {
		$response['response']['code'] = 429;
	}
	
	return $response;
}

add_filter( 'http_response', 'simulate_http_429_from_stripe_api', 10, 3 );
  • Navigate to WooCommerce > Settings > Payments, and select the Stripe option from the list
  • Navigate to the Payment Methods page
  • Confirm that no items in the
  • Use WP-CLI or some other tool to verify that the wc_stripe_test_api_rate_limit option has a value (or the _live_ equivalent) has a value
    • WP-CLI command: wp option get wc_stripe_test_api_rate_limit
  • Use WP-CLI or some other tool to verify that the wp option get wc_stripe_test_api_rate_limit_history (or the _live_ equivalent) has readable data

  • Covered with tests (or have a good reason not to test in description ☝️)
  • [N/A] 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

@daledupreez daledupreez requested a review from a team May 16, 2025 14:22
@daledupreez daledupreez self-assigned this May 16, 2025
@daledupreez daledupreez requested review from annemirasol and removed request for a team May 16, 2025 14:22

$status_code = $response['response']['code'];

if ( 429 === $status_code ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on https://docs.stripe.com/rate-limits#rate-limited-requests, it is better to check for the header. It is possible that a 429 may not be related to rate-limiting. Both work fine, but checking the header would be more consistent.

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.

3 participants