Skip to content

Conversation

@daledupreez
Copy link
Contributor

@daledupreez daledupreez commented Nov 14, 2025

Fixes STRIPE-814

Changes proposed in this Pull Request:

This PR updates our logic for payment method detachment to treat WP-Cron requests as admin requests rather than user-initiated requests. The result of that is that when we get user modification requests via WP-Cron on staging sites, we won't detach the payment method.

The driver for this change is that there are some plugins that perform bulk actions via WP-Cron code, and our current implementation treats those requests as user-initiated requests, which then means we don't check the current environment type.

Testing instructions

We pretty much want to follow the original report in STRIPE-814:

  • Run the code in develop for your site
  • Create a user with customer role and some known email
  • Set your site's Env type to staging or development
  • Ensure you are connected to a live Stripe account -- these checks are bypassed for test connections
  • In a private window login with this user, and add a payment card
  • Come back to admin, adjust your function should_detach_payment_method_from_customer() so that it starts with the following:
	public static function should_detach_payment_method_from_customer() {	
		// TEMP DEBUG
		$debug_is_admin_request = is_admin() || ( defined( 'WP_CLI' ) && WP_CLI );

		$current_url = '';
		if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
			$scheme       = ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http';
			$current_url  = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
		}

		$logger = wc_get_logger();
		$logger->info( wc_print_r( var_export($current_url,true), true ), array( 'source' => 'stripe-env-debug' ) );
		$logger->info( wc_print_r( var_export($debug_is_admin_request,true), true ), array( 'source' => 'stripe-env-debug' ) );
		// TEMP DEBUG ENDS
		// Usual logic continues below
  • Add the following plugin on your site, update TARGET_EMAIL to your email from above and activate it:
<?php
/**
 * Plugin Name: KS Delete Stripe Test User
 * Description: Deletes user with email [email protected] every minute via WP-Cron.
 * Version: 1.1
 * Author: Stripe Debug
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Debug_Delete_Stripe_Test_User {

	const CRON_HOOK = 'debug_delete_stripe_test_user_cron';
	const TARGET_EMAIL = '[email protected]';

	public static function init() {
		// Add custom schedule
		add_filter( 'cron_schedules', [ __CLASS__, 'add_minute_schedule' ] );

		// Hook cron event
		add_action( self::CRON_HOOK, [ __CLASS__, 'delete_user' ] );
	}

	/**
	 * Custom cron interval: every 1 minute
	 */
	public static function add_minute_schedule( $schedules ) {
		$schedules['every_minute'] = [
			'interval' => 60,
			'display'  => __( 'Every Minute' ),
		];
		return $schedules;
	}

	/**
	 * Activate plugin → schedule cron
	 */
	public static function activate() {
		if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
			wp_schedule_event( time(), 'every_minute', self::CRON_HOOK );
		}
	}

	/**
	 * Deactivate plugin → clear cron
	 */
	public static function deactivate() {
		wp_clear_scheduled_hook( self::CRON_HOOK );
	}

	/**
	 * Delete the user if exists.
	 */
	public static function delete_user() {

		$user = get_user_by( 'email', self::TARGET_EMAIL );

		if ( $user ) {
			require_once ABSPATH . 'wp-admin/includes/user.php';
			wp_delete_user( $user->ID );

			error_log( '[Debug Delete User] Deleted user ID ' . $user->ID );
		}
	}
}

Debug_Delete_Stripe_Test_User::init();

register_activation_hook( __FILE__, [ 'Debug_Delete_Stripe_Test_User', 'activate' ] );
register_deactivation_hook( __FILE__, [ 'Debug_Delete_Stripe_Test_User', 'deactivate' ] );
  • Wait for a minute for deletion to occur
  • Check your Woo > Status Logs > stripe-env-debug
  • Confirm that you see false for the request, which indicates that we will return true for the function we checked.
  • Now check out this branch and repeat the steps above, but add || wp_doing_cron() to the $debug_is_admin_request assignment
  • Confirm that after the deletion occurs, the log file includes true for the Cron request

  • 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

Copy link
Contributor

Copilot AI left a 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 fixes an issue where WP-Cron jobs performing bulk user operations on staging sites were incorrectly treated as user-initiated requests, causing payment methods to be detached from production Stripe accounts. The fix treats WP-Cron requests as admin requests, preventing payment method detachment on staging environments.

  • Updated should_detach_payment_method_from_customer() to include wp_doing_cron() in the admin request check
  • Added comprehensive test coverage for WP-Cron scenarios in both test and live modes
  • Updated changelog to document the fix

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
includes/class-wc-stripe-api.php Added wp_doing_cron() check to treat WP-Cron requests as admin requests
tests/phpunit/WC_Stripe_API_Test.php Added test cases and is_cron_request parameter to verify WP-Cron behavior
changelog.txt Added changelog entry for the fix
readme.txt Added changelog entry for the fix

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@daledupreez daledupreez marked this pull request as ready for review November 14, 2025 09:30
@daledupreez daledupreez requested review from a team, diegocurbelo and malithsen and removed request for a team November 14, 2025 09:30
Copy link
Member

@diegocurbelo diegocurbelo left a 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 also confirmed in the Stripe dashboard that the payment method was not detached.

Just one minor detail with the instructions:

Now check out this branch and repeat the steps above.
Confirm that after the deletion occurs, the log file includes true for the Cron request

The TEMP DEBUG section needs to be updated to the same condition used later in the function:

$is_admin_request = is_admin() ||
	( defined( 'WP_CLI' ) && WP_CLI ) ||
	wp_doing_cron();
Image

@daledupreez
Copy link
Contributor Author

The TEMP DEBUG section needs to be updated to the same condition used later in the function

🤦 You're right! Done.

Copy link
Contributor

@malithsen malithsen left a comment

Choose a reason for hiding this comment

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

Looks good, and it works as described.

@daledupreez daledupreez merged commit 2c0ad60 into develop Nov 18, 2025
40 checks passed
@daledupreez daledupreez deleted the add/checks-for-wp-cron-when-checking-if-payment-methods-can-be-detached branch November 18, 2025 20:22
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.

4 participants