phpajaxwordpresswoocommerceuser-roles

Add a fee for specific user roles when "Ship to a different address?" has been checked on WooCommerce checkout


I have a wholesale site with different user roles & want to allow employees to start ordering online from here also.

I want to only add a $5 fee if the user roles 'team' and 'team2' select ship to a different address (they get free shipping if sent to their billing address).

No other user role should see the fee if selecting the ship to a different address.

This is the closest solution I've found to make this happen but need help configuring this code to apply to only those two user roles and no one else.

// send as gift for Team & Team2 role add $5 fee
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
    // Only on checkout page for Order notes field
    if( 'ship_to_different_address' === $key && is_checkout() ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}

// Ajax / jQuery script
add_action( 'wp_footer', 'ship_to_different_address_script' );
function ship_to_different_address_script() {
    // On checkoutpage
    if( ( is_checkout() && ! is_wc_endpoint_url() ) ) :
        ?>
        <script type="text/javascript">
            jQuery( function($){
                if (typeof woocommerce_params === 'undefined')
                    return false;

                console.log('defined');

                $('input[name=ship_to_different_address]').click( function(){
                    var fee = $(this).prop('checked') === true ? '1' : '';

                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'ship_to_different_address',
                            'ship_to_different_address': fee,
                        },
                        success: function (result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                        },
                    });
                });
            });
        </script>
    <?php
    endif;
}

// Get the ajax request and set value to WC session
add_action( 'wp_ajax_ship_to_different_address', 'get_ajax_ship_to_different_address' );
add_action( 'wp_ajax_nopriv_ship_to_different_address', 'get_ajax_ship_to_different_address' );
function get_ajax_ship_to_different_address() {
    if ( isset($_POST['ship_to_different_address']) ) {
        WC()->session->set('ship_to_different_address', ($_POST['ship_to_different_address'] ? '1' : '0') );
        echo WC()->session->get('ship_to_different_address');
    }
    die();
}

// Add / Remove a custom fee
add_action( 'woocommerce_cart_calculate_fees', 'add_remove_ship_to_different_address', 10, 1 );
function add_remove_ship_to_different_address( $cart )
{
    // Only on checkout
    if ((is_admin() && !defined('DOING_AJAX')) || is_cart())
        return;

    $fee_amount = 5.00;

    if (WC()->session->get('ship_to_different_address'))
        $cart->add_fee(__('Shipping fee', 'woocommerce'), $fee_amount);
}

Solution

  • Your code contains some mistakes, missing pieces, and unnecessary steps.

    This answer shows (without any user restrictions) how to add a fee when "Ship to a different address?" has been checked:

    // The jQuery Ajax request
    function action_wp_footer() {
        // Only checkout page
        if ( is_checkout() && ! is_wc_endpoint_url() ) :
    
        // Remove "ship_different" custom WC session on load
        if ( WC()->session->get( 'ship_different' ) ) {
            WC()->session->__unset( 'ship_different' );
        }
        
        // jQuery Ajax code below
        ?>
        <script type="text/javascript">
        jQuery( function($) {
            if ( typeof wc_checkout_params === 'undefined' )
                return false;
    
            var a = '#ship-to-different-address-checkbox', b = '';
    
            // Ajax function
            function triggerSTDA( value ) {
                 $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action': 'ship_different_address',
                        'ship_different': value,
                    },
                    success: function (result) {
                        $( 'body' ).trigger( 'update_checkout' );
                        // console.log( result ); // For testing (to be removed)
                    }
                });
            }
    
            $( a ).on( 'change', function() {
                b = $( this ).prop('checked') === true ? 'yes' : 'no';
                triggerSTDA( b );
            });
        });
        </script>
        <?php
        endif;
    }
    add_action( 'wp_footer', 'action_wp_footer' );
    
    // The Wordpress Ajax PHP receiver
    function get_ajax_ship_different_address() {
        if ( isset( $_POST['ship_different'] ) ) {
            WC()->session->set( 'ship_different', esc_attr( $_POST['ship_different'] ) );
            echo $_POST['ship_different'];
        }
        
        die();
    }
    add_action( 'wp_ajax_ship_different_address', 'get_ajax_ship_different_address' );
    add_action( 'wp_ajax_nopriv_ship_different_address', 'get_ajax_ship_different_address' );
    
    // Add / remove a custom fee
    function action_woocommerce_cart_calculate_fees( $cart ) {
        // Only on checkout
        if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || is_cart() )
            return;
    
        $fee_amount = 5;
    
        if ( WC()->session->get( 'ship_different' ) == 'yes' ) {
            $cart->add_fee( __( 'Shipping fee', 'woocommerce'), $fee_amount );
        }
    }
    add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
    

    However, your question was to only apply this based on certain user roles:

    So you get:

    // The jQuery Ajax request
    function action_wp_footer() {
        // Only for logged in users
        if ( ! is_user_logged_in() )
            return;
        
        // Only checkout page
        if ( is_checkout() && ! is_wc_endpoint_url() ) :
    
        // Remove "ship_different" custom WC session on load
        if ( WC()->session->get( 'ship_different' ) ) {
            WC()->session->__unset( 'ship_different' );
        }
        
        // jQuery Ajax code below
        ?>
        <script type="text/javascript">
        jQuery( function($) {
            if ( typeof wc_checkout_params === 'undefined' )
                return false;
    
            var a = '#ship-to-different-address-checkbox', b = '';
    
            // Ajax function
            function triggerSTDA( value ) {
                 $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action': 'ship_different_address',
                        'ship_different': value,
                    },
                    success: function (result) {
                        $( 'body' ).trigger( 'update_checkout' );
                        // console.log( result ); // For testing (to be removed)
                    }
                });
            }
    
            $( a ).on( 'change', function() {
                b = $( this ).prop('checked') === true ? 'yes' : 'no';
                triggerSTDA( b );
            });
        });
        </script>
        <?php
        endif;
    }
    add_action( 'wp_footer', 'action_wp_footer' );
    
    // The Wordpress Ajax PHP receiver
    function get_ajax_ship_different_address() {
        if ( isset( $_POST['ship_different'] ) ) {
            WC()->session->set( 'ship_different', esc_attr( $_POST['ship_different'] ) );
            echo $_POST['ship_different'];
        }
        
        die();
    }
    add_action( 'wp_ajax_ship_different_address', 'get_ajax_ship_different_address' );
    add_action( 'wp_ajax_nopriv_ship_different_address', 'get_ajax_ship_different_address' );
    
    // Add / remove a custom fee
    function action_woocommerce_cart_calculate_fees( $cart ) {
        // Only on checkout
        if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || is_cart() )
            return;
        
        // Only for logged in users
        if ( ! is_user_logged_in() )
            return;
    
        // Get current WP_User Object
        $user = wp_get_current_user();
        
        // Roles to check, adapt to your specific needes
        $roles_to_check = array( 'team', 'team2', 'administrator' );
        
        // User roles
        $roles = ( array ) $user->roles;
        
        // Compare
        $compare = array_diff( $roles, $roles_to_check );
    
        // Result is empty
        if ( empty ( $compare ) ) {
            // Amount
            $fee_amount = 5;
    
            if ( WC()->session->get( 'ship_different' ) == 'yes' ) {
                $cart->add_fee( __( 'Shipping fee', 'woocommerce'), $fee_amount );
            }
        }
    }
    add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
    

    Partly used in this answer