WooCommerce: Failed Orders Monitor & Temporary Lockdown

Sooner or later, every WooCommerce store will face a carding attack. It’s a matter of when, not if. We covered the ins and outs of this in a recent class (Preventing WooCommerce Checkout Carding Attacks), and now this post provides the code solution you’ve all been waiting for.

Want to temporarily lock down your WooCommerce site when too many failed orders happen?

This snippet does just that! When the 3rd order in a row fails, it triggers a 10-minute lockdown, disabling a specific payment gateway, and preventing purchases of low-ticket products. Plus, you’ll get an email notification when the lockdown is active.

It works by setting a temporary flag (a WordPress “transient“) and checking it before allowing payments and purchases.

This is a great way to prevent repeated failures, investigate payment issues, mitigate carding attacks, and ensure a smooth customer experience. Enjoy!

Too many failed orders – a possible carding attack! Let’s deny these robots by locking down WooCommerce for a little while…

PHP Snippet: Monitor Failed Orders & Temporarily Lock Down WooCommerce In Case Of Carding Attacks

This code snippet helps monitor failed WooCommerce orders and temporarily locks down the site if too many failures occur in the last 10 minutes. Here’s a breakdown of its functionality:

  1. Counting Failed Orders: The bbloomer_get_failed_orders_last_10mins() function retrieves all failed orders created in the last 10 minutes and returns the count. It uses wc_get_orders() to fetch the orders based on the status and time.
  2. Setting Lockdown on Multiple Failures: When a failed order occurs, the bbloomer_monitor_failed_orders_behavior() function checks if there have been at least two failed orders in the last 10 minutes. If so, it sets a transient to lock the site for 10 minutes and sends an email notification to the site admin about the lockdown.
  3. Disabling Payment Gateway: If the transient exists, the bbloomer_disable_cc_gateway() function disables the credit card payment gateway (e.g., Stripe).
  4. Preventing Low-Value Purchases: The bbloomer_disable_cheap_purchases() function prevents purchases of low-value products (less than $20) when the lockdown is active.
/**
 * @snippet       Lock Down WooCommerce During Carding Attacks
 * @tutorial      https://businessbloomer.com/woocommerce-customization
 * @author        Rodolfo Melogli, Business Bloomer
 * @compatible    WooCommerce 9
 * @community     https://businessbloomer.com/club/
 */

// COUNT FAILED ORDERS LAST 10 MINUTES
function bbloomer_get_failed_orders_last_10mins() { 
    $args = array(
        'status' => 'failed',
        'date_created' => '>' . ( time() - 10 * MINUTE_IN_SECONDS ),
        'limit' => -1,
		  'return' => 'ids',
    );
    $failed_orders = wc_get_orders( $args );
    return $failed_orders ? count( $failed_orders ) : 0;
}

// AT THE NEXT FAILED ORDER, MAYBE SET A TRANSIENT TO LOCK DOWN WOO
add_action( 'woocommerce_order_status_failed', 'bbloomer_monitor_failed_orders_behavior' );

function bbloomer_monitor_failed_orders_behavior( $order_id ) {
    $failed_orders_count = get_failed_orders_last_10mins();
    if ( $failed_orders_count >= 2 ) {
        set_transient( 'bbloomer_failed_order_lock', time(), 10 * MINUTE_IN_SECONDS );
        wp_mail( get_option( 'admin_email' ), 'WooCommerce Lockdown Active', 'A WooCommerce lockdown is active for 10 minutes due to a carding attack.' );	
    }	
}

// IF THE TRANSIENT EXISTS, TEMP DISABLE CC PAYMENTS
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_disable_cc_gateway' );

function bbloomer_disable_cc_gateway( $gateways ) {
    if ( get_transient( 'bbloomer_failed_order_lock' ) && isset( $gateways['stripe'] ) ) {
        unset( $gateways['stripe'] );
    }
    return $gateways;
}

// IF THE TRANSIENT EXISTS, TEMP DISABLE LOW VALUE PURCHASES
add_filter( 'woocommerce_is_purchasable', 'bbloomer_disable_cheap_purchases', 9999, 2 );

function bbloomer_disable_cheap_purchases( $purchasable, $product ) {
	if ( $product->get_price() > 19.99 || $product->get_price() < 0.01 ) return $purchasable;
    if ( get_transient( 'bbloomer_failed_order_lock' ) ) {
        return false;
    }
    return $purchasable;
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

4 thoughts on “WooCommerce: Failed Orders Monitor & Temporary Lockdown

  1. If we were to amend the gateway from ‘stripe’ to ‘paypal’ would that lockdown the PayPal gateway?
    Thank you in advance!

    1. Yes, of course, as long as your PayPal gateway comes with the ‘paypal’ ID, which is not always the case

  2. This happened to me recently, there were 1000s of failed payments over a period of 2-3 days.. day and night.. and 7-8 of those transactions went through. Spent hours on the phone with paypal to resolve this coz I didn’t want to get flagged for fraudulent transactions. They just told me to remove the payment buttons. Luckily, this was for a site that had less than 5 services and were small amounts. So it wasn’t a huge deal for me to remove the buy now buttons. But I can’t imagine this hitting a larger business with hundreds of products. You cant just shut down the site!

    My question is will that 10 min lockdown also deny any real transactions? Is it complete site wide no transactions going through? And does it restart automatically after 10 min?

    Would a genuine customer get some sort of notification that pls try again after 10 min or something to that effect?

    Thank you for your work.

    1. Well of course this can be customized. In my solution, I’m locking down Stripe payments only (so if you have PayPal that will keep working), and also locking down low ticket items (between 0.01 and 19.99), but you can of course remove either one or add a different type of lockdown e.g. logged in users only.

      Transient will auto-reset in 10 mins, so after that it will automatically get back to normal.

      Always test this first on staging/dev instead of your live site!

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

Your email address will not be published. Required fields are marked *