Диагностика задачи: зачем менять цену товаров при оплате?
В WooCommerce иногда возникает необходимость изменить стоимость товаров именно в момент оплаты. Например, для применения динамических скидок, комиссий или корректировок курса валюты. Однако делать это нужно аккуратно, чтобы не повредить логику заказов и не вызвать конфликты с другими плагинами.
В чем проблема без автоматических изменений?
- Стандартные скидки и купоны не всегда покрывают сложные сценарии;
- Ручное изменение цены клиентом невозможно;
- Изменение цены после оформления заказа не влияет на итоговую стоимость, если не настроено корректно.
Пошаговое решение: автоматическое изменение цены товара в момент оплаты
Для изменения цены товаров в корзине до создания заказа нужно использовать хук woocommerce_before_calculate_totals. В этом хуке можно менять цену товаров динамически.
Пример кода, который добавляет 10% комиссию к цене товара при наличии определённого способа оплаты (например, 'cod' - наложенный платеж):
add_action('woocommerce_before_calculate_totals', 'custom_change_price_on_payment_method', 10, 1);
function custom_change_price_on_payment_method($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// Получаем выбранный способ оплаты из сессии
$chosen_payment = WC()->session->get('chosen_payment_method');
// Проверяем, выбран ли способ оплаты 'cod'
if ($chosen_payment !== 'cod') {
return; // Если выбран другой способ, ничего не меняем
}
// Увеличиваем цену каждого товара на 10%
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$original_price = $cart_item['data']->get_regular_price();
$new_price = $original_price * 1.10; // +10%
$cart_item['data']->set_price($new_price);
}
}Обратите внимание:
- Используем
get_regular_price(), чтобы брать базовую цену товара; - Изменяем цену через
set_price()в объекте товара в корзине; - Проверяем, что функция не запускается в админке и не во время AJAX-запросов, чтобы избежать ошибок.
Как сделать так, чтобы цена менялась только при определённом способе оплаты?
Способ оплаты выбирается клиентом на странице оформления заказа, и сохраняется в сессии WooCommerce. В приведённом коде мы это учитываем через WC()->session->get('chosen_payment_method'). Для отработки этого изменения корректно нужно, чтобы корзина пересчитывалась после выбора способа оплаты.
Проверка результата после внедрения
- Перейдите в корзину и выберите способ оплаты, для которого настроено изменение цены (например, "Наложенный платеж");
- Обратите внимание на стоимость товаров и итоговую сумму — в ней должна отразиться наценка 10%;
- При смене способа оплаты на другой — цена должна вернуться к исходной;
- Создайте заказ и проверьте, что цена в заказе соответствует изменённой цене в корзине.
Частые ошибки и как их исправить
- Цена не меняется при выборе способа оплаты: убедитесь, что корзина пересчитывается после выбора способа оплаты. Иногда нужно добавить JavaScript, который вызывает обновление корзины при изменении способа оплаты.
- Изменения цены влияют на админку: добавьте проверку
is_admin() && !defined('DOING_AJAX'), чтобы исключить выполнение кода в админке. - Изменённая цена не сохраняется в заказе: WooCommerce берёт цену из корзины при оформлении заказа, проверьте, что изменения происходят до вызова создания заказа.
- Конфликты с другими плагинами скидок: тестируйте на чистой установке и поэтапно подключайте плагины для выявления конфликтов.
Практические советы по производительности и безопасности
- Не перегружайте хук
woocommerce_before_calculate_totalsсложными запросами и вычислениями — он вызывается часто; - Проверяйте, что цена не меняется бесконтрольно, чтобы избежать зацикливания;
- Используйте кеширование данных, если нужно получать внешние параметры для изменения цены;
- Тестируйте на staging-сайте перед внедрением на боевом ресурсе.
Пример расширенного кода: динамическое изменение цены по курсу валюты при оплате через PayPal
add_action('woocommerce_before_calculate_totals', 'change_price_based_on_payment_and_currency', 10, 1);
function change_price_based_on_payment_and_currency($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
$chosen_payment = WC()->session->get('chosen_payment_method');
if ($chosen_payment !== 'paypal') {
return;
}
// Пример получения курса валюты (фиксированное значение)
$usd_to_rub = 75; // курс, можно получать из API
foreach ($cart->get_cart() as $cart_item) {
$base_price = $cart_item['data']->get_regular_price();
// Допустим, товар в USD, меняем на RUB
$new_price = $base_price * $usd_to_rub;
$cart_item['data']->set_price($new_price);
}
}Таблица сравнения способов изменения цены товаров при оплате
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
Изменение цены в woocommerce_before_calculate_totals | Динамическое изменение цены в корзине | Гибкость, работает до создания заказа | Нужно контролировать вызовы, возможно, конфликт с плагинами |
| Использование купонов | Добавление скидок через купоны | Простота, встроено в WooCommerce | Менее гибко, не позволяет изменять цену произвольно |
| Изменение цены в самом заказе (после создания) | Редактирование цены в админке или через хуки заказа | Подходит для исправлений после оформления | Не влияет на корзину и интерфейс клиента |