Hooking After Validation but Before Order Create in Woocommerce Checkout

13,620

Solution 1

I was able to figure this out finally, Its more of a workaround since I don't think there is a clear way to do this.

As soon as the "Place Order" button is clicked, we use the checkout_place_order event to place a hidden field with a value set to 1.

var checkout_form = $('form.checkout');

checkout_form.on('checkout_place_order', function () {
    if ($('#confirm-order-flag').length == 0) {
        checkout_form.append('<input type="hidden" id="confirm-order-flag" name="confirm-order-flag" value="1">');
    }
    return true;
});

Next, we use the hook woocommerce_after_checkout_validation to check our hidden input and if the value is 1 add in error (This stops the order from going through).

function add_fake_error($posted) {
    if ($_POST['confirm-order-flag'] == "1") {
        wc_add_notice( __( "custom_notice", 'fake_error' ), 'error');
    } 
}

add_action('woocommerce_after_checkout_validation', 'add_fake_error');

Last, we use the checkout_error event to determine if there was a real validation or if if there is only 1 error, the error we added. If there is only 1 error it means validation passed so we can show our modal (or whatever you need to do).

$(document.body).on('checkout_error', function () {
    var error_count = $('.woocommerce-error li').length;

    if (error_count == 1) { // Validation Passed (Just the Fake Error I Created Exists)
        // Show Confirmation Modal or Whatever
    }else{ // Validation Failed (Real Errors Exists, Remove the Fake One)
        $('.woocommerce-error li').each(function(){
            var error_text = $(this).text();
            if (error_text == 'custom_notice'){
                $(this).css('display', 'none');
            }
        });
    }
});

Inside my modal I have a confirm button that sets our hidden field value to nothing and clicks the place order button again. This time the order will go through because we are checking for the hidden input value of 1.

$('#confirm-order-button').click(function () {
    $('#confirm-order-flag').val('');
    $('#place_order').trigger('click');
});

Solution 2

As far as I know, there is no hooks in between validation and order creation process, that will allow you to interact with customer, making some actions.

Using jQuery and Sweet Alert component (SWAL 2), here is an example of code that will disable the "Place Order" button displaying a Sweet Alert with confirmation buttons. It's not perfect, but it answers partially your question.

Once customer will confirm, the "Place Order" button will be enabled back and it will be triggered by the code… If the customer use the cancel button, Checkout review order will be refreshed (Ajax).

The code:

add_action( 'wp_footer', 'checkout_place_order_script' );
function checkout_place_order_script() {
    // Only checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ):

    // jQuery code start below
    ?>
    <script src="https://unpkg.com/[email protected]/dist/sweetalert2.all.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/polyfill.min.js"></script>
    jQuery( function($){
        var fc = 'form.checkout',
            pl = 'button[type="submit"][name="woocommerce_checkout_place_order"]';

        $(fc).on( 'click', pl, function(e){
            e.preventDefault(); // Disable "Place Order" button

            // Sweet alert 2
            swal({
                title:  'Are you sure?',
                text:   "You are about proceed the order",
                type:   'success',
                showCancelButton:   true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor:  '#d33',
                confirmButtonText:  "Yes let's go!"
            }).then((result) => {
                if (result.value) {
                    $(fc).off(); // Enable back "Place Order button
                    $(pl).trigger('click'); // Trigger submit
                } else {
                    $('body').trigger('update_checkout'); // Refresh "Checkout review"
                }
            });
        });
    });
    </script>
    <?php
    endif;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here

Solution 3

I'm late to the party, but wanted to share a variation of the answers above

jQuery(document).ready(function($){

    /* on submit */
    $('form#FORMID').submit( function(e) {

        /* stop submit */
        e.preventDefault();

        /* count validation errors */
        var error_count = $('.woocommerce-error li').length;

        /* see if terms and conditions are accepted */
        var terms = $('input#terms').is(':checked');

        /* if there are no validation errors and terms are accepted*/
        if( error_count == 0 && terms ) { 

            /* trigger confirmation dialogue */
            if( confirm('Are you sure?') ){

                /* resume default submit */
                $(this).unbind('submit').submit();

            } else {

                /* do nothing */
                e.stopPropagation();

            }
        }

    });
});
Share:
13,620
RiddleMeThis
Author by

RiddleMeThis

Apparently, this user ...

Updated on June 24, 2022

Comments

  • RiddleMeThis
    RiddleMeThis almost 2 years

    I am trying to create a step in checkout to confirm your order. I'm thinking when the place order button is clicked AND the checkout fields are valid I could run some JS to show a modal or whatever.

    Is there a JS trigger/event similar to checkout_place_order that runs after validation? For example, I can use the following but it happens before validation. Maybe there is a way to trigger validation from inside there and display my modal based off that?

    var checkout_form = $('form.checkout');
    
    checkout_form.on('checkout_place_order', function () {
    
        // do your custom stuff
    
        return true; // continue to validation and place order
        return false; // doesn't validate or place order
    });
    

    There is also the woocommerce_after_checkout_validation hook but I am not sure how to utilize it to achieve what I'm after.

    I am open to ideas...

  • RiddleMeThis
    RiddleMeThis over 5 years
    I'm not a huge fan of using that alert box but the main problem with your example is it doesn't happen after validation so it makes for an awkward experience if there is an error.
  • RiddleMeThis
    RiddleMeThis over 5 years
    Do you know a way to makes this run only after the form is valid? Or a way to trigger validation to run?
  • user3514052
    user3514052 almost 2 years
    OMG, thank you sooo much! After a full day of testing i found a working solution!