Michael
Michael

Reputation: 13

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 ) );
        }
    }
}

Upvotes: 1

Views: 1988

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 253939

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;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        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.

Upvotes: 1

Related Questions