Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hooking After Validation but Before Order Create in Woocommerce Checkout

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...

like image 387
RiddleMeThis Avatar asked Oct 09 '18 17:10

RiddleMeThis


2 Answers

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');
});
like image 151
RiddleMeThis Avatar answered Oct 07 '22 19:10

RiddleMeThis


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

like image 36
LoicTheAztec Avatar answered Oct 07 '22 21:10

LoicTheAztec