You’re under a carding attack, and the bot tries to submit the payment for a given order 300 times… Which means 300 failed order emails, and a database mess.
WooCommerce doesn’t limit how many times a customer (or bot) can attempt to pay for a failed order via the “Order Pay” page. This opens the door to abuse, unnecessary clutter in the order table, and frustration for both store owners and customers.
One way to mitigate this is by tracking how many times a failed order has been retried and automatically cancelling it after the third attempt. This solution keeps things clean, secure, and under control.

PHP Snippet: Limit Payment Retries on Failed Orders @ WooCommerce Order Pay Page (WooCommerce Stripe Payment Gateway)
The following snippet is based on the official WooCommerce Stripe Payment Gateway plugin, but you can adapt it to any other payment provider, as long as they provide a “hook” upon failed payment.
This code snippet automatically cancels WooCommerce orders after three failed Stripe payment attempts. When a customer tries to pay with Stripe and the payment fails (due to declined cards, insufficient funds, or other issues), this function runs automatically.
The code keeps track of how many times payment has failed for each order by storing a counter in the order’s metadata. Each time a Stripe payment fails, it increases this counter by one and saves it to the database.
If this is the customer’s first or second failed attempt, nothing dramatic happens – they can try paying again. However, once the payment fails for the third time, the system automatically changes the order status to “cancelled” and adds a note explaining why.
This prevents customers (and bots) from making endless payment attempts on the same order and helps store owners manage failed transactions more efficiently. It’s particularly useful for preventing fraud attempts or clearing out orders that customers have abandoned after multiple failed payment tries.
/**
* @snippet Max 3 Stripe Payment Retries @ WooCommerce Order Pay
* @tutorial https://businessbloomer.com/woocommerce-customization
* @author Rodolfo Melogli, Business Bloomer
* @compatible WooCommerce 9
* @community https://businessbloomer.com/club/
*/
add_action( 'wc_gateway_stripe_process_payment_error', 'bbloomer_handle_stripe_payment_failure', 10, 2 );
function bbloomer_handle_stripe_payment_failure( $error, $order ) {
if ( ! $order || ! is_a( $order, 'WC_Order' ) ) return;
$order_id = $order->get_id();
// Attempt count
$attempt_count = $order->get_meta( '_stripe_payment_attempts', true );
$attempt_count = $attempt_count ? intval( $attempt_count ) + 1 : 1;
$order->update_meta_data( '_stripe_payment_attempts', $attempt_count );
$order->save_meta_data();
// Cancel order after 3 attempts
if ( $attempt_count >= 3 ) {
$order->update_status( 'cancelled', sprintf( 'Order cancelled after %d failed Stripe payment attempts', $attempt_count ) );
}
}