phpwordpresswoocommercecheckboxdiscount

Product page custom checkbox enable a percentage discount on WooCommerce cart subtotal


The goal is simple, add a checkbox to the WooCommerce Product Page. If the user checks the checkbox, a 5% discount is applied on cart subtotal.

I have checked and doubled checked the code like ten times, I just cannot figure out why it gives me the "Fatal Error".

This is the code:

add_action( 'woocommerce_after_add_to_cart_button', 'ls_automatic_discount_checbox', 10 );
function ls_automatic_discount_checbox() {
    echo '<p><label><input type="checkbox" name="apply_automatic_discount" value="1"/> Apply 5% discount to your subtotal</label></p>';
}

add_action( 'woocommerce_cart_calculate_fees', 'ls_apply_discount_on_checkbox_check', 10, 7 );
function ls_apply_discount_on_checkbox_check( $cart, $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {

        // makes sure that the checkbox is ticked
        if ( isset( $_POST[ 'apply_automatic_discount' ] ) && $_POST[ 'apply_automatic_discount' ] == 1 ) {        

        // if it is, check what the percentaged discount on the subtotal is
        $percent = 5;

        // if all checks out - give the discount
        if ( isset ( $percent ) && $percent > 0 ) {

        // customer gets a discount of 5% of the SUBTOTAL
        $discount = $cart->cart_contents_total * $percent / 100;
        $cart->add_fee( __('5% OFF', 'woocommerce' ) . " (" . $percent . "%)", -$discount);
    
        }
    }
}

Solution

  • There are some missing things and mistakes in your code:

    The code:

    add_action( 'woocommerce_after_add_to_cart_button', 'ls_automatic_discount_checbox', 10 );
    function ls_automatic_discount_checbox() {
        printf( '<p class="auto-discount"><label><input type="checkbox" name="auto_discount" value="1"/> %s</label></p>', 
            __('Apply 5% discount to your subtotal', 'woocommerce') );
    }
    
    // Add custom cart item data
    add_filter('woocommerce_add_cart_item_data', 'add_custom_field_value_to_cart_item_data', 10, 2);
    function add_custom_field_value_to_cart_item_data($cart_item_data, $product_id) {
        $cart_item_data['auto_discount'] = isset($_POST['auto_discount']) ? '1' : '0';
        return $cart_item_data;
    }
    

    Now you can add a discount globally or by product (where the checkbox has been checked):

    A/. Globally (on the cart subtotal):

    add_action( 'woocommerce_cart_calculate_fees', 'auto_applied_product_discount', 10 );
    function auto_applied_product_discount( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        $auto_discount = false; // Initializing
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( isset($cart_item['auto_discount']) && $cart_item['auto_discount'] ) {
                $auto_discount = true;
                break; // Stop the loop
            }
        }
        
        if ( $auto_discount ) {
            $percent  = 5;
            $total    = $cart->cart_contents_total;
            $cart->add_fee( __('5% OFF', 'woocommerce' ) . " (" . $percent . "%)", -($total * $percent / 100));
        }
    }
    

    B/. By product subtotal (where the checkbox has been checked):

    add_action( 'woocommerce_cart_calculate_fees', 'auto_applied_product_discount', 10 );
    function auto_applied_product_discount( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        $total = 0; // Initializing
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( isset($cart_item['auto_discount']) && $cart_item['auto_discount'] ) {
                $total += $cart_item['line_total'];
            }
        }
        
        if ( $total > 0 ) {
            $percent  = 5;
            $cart->add_fee( __('5% OFF', 'woocommerce' ) . " (" . $percent . "%)", -($total * $percent / 100));
        }
    }
    

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