Have you received one or many attempts of fraudulent orders on your WooCommerce WordPress website, as one of my clients did, here are some solutions to reduce this from happening in the future.
What this will do is run a function called spam_account which will compare the name. the first line in the address, phone number and the domain name of the email account. If any of those match with what you have added in the arrays then it will display a message and send an email alerting you of this.
Just copy this into your functions.php file.
function spam_account() {
$form_name = $_POST['billing_first_name'] . ' ' . $_POST['billing_last_name'];
$form_add = $_POST['billing_address_1'];
$form_email = $_POST['billing_email'];
$form_phone = $_POST['billing_phone'];
$form_check = $_POST['check'];
$honeypot = $_POST['confirm_email'];//See below about honeypots
$is_spam = spam_domains( $form_email );
$blocked_name = array(
'Bob Smith',
'Elon Musk',
'Santa Clause',
);
$blocked_add = array(
'No1 High Street',
'North Pole',
);
$blocked_phone = array(
'0111 2345678',
'0123-1234664',
);
//See Check fields below
if ( strtolower( $form_check ) != 'BrandName' )
wc_add_notice('Please fill all field out correctly, thank you.', 'error');
if ( ( in_array( strtolower( $form_name ), $blocked_name ) ) OR ( in_array( strtolower( $form_add ), $blocked_add ) ) OR ( in_array( strtolower( $form_phone ), $blocked_phone ) ) OR ( $is_spam == true ) OR ( $honeypot != "" ) ) {
global $wpdb;
$d = date("d/m/y H:i:s");
$wpdb->insert( $wpdb->prefix . "IP_blacklist" , array(
'date' => $d ,
'details' => 'Name: ' . $form_name . ' - Address: ' . $form_add . ' - Phone: ' . $form_phone . ' Is Spam: ' . $is_spam,
), array( '%s', '%s' ) );
wc_add_notice('Sorry, we are unable to process your order. Please contact us directly using <a href="/contact/" title="Contact form">this form.</a>', 'error');
$body = 'An attempted order on the site <b>example.com</b> has been flagged due to the following reason:<br/><br/>
One or more of the following used fields has been flagged as SPAM and therefore a fraudulent order has been stopped.<br/><br/>
<b>NAME:</b> '.$form_name.'<br/>
<b>ADDRESS:</b> '.$form_add.'<br/>
<b>EMAIL:</b> '.$form_email.'<br/>
<b>PHONE:</b> '.$form_phone.'<br/><br/>
Regards<br/>
Anti-Spam team <br/><br/><br/>
';
spam_account_email( '[email protected]' , 'ALERT: Possible Fake Account' , $body );
}
}
add_action('woocommerce_checkout_process', 'spam_account');
function spam_domains( $e ) {
$x = explode( '@', $e );
$blocked_domains = array(
'domainToBlock.com',
);
if ( in_array( strtolower( $x[1] ), $blocked_domains ) )
return true;
return;
}
function spam_account_email( $to, $sub, $body ) {
$headers = array(
'From: Your Name <[email protected]>',
'Content-Type: text/html; charset=UTF-8'
);
$result = wp_mail( $to, $sub, $body, $headers );
}
This is a very basic bit of code you can use to help reduce fake orders, it is by no means good enough to stop professional hackers. For those, you need to do a little more...
A honeypot field is whereby you create a hidden field from the human visitors but is still visible to bots to see and use. If the field looks like one that needs to be used the bot will most likely fill something, anything, so it thinks it has completed the form.
When the form fields are checked and the honeypot field has a value then you know it was filled out by a bot and you can act appropriately.
To create a honeypot field in your form it is just a simple HTML line of code you can add to your form - just don't call it honeypot as I have in this example:
<input type="email" name="honeypot" id="confirm_email" hidden />
To add a honeypot field to your WordPress WooCommerce checkout form you can use the following function which you can add to your functions.php file.
function add_honeypot_field() {
echo '<div style="display: none;">
<input type="text" name="JumpingGiraffeLovesYou">
<label for="confirm_email">Confirm email address:</label>
<input type="email" name="confirm_email" id="confirm_email" autocomplete="off" />
</div>';
return;
}
add_action('woocommerce_after_checkout_billing_form', 'add_honeypot_field');
What this does is add a field and label called confirm_email to the form, it is a good name as it sounds like you need to fill it in to confirm you have typed in your email address correctly.
You will have noticed that there is another field called JumpingGiraffeLovesYou, some browsers will not use the autocomplete=off - which stops the field from being automatically filled in and included in the confirm_email field - and still add previously saved values to this field. This of course would not be good if we don't want the field to be filled in by a human.
So having another field before it can stop the confirm_email field from being automatically filled in.
I have used the hook woocommerce_after_checkout_billing_form as it's directly after the main form which more often than not the last field is the real email field.
You will notice the display: none; a command which hides the form from humans.
This will help but we can go even further...
*** Please test this option well, particularly if you use Paypal which sends the user back to the same checkout page whilst paying. If this is the case then do not use it as it could stop orders ***
To add a Check field - which is what I call it, there might be a fancy name for it elsewhere - whereby you ask the human to add a word to a field which you can compare after the form is filled in.
I often use these instead of the dreaded Captcha checks - I hate those things! - as it's easy to add and you can use it to help sublimely highlight a message (more on that in a mo).
function add_honeypot_field() {
echo '<div style="display: none;">
<label for="confirm_email">Confirm email address:</label>
<input type="email" name="confirm_email" id="confirm_email" />
</div>';
echo '<div>
<label for="check">Please type <b>BrandName</b> here *</label>
<input type="text" name="check" id="check" required />
</div>';
return;
}
add_action('woocommerce_after_checkout_billing_form', 'add_honeypot_field');
As you can see I have added the Check field to the previous code we created for the honeypot field. The label says to add a word in the field which you compare after the form is filled out. Some bots will not understand what we are asking and therefore get it wrong. You can be as imaginative as you like with the word(s). I like to use the brand name as it helps drive home the name of where they bought the product as they had to type it in and not just read it somewhere.
I'm not done yet! My favourite is still to come...
To disable the place order button in the checkout form within WooCommerce isn't as straightforward as other options above to stop bots from ordering off your website. But, it's easy when you have the code to add like below! :)
The reason why you would want to stop someone from pressing the Place Order button - as mad as that sounds - is to slow everything down just a little. Bot crawl websites very quickly and fill out forms in milliseconds, they don't tend to want to hang around for 10 seconds to press the order button. After all, they are very busy little bots!
I have picked 10 seconds but you can choose the length as you wish, just change the 10 in the code below. I use 10 seconds as a human would have to be very quick at typing to fill out all the fields before they are ready to confirm with the buy button.
That said a button not working could annoy some people so I make it obvious that it is disabled by changing the opacity until it is active and ready to use.
I go one step further too by adding a countdown displayed just below the order button counting down the 10 seconds before they can make their order. You can also add a message explaining why this is happening if you like too.
Right, let's get down to the code. For this time we need to create a new JavaScript file as well as add a couple of new functions in the functions.php file.
Create a directory within your themes folder called /js/ (if not already there), the full path will be something like this:
path/wp-content/themes/yourtheme/js/
Name the file countdown.js. Within that file add the following code:
var myDiv = document.getElementById("order_review");
var countdown = document.getElementById("countdown");
var duration = 10; //Duration in seconds
var intervalId;
function disableDiv() {
myDiv.style.opacity = 0.5; //Set the opacity to 0.5
myDiv.style.pointerEvents = "none";
}
function enableDiv() {
myDiv.style.opacity = 1; //Set the opacity back to 1
myDiv.style.pointerEvents = "auto";
}
disableDiv();
intervalId = setInterval(function() {
duration--;
countdown.textContent = "Enabled in " + duration + " seconds";
if (duration <= 0) {
clearInterval(intervalId);
countdown.textContent = "";
enableDiv();
}
}, 1000); // 1000 milliseconds = 1 second
Now in the functions.php file, you need to add two functions. The first will run the JavaScript file we just created. The second will add the countdown clock just below the form. I am using the WooCommerce hook woocommerce_checkout_after_order_review here but you can use the hook you like on the page.
function disable_checkout_button() {
wp_enqueue_script( 'disable-checkout-button', get_stylesheet_directory_uri() . '/js/countdown.js', array( 'jquery' ), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'disable_checkout_button' );
function add_countdown() {
echo '<span id="countdown"></span>';
}
add_action('woocommerce_checkout_after_order_review', 'add_countdown');
WordPress have several APIs you can use to help your website perform better, I use the nonce commands to help identify fake orders. Although the code doesn't actually check for Bots or even if the user is on the site, it does help protect against CSRF ( Cross-Site Request Forgery ) attacks by ensuring the request originated from the same site.
In the code below it will check for the nonce value and if doesn't exist it will redirect the user to another page, of your choice.
// Add nonce field to WooCommerce checkout form
function add_checkout_nonce_field() {
wp_nonce_field('checkout_nonce_action', 'checkout_nonce');
}
add_action('woocommerce_checkout_before_customer_details', 'add_checkout_nonce_field');
// Verify nonce and act on if not correct
function check_user_on_checkout() {
if (isset($_POST['checkout_nonce']) && wp_verify_nonce($_POST['checkout_nonce'], 'checkout_nonce_action')) {
// User is on the checkout page
return;
} else {
//User is not on the checkout page, add your code here...
}
}
add_action('woocommerce_checkout_process', 'check_user_on_checkout');
In this example, I have added an action name - checkout_nonce_action - to replace the default WordPress nonce value of _wpnonce. This will add further security, no point in not doing it really. It can be whatever you like as with the second parm - checkout_nonce - for the field name.
Whilst you are looking at this code you might be thinking that it would be good if you could redirect the bot to another landing page if they flag one of the many tests we have in this code.
At the moment it will just display a message, however, if you want to redirect to another page then sadly there doesn't look like there is a way to do this - unless stated elsewhere.
If you do find a way please let me know on social media, the buttons are below.
The best thing about using this code is that you don't need to rely on third-party developers to update their WordPress plugin and you don't need those awful captchas!
You can also record when this happens so you can find out more about the user/bot.
Version 3 of Google's re-captcha is much better for the user and doesn't need someone to perform a task like identifying traffic lights in the boxes. That said, if you don't want Google on your site this is another option.
I have also created a post about IP address rate limiting which is very useful for securing your site as well as this functions, you can find it here on the Creating WooCommerce Checkout Rate Limiting page.
Additionally, you might also be interested in our post on How to Blacklist an IP address and redirect them too!.
That's it I hope this will help stop those pesky bots from ordering off your site, any questions please get in touch on social media, buttons to my accounts are in the footer.