WooCommerce security on checkout

I’ve been trying to add a kind of security, like a captcha or security question, to the checkout form. I’ve tried it using PHP, add-ons, plugins, but I can’t find anything that works. Do you guys know how I can do this? It’s so that I don’t get a lot of orders from bots. Preferably in code. I tried it using

$number = 2
//other wordpress/woocommerce code
'human' => array(
            'label'       => __( 'Are you a human?', 'woocommerce' ),
            'placeholder' => __( 'What is 1 + 1?', 'woocommerce' ),
            'required'    => true,
            'validate'    => $number
        ),

in woocommerce/includes/class-wc-countries.php
but it wouldn’t work: it showed the form, but I could enter anything, and it would just continue, even if I entered e.g. 324.

Related posts

3 comments

  1. Expanding on my tutorial on customizing the checkout fields we can start with adding and displaying some fields:

    This will add the computation check field:

    function so_31413975_filter_checkout_fields($fields){
        $fields['extra_fields'] = array(
                'human_check' => array(
                    'type' => 'text',
                    'label' => __( 'What is 1+1?', 'stack-overflow' ),
                    'placeholder' => __( 'Enter a number', 'stack-overflow' )
                    )
                );
    
        return $fields;
    }
    add_filter( 'woocommerce_checkout_fields', 'so_31413975_filter_checkout_fields' );
    

    And this displays it on the checkout

    function so_31413975_extra_checkout_fields(){ 
    
        $checkout = WC()->checkout(); ?>
    
        <div class="extra-fields">
        <h3><?php _e( 'Are you human?', 'stack-overflow' ); ?></h3>
    
        <?php 
        // because of this foreach, everything added to the array in the previous function will display automagically
        foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
    
                <?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
    
            <?php endforeach; ?>
        </div>
    
    <?php }
    add_action( 'woocommerce_checkout_after_customer_details' ,'so_31413975_extra_checkout_fields' );
    

    I like honeypots, which are fields that humans are meant to keep blank but bots might try to fill. They catch bots but don’t even show to humans and humans don’t have to do anything. Win, win! Because this is a hidden input I was not able to add it via the functions above. Therefore we will add the markup directly the checkout template.

    function so_31413975_add_honeypot(){ ?>
        <p style="display:none" id="sweetness"><label for="sweetness" class=""><?php _e('Leave this field blank', 'stack-overflow' );?> </label><input type="text" class="input-text " name="sweetness" id="sweetness" placeholder="<?php _e( 'Do not write here', 'stack-overflow' );?>" value=""></p>
    <?php
    }
    add_action( 'woocommerce_checkout_before_order_review', 'so_31413975_add_honeypot' );
    

    WooCommerce only allows for certain types of validation. Outside of required, city, phone, etc, we must do our own validation with the posted info. By adding an error notice we stop the order from being completed.

    function so_31413975_validate_checkout(){
        if ( !isset( $_POST['sweetness'] ) || ( isset( $_POST['sweetness'] ) && trim( $_POST['sweetness'] ) !== '' ) ){
            wc_add_notice( __( 'You seem like a bot.', 'stack-overflow' ), 'error' );
        }
    
        if ( ! isset( $_POST['human_check'] ) || ( isset( $_POST['human_check'] )&& intval( $_POST['human_check'] ) !== 2 ) ){
            wc_add_notice( __( 'Please enter the correct number', 'stack-overflow' ), 'error' );
        }
    }
    add_action( 'woocommerce_checkout_process', 'so_31413975_validate_checkout' );
    
  2. You could edit the page the form is on: hide the button until the user enters the captcha correctly, or answers the math question properly:

    http://jsfiddle.net/robinvandernoord/pexhLL2g

        <div id="place_order" style="display:none">
        <button onclick="alert('yay')">Place Order</button>
    </div>
    <p style="text-align: left;">[woocommerce_checkout]</p>
    
    <h2>are you human?</h2>
    
    <script>
        function enable() {
            var user = document.getElementById("user").value;
            if (user === answer) {
                var docu = document.getElementById("place_order").style;
                docu.display = "block";
                var eneb = document.getElementById("enable").style;
                eneb.display = "none";
                var met = document.getElementById("math").style;
                met.display = "none";
                var user = document.getElementById("user").style;
                user.display = "none";
            } else {
                makeMath();
            }
        }
    </script>
    <div id="math"></div>
    <script>
        function makeMath() {
            var random1 = Math.floor(Math.random() * 5);
            var random2 = Math.floor(Math.random() * 5);
            answer = random1 + random2;
            var mat = document.getElementById("math");
            mat.innerHTML = ""
            mat.innerHTML += "what is ";
            switch (random1) {
                case 0:
                    mat.innerHTML += "zero";
                    break;
                case 1:
                    mat.innerHTML += "one";
                    break;
                case 2:
                    mat.innerHTML += "two";
                    break;
                case 3:
                    mat.innerHTML += "three"
                    break;
                case 4:
                    mat.innerHTML += "four";
                    break;
                case 5:
                    mat.innerHTML += "five";
                    break;
                case 6:
                    mat.innerHTML += "six";
                    break;
                default:
                    mat.innerHTML += random1;
                    break;
            }
            /* 
    //mat.innerHTML += " plus ";
    */
            mat.innerHTML += " plus ";
            switch (random2) {
                case 0:
                    mat.innerHTML += "zero";
                    break;
                case 1:
                    mat.innerHTML += "one";
                    break;
                case 2:
                    mat.innerHTML += "two";
                    break;
                case 3:
                    mat.innerHTML += "three"
                    break;
                case 4:
                    mat.innerHTML += "four";
                    break;
                case 5:
                    mat.innerHTML += "five";
                    break;
                case 6:
                    mat.innerHTML += "six";
                    break;
                default:
                    mat.innerHTML += random1;
                    break;
            }
            /*
    note
    */
            mat.innerHTML += "?";
            /*
    note
    */
            switch (answer) {
                case 1:
                    answer = "one";
                    break;
                case 2:
                    answer = "two";
                    break;
                case 3:
                    answer = "three";
                    break;
                case 4:
                    answer = "four";
                    break;
                case 5:
                    answer = "five";
                    break;
                case 6:
                    answer = "six";
                    break;
                case 7:
                    answer = "seven";
                    break;
                case 8:
                    answer = "eight";
                    break;
                case 9:
                    answer = "nine";
                    break;
                case 10:
                    answer = "ten";
                    break;
                case 11:
                    answer = "eleven"
                    break;
                case 12:
                    answer = "twelve"
                    break;
                default:
                    answer = answer;
                    break;
            }
        }
        makeMath();
    </script>
    <input id="user"></input>
    <div onclick="enable()" id="enable">
        <button style="color: white; background-color: #d64181;">Go</button>
    </div>
    

    someone could get the answer too in the console, but only humans know that, right? 😉

Comments are closed.