WooCommerce: автоматическое изменение стоимости товара при выборе способа доставки

Проблема: как автоматически менять цену товара в WooCommerce при выборе доставки

В стандартном WooCommerce цена товара фиксирована и не зависит от выбранного способа доставки. Но бывают задачи, когда нужно изменить стоимость товара в зависимости от способа доставки — например, добавить наценку при экспресс-доставке или скидку при самовывозе. В этом сценарии мы рассмотрим, как программно менять цену товара в корзине и на странице товара в зависимости от выбранного способа доставки.

Диагностика задачи: что нужно учесть

  • Изменение цены должно происходить динамически, без перезагрузки страницы (желательно AJAX).
  • Изменённая цена должна отображаться на странице товара, в корзине и на этапе оформления заказа.
  • Изменения должны применяться только к конкретному товару или группе товаров.
  • Необходимо корректно учитывать налоговые ставки и отображать итоговую сумму.
  • Нужно избежать конфликтов с другими плагинами, особенно с кэшированием.

Пошаговое решение

1. Добавляем выбор способа доставки на страницу товара

Для демонстрации добавим на страницу товара селект с вариантами доставки. Обычно выбор доставки происходит на странице корзины/оформления, но для примера покажем на товаре.

add_action('woocommerce_before_add_to_cart_button', function() {
    echo '<p><label for="delivery_method">Выберите способ доставки:</label>';
    echo '<select id="delivery_method" name="delivery_method">';
    echo '<option value="standard">Стандартная доставка</option>';
    echo '<option value="express">Экспресс-доставка (+500 руб.)</option>';
    echo '<option value="pickup">Самовывоз (-100 руб.)</option>';
    echo '</select></p>';
});

2. Сохраняем выбранный способ доставки при добавлении в корзину

add_filter('woocommerce_add_cart_item_data', function($cart_item_data, $product_id, $variation_id) {
    if (isset($_POST['delivery_method'])) {
        $cart_item_data['delivery_method'] = sanitize_text_field($_POST['delivery_method']);
        // Чтобы товар с разной доставкой не объединился
        $cart_item_data['unique_key'] = md5(microtime().rand());
    }
    return $cart_item_data;
}, 10, 3);

3. Изменяем цену товара в корзине в зависимости от способа доставки

add_action('woocommerce_before_calculate_totals', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    foreach ($cart->get_cart() as $cart_item) {
        if (isset($cart_item['delivery_method'])) {
            $price = $cart_item['data']->get_regular_price();
            switch ($cart_item['delivery_method']) {
                case 'express':
                    $price += 500; // наценка
                    break;
                case 'pickup':
                    $price -= 100; // скидка
                    if ($price < 0) $price = 0;
                    break;
                case 'standard':
                default:
                    break;
            }
            $cart_item['data']->set_price($price);
        }
    }
});

4. Отображаем выбранный способ доставки в корзине и в заказе

add_filter('woocommerce_get_item_data', function($item_data, $cart_item) {
    if (!empty($cart_item['delivery_method'])) {
        $delivery_names = [
            'standard' => 'Стандартная доставка',
            'express' => 'Экспресс-доставка',
            'pickup' => 'Самовывоз',
        ];
        $item_data[] = [
            'key' => 'Способ доставки',
            'value' => $delivery_names[$cart_item['delivery_method']] ?? $cart_item['delivery_method'],
        ];
    }
    return $item_data;
}, 10, 2);

5. Добавляем выбранный способ доставки в метаданные заказа

add_action('woocommerce_add_order_item_meta', function($item_id, $values) {
    if (!empty($values['delivery_method'])) {
        wc_add_order_item_meta($item_id, 'Способ доставки', $values['delivery_method']);
    }
}, 10, 2);

Проверка результата

  • Откройте страницу товара, выберите способ доставки и добавьте товар в корзину.
  • Перейдите в корзину — цена товара должна измениться согласно выбранному способу доставки.
  • В корзине под каждым товаром должно отображаться выбранное значение способа доставки.
  • При оформлении заказа проверьте, что выбранный способ доставки сохраняется в деталях заказа.
  • Для проверки можно добавить несколько товаров с разными способами доставки — они не должны объединяться.

Частые ошибки и как их исправить

  • Цена не меняется в корзине: Проверьте, что хук woocommerce_before_calculate_totals не прерывается другими плагинами и что функция не возвращает преждевременно на админке.
  • Товар объединяется в корзине несмотря на разные способы доставки: Не забудьте добавить уникальный ключ в cart_item_data, чтобы WooCommerce считал товары разными.
  • Изменения не отображаются на странице товара: Для динамического изменения цены на странице товара потребуется реализовать AJAX-обработчик и JavaScript для перезагрузки цены без обновления страницы.
  • Неверное отображение в заказах: Проверьте, что метаданные корректно добавляются с помощью wc_add_order_item_meta.

Практические советы по безопасности и производительности

  • Всегда используйте sanitize_text_field или аналогичные функции для обработки данных из $_POST.
  • Избегайте тяжелых операций внутри хуков изменения цены, так как они вызываются несколько раз в процессе оформления заказа.
  • При использовании кэширования страниц убедитесь, что корзина и цены корректно обновляются для каждого пользователя.
  • Если необходимо отображать изменённую цену на странице товара в реальном времени, реализуйте AJAX-запросы с nonce для безопасности.

Сравнение способов реализации

МетодПлюсыМинусы
Изменение цены в корзине через хук woocommerce_before_calculate_totalsПросто, работает для всех товаров, меняет цену в корзине и заказеНе влияет на страницу товара, нет динамического обновления цены до добавления в корзину
Динамическое изменение цены на странице товара через AJAXПоказывает актуальную цену сразу, улучшает UXСложнее в реализации, требует JS и AJAX, повышает нагрузку
Использование плагинов для адаптивных ценГотовые решения с UI для настройкиМожет быть дорого, нагрузка на сайт, ограниченная гибкость
Эффективное ведение логов ошибок в WordPress: практические методы и примеры кода
01.03.2026
Как удалить автоматически неиспользуемые шорткоды в WordPress
01.04.2026
Как разрешить отправку формы только авторизованным пользователям в WordPress
11.01.2026
Оптимизация базы данных WordPress: ускоряем сайт и улучшаем производительность
23.11.2025
Как создать автоматическую резервную копию WordPress с помощью плагинов и собственного кода
20.11.2025