Пользовательская цена продукта в Woocommerce

Иногда нужно чтобы продукт в Woocommerce имел не заданную стоимость продукта, а ту которую ввел пользователь, например для сбора пожертвований.

Для этого нужно создать для каждого элемента дополнительное поле (например custom_price) с новой ценой, и при подсчете стоимости корзины с помощью хука woocommerce_before_calculate_totals установить для каждого элемента корзины стоимость из дополнительного поля с новой ценой.

В файле темы functions.php создаем следующую функцию:

//Сохраняем цену указанную пользователем в поле custom_price
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) {
    if( isset($_POST['custom_price']) && !empty( $_POST['custom_price'])) {
        //Сохраняем пользовательские данные в корзину
        $cart_item_data['custom_price'] = (float)sanitize_text_field($_POST['custom_price']);
 
 	//Делаем товар отдельным и уникальным элементом в корзине
        $cart_item_data['unique_key'] = md5(microtime().rand());
    }
    return $cart_item_data;
}
 
//Обновляем цену товара в корзине
add_action('woocommerce_before_calculate_totals', 'change_cart_item_price', 30, 1);
function change_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_price'])){
            $cart_item['data']->set_price($cart_item['custom_price']);
        }
    }
}

Где $_POST[‘custom_price’] — это пользовательская цена товара.

Данную функцию легко переделать например для продукта у которого цена рассчитывается в зависимости от ширины и высоты.