Search code examples
phpwoocommercecartuser-roleswoocommerce-checkout-fields

WooCommerce Checkout - Validate User Role and Cart Contents


I'm facing a challenge with WooCommerce's checkout process.

I use the "B2B for WooCommerce" plugin to differentiate between regular products and B2B product. Here's the scenario:

1 - A unregistered visitor adds products from the "Regular" category (available by default to unregistered visitors) to their cart.

2 - On the checkout page, the visitor decides to register as a B2B client (by form select field on the checkout page).

3 - The registration and checkout processes occur simultaneously on this single page.

I want to prevent the order from being placed if a user is registering as a B2B client and has "Regular" products in their cart. Since both actions (registration and checkout) happen at once, typical WooCommerce hooks aren't working as expected.

How can I validate the user role being registered and the cart contents during checkout process and prevent the order if the conditions are met? Or maybe there's a better, simpler way to do this?

I've tried a function to reset the cart and reload the page.

Edit:

User Role: Wwp_wholesaler

I've created two WooCommerce product categories: Normal and Wholesale. The "Normal" one is visible to all visitors. The "Wholesale" becomes visible to "Wwp_wholesaler" after they register with that role.

The name attribute of the select field is: "afreg_select_user_role". The value attributes for the options are "customer" for regular customers and "wwp_wholesaler" for wholesalers.


Solution

  • The following code will early stop the checkout process when a B to B customer is detected with regular items in cart. In that case, the regular items will be removed from cart throwing an error message, avoiding placing the order.

    enter image description here

    Note: The provided user role slug is wrong, as user role slugs doesn't have capitals.

    The code:

    add_action( 'woocommerce_checkout_create_order', 'process_checkout_creating_order',  10, 2  );
    function process_checkout_creating_order( $order, $data ) {
        global $current_user;
    
        $targeted_field = 'afreg_select_user_role'; // Checkout field key to target
        $targeted_role  = 'wwp_wholesaler'; // User role slug (for B to B)
        $targeted_term  = 'Normal'; // Category term for Regular items
    
        // Targeting B to B user role only
        if( ( isset($data[$targeted_field]) && $data[$targeted_field] === $targeted_role ) 
        || in_array( $targeted_role, $current_user->roles ) ) {
            $cart = WC()->cart; //  Cart live object
            $item_keys_found = array(); // Initializing
    
            // Loop through cart items to search for "regular" items
            foreach ( $cart->get_cart() as $item_key => $item ) {
                if ( has_term( $targeted_term, 'product_cat', $item['product_id']) ) {
                    $item_keys_found[] = $item_key;
                }
            }
            // If regular items are found
            if ( count($item_keys_found) > 0 ) {
                // Loop through regular item keys (and remove each)
                foreach ( $item_keys_found as $item_key ) {
                    $cart->remove_cart_item( $item_key );
                }
                // Throw an error message, avoiding saving and processing the order
                throw new Exception( 
                    sprintf( __('You are not allowed to purchase "Regular" items.'.
                    ' %d "Regular" %s been removed from cart. %s', 'woocommerce'),
                        count($item_keys_found),
                        _n('item has', 'items have', count($item_keys_found), 'woocommerce'),
                        sprintf( '<a href="%s" class="button">%s</a>', get_permalink(wc_get_page_id('shop')), __('Continue shopping', 'woocommerce') )
                ) );
            }
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and work.