phpwordpresswoocommercecart

WooCommerce Price overriding not working


I have set up a hidden input item using woocommerce_before_add_to_cart_button hook

function add_gift_wrap_field() {
    ?>`<input type="hidden" id="price_val" name="added_price" value="100.34">`<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );

Saving fields against the product:

function save_gift_wrap_fee( $cart_item_data, $product_id ) {

    if( isset( $_POST['added_price'] ) ) {

        $cart_item_data = array();

        $cart_item_data[ "gift_wrap_fee" ] = "YES"; 
        $cart_item_data[ "gift_wrap_price" ] = 100;     
    }
    return $cart_item_data;

}
add_filter( 'woocommerce_add_cart_item_data', 'save_gift_wrap_fee', 99, 2 );

Now I can echo out the $_POST['added_price'] inside this woocommerce_before_calculate_totals hook.

The code I written is shown below:

function calculate_gift_wrap_fee( $cart_object ) {
    if( !WC()->session->__isset( "reload_checkout" )) {
        /* Gift wrap price */
        $additionalPrice = number_format($_POST['added_price'], 2); 

        $additionalPrice = floatval($additionalPrice);
        //echo $additionalPrice; exit(); shows the value
        foreach ( $cart_object->cart_contents as $key => $value ) {
            if( isset( $value["gift_wrap_fee"] ) ) {
                    /* Woocommerce 3.0 + */
                    $orgPrice = floatval( $value['data']->get_price() );
                    $value['data']->set_price( $orgPrice + $additionalPrice );    //not adding the $additionalPrice here.     
            }
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 99 );

What am I doing wrong here?


Solution

  • Here is the complete clean, tested and working solution based on your code question.

    Here I have included your custom field key/value in the cart object for the related cart item, instead of getting the Post value in your calculate_gift_wrap_fee() function.

    This way it's not possible to loose the custom field value and the new price calculation is reliable.

    I have commented 'gift_wrap_fee' and 'gift_wrap_price' as they are not really needed now (but you can uncomment them if you like).

    Here is this code:

    // The hidden product custom field
    add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
    function add_gift_wrap_field() {
        ?>
            <input type="hidden" id="price_val" name="added_price" value="100.34">
        <?php
    }
    
    // Adding the custom field to as custom data for this cart item in the cart object
    add_filter( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
    function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
        $bool = false;
        $data = array();
        if( ! empty( $_REQUEST['added_price'] ) ) {
            $cart_item_data['custom_data']['added_price'] = $_REQUEST['added_price'];
            // Below this 2 values are not really needed (I think)
            // (You can uncomment them if needed)
    
            ## $cart_item_data['custom_data']['gift_wrap_fee'] = 'YES';
            ## $cart_item_data['custom_data']['gift_wrap_price'] = 100;
    
            // below statement make sure every add to cart action as unique line item
            $cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
            WC()->session->set( 'custom_data', $data );
        }
        return $cart_item_data;
    }
    
    // Changing the cart item price based on custom field calculation
    add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 10, 1 );
    function calculate_gift_wrap_fee( $cart ) {
    
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Iterating though cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            // Continue if we get the custom data for the current cart item
            if( ! empty( $cart_item['custom_data'] ) ){
                // Get the custom field "added price" value
                $added_price = number_format( $cart_item['custom_data']['added_price'], 2 );
                // The WC_Product object
                $product = $cart_item['data'];
                // Get the price (WooCommerce versions 2.5.x to 3+)
                $product_price = method_exists( $product, 'get_price' ) ? floatval(product->get_price()) : floatval($product->price);
                // New price calculation
                $new_price = $product_price + $added_price;
                // Set the calculeted price (WooCommerce versions 2.5.x to 3+)
                method_exists( $product, 'set_price' ) ? $product->set_price( $new_price ) : $product->price = $new_price;
            }
        }
    }
    

    Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

    This code is tested and works on WooCommerce versions from 2.5.x to 3+.