Search code examples
phpwordpresswoocommercehook-woocommercecheckout

Prevent Place Order using woocommerce_checkout_process


Is there a way to stop the Place Order from going forward using the woocommerce_checkout_process action?

If woocommerce_checkout_process was a filter then returning something like false would probably stop the process, but since this is an action, returning anything is ignored.

Upon running the woocommerce_checkout_process action, I want to:

  1. Check all items in cart, and
  2. Check all fields filled in by customer (name, address, phone, etc), and
  3. If certain criteria is not met, send an error message to customer saying that they can not place an order until they have completed criteria xyz.

Is there something that can be set within WooCommerce variables to stop the order from proceeding from woocommerce_checkout_process action?

Also, how would I grab the current order items and customer info during this action?

Thanks


Solution

  • To stop the checkout process, there are a lot of different hooks that you can use and they are all action hooks:

    1). woocommerce_checkout_process hook is mostly used with custom checkout fields for validation, using the $_POST variable to check that custom fields, allowing to stop the checkout process using an error notice, like in this basic example:

    add_action('woocommerce_checkout_process', 'custom_checkout_field_validation');
    function custom_checkout_field_validation() {
        if ( isset($_POST['custom_field']) && ! empty($_POST['custom_field']) ) {
            wc_add_notice(__('Invalid <strong>Custom field</strong>, please check ...'), 'error');
        }
    }
    

    You can also check with this hook:

    • Everything that goes through the $_POST variable,
    • The WC_Cart Object and all cart items,
    • The WC_Session data

    This hook is triggered before the WC_Order object creation.


    2). woocommerce_checkout_create_order action hook has 2 parameters $order and $data. It is triggered after the fields validation. In this hook, the WC_Order object exist with all the data, but it's not yet saved to the database.

    It allows to stop the checkout process like in this answer, by using something like this basic code:

    add_action( 'woocommerce_checkout_create_order', 'process_checkout_creating_order',  10, 2  );
    function process_checkout_creating_order( $order, $data ) {
        if( ! $order->get_billing_company() ) {
            throw new Exception( __("My error text") );
        }
    }
    
    

    You can:

    • Change the order data,
    • Check cart items,
    • Check the WC_Session data.

    Now for order items (before order is saved), is better to use the following hooks, depending on the item type:

    With that order items hooks, you can use throw new Exception() to stop the checkout process, displaying an error notice.


    1. woocommerce_checkout_order_created hook has $order as unique argument. Here, The WC_Order exist and has been saved to database, with a "pending" status.

    You can stop the checkout process by using throw new Exception().
    You can check the WC_Order data, the cart items, and the WC_Session data.
    You can change the WC_Order data, by using all available setter methods.

    The problem here is that as the order has been created and saved, and if you stop the checkout process, and if the customer place again an his order, another order is created and saved in the database...


    Related: What is the last hook triggered before an order is created in WooCommerce?