Диагностика задачи: зачем менять цену товара при выборе доставки
В стандартном WooCommerce стоимость товара и стоимость доставки считаются отдельно. Однако в некоторых бизнес-сценариях необходимо динамически изменять цену товара в корзине в зависимости от выбранного способа доставки. Например, при выборе экспресс-доставки цена товара увеличивается на 10% или добавляется фиксированная наценка.
Основные вопросы для диагностики:
- Какой эффект требуется: изменить цену конкретного товара или итоговую сумму корзины?
- Нужно ли сохранять корректную историю заказов?
- Как не повредить совместимость с другими плагинами?
Как отследить выбор способа доставки в WooCommerce
Способ доставки в WooCommerce выбирается на странице оформления заказа (checkout). Для динамического изменения цены в корзине или на странице товара необходимо реагировать на изменение способа доставки в реальном времени.
Для этого можно использовать AJAX-хуки WooCommerce и PHP-фильтры, в частности:
woocommerce_package_rates— фильтр для изменения доступных способов доставки;woocommerce_cart_calculate_fees— добавление дополнительных сборов;- JavaScript-события на странице оформления заказа для отслеживания выбора способа доставки.
Пошаговое решение: автоматическое изменение цены товара по способу доставки
1. Добавляем JavaScript для отслеживания выбора способа доставки
jQuery(function($){
$('form.checkout').on('change', 'input[name^="shipping_method"]', function(){
$('body').trigger('update_checkout');
});
});Этот код заставляет WooCommerce обновлять данные корзины при смене способа доставки.
2. Изменяем цену товара в корзине на сервере
add_action('woocommerce_before_calculate_totals', 'custom_change_price_by_shipping_method', 20, 1);
function custom_change_price_by_shipping_method($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
// Получаем выбранный способ доставки
$chosen_methods = WC()->session->get('chosen_shipping_methods');
if (empty($chosen_methods)) return;
$shipping_method = $chosen_methods[0];
// Пример: если выбран способ доставки 'flat_rate:10', увеличиваем цену товара на 15%
if ($shipping_method === 'flat_rate:10') {
foreach ($cart->get_cart() as $cart_item) {
$original_price = $cart_item['data']->get_regular_price();
$new_price = $original_price * 1.15; // +15%
$cart_item['data']->set_price($new_price);
}
} else {
// В остальных случаях восстанавливаем оригинальную цену
foreach ($cart->get_cart() as $cart_item) {
$original_price = $cart_item['data']->get_regular_price();
$cart_item['data']->set_price($original_price);
}
}
}3. Очистка цены при смене способа доставки
Важно сбрасывать цены обратно, чтобы избежать накопления наценок при повторном выборе способов доставки.
Проверка результата после внедрения
- Перейдите в корзину или оформление заказа.
- Выберите способ доставки
flat_rate:10(или указанный в вашем магазине). - Убедитесь, что цена товара изменилась на 15% больше.
- Выберите другой способ доставки — цена должна вернуться к исходной.
- Проверьте, что на странице оплаты итоговая сумма корректна и соответствует ожиданиям.
Частые ошибки и как их исправить
- Цена товара не меняется при выборе способа доставки
Проверьте, вызывается лиupdate_checkoutв JS. Без этого сервер не обновляет корзину при смене доставки. - Наценка накапливается при повторном выборе способов доставки
Убедитесь, что в коде в блокеelseправильно восстанавливается исходная цена (используйтеget_regular_price(), а не текущее значение). - Изменение цены ломает совместимость с плагинами кеширования
Отключите кеширование страниц корзины и оформления заказа или настройте исключения. - Цена меняется в админке
Добавьте проверкуif (is_admin() && !defined('DOING_AJAX')) return;для предотвращения изменений в бэкенде.
Практические советы по безопасности и производительности
- Не изменяйте цену товара в базе данных напрямую — меняйте только в объекте
$cart_item['data']для текущей сессии. - Избегайте слишком сложных вычислений в хукe
woocommerce_before_calculate_totals, чтобы не ухудшать скорость работы корзины. - Тестируйте работу в разных браузерах и с разными плагинами кеширования.
- Используйте child-тему или собственный плагин для добавления кода, чтобы не потерять изменения при обновлении WooCommerce.
Сравнение способов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
Изменение цены товара в woocommerce_before_calculate_totals | Гибкое, меняет цену именно товара, легко контролировать | Нужно аккуратно сбрасывать цену, возможны конфликты с кешем |
Добавление сборов woocommerce_cart_calculate_fees | Просто добавить дополнительную плату без изменения цены товара | Не меняет цену товара, сборы отображаются отдельно |
| JavaScript-манипуляции на фронтенде | Быстро и просто для визуального изменения | Не влияет на итоговые расчёты, ненадёжно |