Set product variation custom calculated price dynamically in WooCommerce

I am trying to dynamically add to a products price when a user checks out based on what they have entered in the product page. The setting of the price is only working on a non variation product.

I need to be able to set the price on the variations of the products as well.

The code that I am using:

function add_cart_item_data( $cart_item_meta, $product_id, $variation_id ) {
    $product = wc_get_product( $product_id );
    $price = $product->get_price();

    $letterCount = strlen($_POST['custom_name']);
    $numberCount = strlen($_POST['custom_number']);

    if($letterCount != '0') {

        $letterPricing = 20 * $letterCount;
        $numberPricing = 10 * $numberCount;

        $additionalPrice = $letterPricing + $numberPricing;

        $cart_item_meta['custom_price'] = $price + $additionalPrice;
    }
    return $cart_item_meta;
}

function calculate_cart_total( $cart_object ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
       return;
    }

    foreach ( $cart_object->cart_contents as $key => $value ) {
        if( isset( $value['custom_price'] ) ) {
            $price = $value['custom_price'];
            $value['data']->set_price( ( $price ) );
        }
    }
}

1 answer

  • answered 2018-03-13 22:52 LoicTheAztec

    I have completely revisited your code:

    // Set custom data as custom cart data in the cart item
    add_filter( 'woocommerce_add_cart_item_data', 'add_custom_data_to_cart_object', 30, 3 );
    function add_custom_data_to_cart_object( $cart_item_data, $product_id, $variation_id ) {
        if( ! isset($_POST['custom_name']) || ! isset($_POST['custom_number']) )
            return $cart_item_data; // Exit
    
        if( $variation_id > 0)
            $product = wc_get_product( $variation_id );
        else
            $product = wc_get_product( $product_id );
    
        $price = $product->get_price();
    
        // Get the data from the POST request and calculate new custom price
        $custom_name = sanitize_text_field( $_POST['custom_name'] );
        if( strlen( $custom_name ) > 0 )
            $price += 20 * strlen( $custom_name );
        $custom_number = sanitize_text_field( $_POST['custom_number'] );
        if( strlen( $custom_number ) > 0 )
            $price += 10 * strlen( $custom_number );
    
        // Set new calculated price as custom cart item data
        $cart_item_data['custom_data']['price'] = $price;
    
        return $cart_item_data;
    }
    
    // Set the new calculated price of the cart item
    add_action( 'woocommerce_before_calculate_totals', 'set_new_cart_item_price', 50, 1 );
    function set_new_cart_item_price( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        foreach ( $cart->get_cart() as $cart_item ) {
            if( isset( $cart_item['custom_data']['price'] ) ) {
                // Get the new calculated price
                $new_price = (float) $cart_item['custom_data']['price'];
    
                // Set the new calculated price
                $cart_item['data']->set_price( $new_price );
            }
        }
    }
    

    This code goes on function.php file of your active child theme (or theme).

    Tested and works as well with product variations.