WooCommerce custom Ajax add to cart: How to set a custom price?

Viewed 1564

I am trying to add a product from an on_click event at checkout. That product's price is calculated dynamically with an external API so it is registered as having a price of 0 in woocommerce itself. I am trying to add this product to the cart (working) and then set that product's price to the one I receive from the API (not working). Here is the relevant code:

AJAX call on click:

       jQuery('#theftdaminsurance').on('click', function(){
        jQuery.ajax({
        type: "POST",
        url: "/wp-admin/admin-ajax.php",
        data: {
            action: 'add_product_to_cart_checkout',
            // add your parameters here
            price: <?php echo $year_dam_price; ?>,
            productid: ins_product_id
        },
        success: function (output) {
        document.getElementById("loaderdiv").style.display = "none";
        jQuery(document.body).trigger("update_checkout");
        }
        });
        });

I checked everything here and the call is made properly with all the right info being passed on. Here is the function being called:

add_action('wp_ajax_add_product_to_cart_checkout', 'add_product_to_cart_checkout');

// register the ajax action for unauthenticated users
add_action('wp_ajax_nopriv_add_product_to_cart_checkout', 'add_product_to_cart_checkout');

function add_product_to_cart_checkout() {
    $product_id = $_REQUEST['productid'];
    $price = floatval($_REQUEST['price']);
    $ebike_ids = array(17386,17385,17382,17378,17375,17372,17370,17369,17364,16132,16130,4561,4550,3490,2376);
    $found = false;
    //check if there is something in cart
    if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
        //Delete all preexisting insurance products and find qty of ebikes
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            $product_idebike = $cart_item['product_id'];
            if ( ($cart_item['product_id'] == "16600") || ($cart_item['product_id'] == "16653") || ($cart_item['product_id'] == "16654") || ($cart_item['product_id'] == "16655") ||($cart_item['product_id'] == "16659") || ($cart_item['product_id'] == "16660")) {
                        WC()->cart->remove_cart_item( $cart_item_key );
            }           
        //get ebike quantity
    for ($x = 0; $x <= 14; $x++) {
        if ($product_idebike == $ebike_ids[$x]) {
            $quantity =  $cart_item['quantity'];
            break;
        }
    }
        }
            // if command is not to remove add relevant products
                if ($price != "-1") {
                WC()->cart->add_to_cart( $product_id, $quantity );
                foreach( WC()->cart->get_cart() as $cart_item ){
                    $id = $cart_item['product_id'];
                    if ($product_id == $id) {
                        $cart_item['data']->set_price( $price );
                    }
                }
                }
            
    }

}

Here I basically debugged everythingcarefully and everything behaves as it should but the set_price function. I cannot get it to update the product's price to the one passed in the AJAX call. The price remains 0 once the checkout is updated and before it is as well. Am i calling or using this function the wrong way?

Thanks a lot for your help!

1 Answers

It seems that you are making things much more complicated than they should be on your Ajax receiver function…

Note that you can add custom cart item data when using WC_Cart add_to_cart() method, so you will add your insurance price as custom cart item data and afterwards use it to set the price.

Here is your revisited Ajax PHP receiver function:

add_action('wp_ajax_add_product_to_cart_checkout', 'add_product_to_cart_checkout');
add_action('wp_ajax_nopriv_add_product_to_cart_checkout', 'add_product_to_cart_checkout');
function add_product_to_cart_checkout() {
    if ( isset($_POST['productid']) && isset($_POST['price']) && ! WC()->cart->is_empty() ) {
        $product_id     = intval($_POST['productid']);
        $price          = floatval($_POST['price']);
        $ebike_ids      = array(17386,17385,17382,17378,17375,17372,17370,17369,17364,16132,16130,4561,4550,3490,2376);
        $insurance_ids  = array(16600,16653,16654,16655,16659,16660);
        $found          = false;
        $ebike_quantity = 0;

        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            // Delete all preexisting insurance products
            if ( in_array( $cart_item['product_id'],  $insurance_ids ) ) {
                WC()->cart->remove_cart_item( $cart_item_key );
            }

            // Get ebikes total quantity
            if ( in_array( $cart_item['product_id'],  $ebike_ids ) ) {
                $ebike_quantity +=  $cart_item['quantity'];
            }
        }

        // If command is not to remove add insurance product with price as custom cart item data
        if ( $price >= 0 && $cart_item['insurance_price'] > 0 ) {
            WC()->cart->add_to_cart( $product_id, $ebike_quantity, 0, array(), array( 'insurance_price' => $price ) );
        }
        die();
    }
}

Then to set the price you will use:

// Set insurance price from custom cart item data
add_action( 'woocommerce_before_calculate_totals', 'set_insurance_price' );
function set_insurance_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
       return;

    foreach ( $cart->get_cart() as $cart_item ) {
        if( isset($cart_item['insurance_price']) && $cart_item['insurance_price'] > 0 ) {
            $cart_item['data']->set_price( $cart_item['insurance_price'] );
        }
    }
}

Now It should works.

Related