Диагностика задачи: зачем менять стоимость товаров при оплате
В WooCommerce иногда требуется динамически изменять цену товаров на этапе оформления заказа — например, для применения скидок, комиссий или специальных условий оплаты. Часто пользователи сталкиваются с проблемой, что стандартные купоны и скидки не подходят под бизнес-логику, и тогда приходится использовать PHP-код.
Главная задача — изменить итоговую стоимость товара именно при оплате, не меняя базовую цену в каталоге и не затрагивая корзину до финального расчёта.
Как WooCommerce рассчитывает стоимость товаров в заказе
WooCommerce использует несколько фильтров для корректировки цен в корзине и заказе, среди них ключевыми являются:
woocommerce_before_calculate_totals— для изменения цен товаров в корзине перед расчётом итогов;woocommerce_cart_calculate_fees— для добавления дополнительных сборов или скидок;woocommerce_order_get_items— для модификации элементов заказа после оформления.
Для изменения стоимости товара именно при оплате лучше работать с первым фильтром, чтобы корректировки применялись в корзине и при формировании заказа.
Пошаговое решение: пример кода для изменения цены товара при оплате
Рассмотрим пример, когда при оформлении заказа цена товара увеличивается на 10% — например, чтобы добавить комиссию за оплату определённым способом. Код нужно добавить в файл functions.php вашей темы или в кастомный плагин.
add_action('woocommerce_before_calculate_totals', 'wpkit_adjust_cart_item_price', 20, 1);
function wpkit_adjust_cart_item_price( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
// Проверяем, что корзина не пустая
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Пример: увеличиваем цену на 10%
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$original_price = $cart_item['data']->get_price();
$new_price = $original_price * 1.10; // +10%
$cart_item['data']->set_price( $new_price );
}
}Этот код применит увеличение цены ко всем товарам в корзине. Если нужно изменить стоимость только для определённого способа оплаты, можно добавить проверку выбранного способа.
Изменение цены только для выбранного способа оплаты
add_action('woocommerce_before_calculate_totals', 'wpkit_adjust_price_for_payment_method', 20, 1);
function wpkit_adjust_price_for_payment_method( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Получаем выбранный способ оплаты из сессии
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if ( $chosen_payment_method !== 'cod' ) return; // Пример: только для оплаты при получении
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$original_price = $cart_item['data']->get_price();
$new_price = $original_price * 1.10; // +10%
$cart_item['data']->set_price( $new_price );
}
}Проверка результата после внедрения
- Добавьте товар в корзину.
- Перейдите к оформлению заказа и выберите способ оплаты, например «Оплата при получении» (если в коде есть проверка по способу).
- Убедитесь, что цена товара в корзине выросла на 10%.
- Завершите заказ и проверьте в админке WooCommerce, что цена заказа и товаров соответствует изменённой стоимости.
- Попробуйте выбрать другой способ оплаты и убедитесь, что цена не меняется.
Частые ошибки и как исправить
- Изменения цены не отображаются в корзине или заказе. Частая причина — неправильный приоритет хука или отсутствие проверки
did_action('woocommerce_before_calculate_totals'). Решение: добавьте проверку, чтобы код выполнялся один раз. - Цена меняется в каталоге, а не только при оплате. Используйте фильтр только в контексте корзины, не меняйте цену товара глобально.
- Цена меняется не для всех способов оплаты. Проверьте, что выбранный способ оплаты сохраняется в сессии и доступен в момент вызова функции.
- Проблемы с кешированием. Если на сайте используется кеширование страниц, динамические изменения цены могут не отображаться корректно. Применяйте AJAX-обновление корзины или отключите кеш для страниц корзины и оформления заказа.
Практические советы по безопасности и производительности
- Не сохраняйте изменённые цены товаров в базе данных — используйте только динамическое изменение через фильтры, чтобы избежать рассинхронизации данных.
- Избегайте тяжелых операций внутри хука
woocommerce_before_calculate_totals, чтобы не замедлять загрузку корзины. - Проверяйте наличие активной сессии WooCommerce перед получением данных о способе оплаты.
- Для сложных условий и логики используйте дополнительные метаполя товаров или пользовательские настройки, чтобы не писать сложные условия прямо в функции.
Сравнение вариантов реализации динамического изменения цены
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
Фильтр woocommerce_before_calculate_totals | Полный контроль над ценой в корзине, работает для любых условий | Нужно аккуратно писать код, может влиять на производительность | Пример из статьи |
Добавление сборов через woocommerce_cart_calculate_fees | Простое добавление дополнительных платежей | Не меняет цену товара, а добавляет отдельный элемент | Добавление комиссии за оплату |
| Использование купонов и скидок WooCommerce | Простая настройка без кода | Ограничена стандартной логикой WooCommerce | Стандартные купоны |