在验证之后但在 Woocommerce 结帐中创建订单之前挂钩

Posted

技术标签:

【中文标题】在验证之后但在 Woocommerce 结帐中创建订单之前挂钩【英文标题】:Hooking After Validation but Before Order Create in Woocommerce Checkout 【发布时间】:2019-03-14 13:30:46 【问题描述】:

我正在尝试在结帐中创建一个步骤来确认您的订单。我在想,当点击下单按钮并且结帐字段有效时,我可以运行一些 JS 来显示模式或其他内容。

是否有类似 checkout_place_order 的 JS 触发器/事件在验证后运行?例如,我可以使用以下内容,但它发生在验证之前。也许有一种方法可以从内部触发验证并据此显示我的模式?

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
);

还有 woocommerce_after_checkout_validation 钩子,但我不知道如何利用它来实现我所追求的。

我对想法持开放态度...

【问题讨论】:

【参考方案1】:

我终于能够弄清楚这一点,它更像是一种解决方法,因为我认为没有明确的方法可以做到这一点。

单击“下订单”按钮后,我们使用 checkout_place_order 事件放置一个隐藏字段,其值设置为 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;
);

接下来,我们使用钩子 woocommerce_after_checkout_validation 来检查我们隐藏的输入,如果值为 1,则添加错误(这会阻止订单通过)。

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');

最后,我们使用 checkout_error 事件来确定是否有真正的验证,或者如果只有 1 个错误,我们添加的错误。如果只有 1 个错误,则表示验证通过,因此我们可以显示我们的模式(或您需要做的任何事情)。

$(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');
            
        );
    
);

在我的模式中,我有一个确认按钮,它将我们的隐藏字段值设置为空,然后再次单击下订单按钮。这次订单将通过,因为我们正在检查隐藏的输入值 1。

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

【讨论】:

【参考方案2】:

据我所知,验证和订单创建过程之间没有任何挂钩,这将允许您与客户互动,进行一些操作。

使用 jQuery 和 Sweet Alert 组件 (SWAL 2),下面是一个代码示例,它将禁用显示带有确认按钮的 Sweet Alert 的“Place Order”按钮。它并不完美,但它部分回答了您的问题。

一旦客户确认,“Place Order”按钮将被启用并由代码触发...如果客户使用取消按钮,Checkout review order 将被刷新(Ajax)。

代码:

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/sweetalert2@8.8.1/dist/sweetalert2.all.min.js"></script>
    <script src="https://unpkg.com/promise-polyfill@8.1.0/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;

代码进入您的活动子主题(或活动主题)的 function.php 文件中。经过测试并且可以工作。

【讨论】:

我不太喜欢使用该警报框,但您的示例的主要问题是它不会在验证后发生,因此如果出现错误,它会带来尴尬的体验。跨度> 您知道只有在表单有效后才能运行的方法吗?还是触发验证运行的方法?【参考方案3】:

我迟到了,但想分享上述答案的变体

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();

            
        

    );
);

【讨论】:

【参考方案4】:

在这种情况下,我为自己做出了一个快速而简单的 JS 决策(有 woocommerce 和条带形式)。这是基于阻止结帐按钮提交但仍会进行表单验证。

// making the wrap click event on dinamic element

$('body').on('click', 'button#place_order_wrap', function(event)  

    // main interval where all things will be 

    var validatoins = setInterval(function() happen

        // checking for errors

        if(no_errors==0) 

        // making the setTimeout() function with limited time like 200ms 
        // to limit checkout function for just make verification

        setTimeout(function() 

            // triggering original button

            $('button#place_order').click(); 

            // if there some errors, stop the interval, return false

            if(($('element').find('ul.woocommerce_error').length!==0)||($('element').find('.woocommerce-invalid-required-field').length!==0)) 

                    clearInterval(validatoins);
                    return false;

                else

                    no_errors=1;

                
            , 200);
        


        if(no_errors==1)    

            // same error checking

            if($('#step5').find('ul.woocommerce_error').length!=0||($('#step5').find('.woocommerce-invalid-required-field').length!==0)) 

                // if there some errors, stop the interval, return false

                clearInterval(validatoins);
                return false; 
            


            setTimeout(function()

                // if no errors

                if(($('#step5').find('ul.woocommerce_error').length==0)&&($('#step5').find('.woocommerce-invalid-required-field').length==0)) 

                    // do something, mark that finished

                    return false;
                
            , 1000);


            // if something finished

            if() 

                setTimeout(function()

                    // trigger original checkout click

                    $('button#place_order').click(); 
                    clearInterval(validatoins);
                , 1000);

            

        

    , 1000);

【讨论】:

以上是关于在验证之后但在 Woocommerce 结帐中创建订单之前挂钩的主要内容,如果未能解决你的问题,请参考以下文章

避免在 WooCommerce 结帐中进行计费电话验证

验证 woocommerce 中的结帐字段

在Woocommerce结帐页面中设置唯一的验证错误通知

WooCommerce - 禁用邮政编码验证

验证 WooCommerce 结帐页面中的附加复选框字段

隐藏 WooCommerce 结帐字段后删除所需的验证