Диагностика задачи: зачем менять стоимость товаров при оплате
В стандартном WooCommerce цена товара фиксирована и задается в карточке товара. Однако в ряде случаев необходимо изменять цену автоматически в момент оформления или подтверждения оплаты. Например, для применения динамических скидок, специальных наценок, учета сезонных факторов или интеграции с внешними системами учета цен. Стандартные купоны и скидки WooCommerce не всегда позволяют гибко реализовать такие сценарии, особенно если изменение цены зависит от внешних условий.
Как работает процесс изменения стоимости в WooCommerce
В WooCommerce стоимость товара в корзине и заказе рассчитывается на основе цены товара и скидок. Для динамической корректировки цены в момент оформления заказа нужно изменить цену именно в объекте WC_Cart или WC_Order_Item_Product. Изменение цены напрямую в базе данных товара не подходит, так как цены должны меняться только для конкретного заказа.
Ключевые хуки для изменения цены в WooCommerce
woocommerce_before_calculate_totals— позволяет изменить цены товаров в корзине перед пересчетом общей стоимости.woocommerce_checkout_create_order_line_item— позволяет изменить цену товара при создании строки заказа.
Пошаговое решение: изменяем цену товара при оплате
В данном примере мы реализуем автоматическое уменьшение цены товара на 10% в момент оформления заказа (например, для зарегистрированных пользователей). Для этого достаточно добавить следующий код в файл functions.php вашей темы или в отдельный плагин:
add_action('woocommerce_before_calculate_totals', 'custom_apply_discount_on_cart_items', 10, 1);
function custom_apply_discount_on_cart_items($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
// Проверяем, авторизован ли пользователь
if (!is_user_logged_in()) return;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$original_price = floatval($product->get_regular_price());
$discounted_price = $original_price * 0.9; // скидка 10%
$product->set_price($discounted_price);
}
}Этот код уменьшит цену всех товаров в корзине на 10%, если пользователь авторизован.
Для гарантированного сохранения цены в заказе добавим корректировку при создании заказа:
add_action('woocommerce_checkout_create_order_line_item', 'custom_change_order_item_price', 10, 4);
function custom_change_order_item_price($item, $cart_item_key, $values, $order) {
$product = $item->get_product();
$original_price = floatval($product->get_regular_price());
if (is_user_logged_in()) {
$discounted_price = $original_price * 0.9;
$item->set_subtotal($discounted_price * $item->get_quantity());
$item->set_total($discounted_price * $item->get_quantity());
$item->set_subtotal_tax(0);
$item->set_total_tax(0);
}
}Проверка результата после внедрения
- Авторизуйтесь на сайте как пользователь.
- Добавьте несколько товаров в корзину.
- Перейдите в корзину и убедитесь, что цены товаров уменьшились на 10%.
- Оформите заказ и посмотрите детали заказа в админке WooCommerce — цена должна совпадать с уменьшенной.
- Для неавторизованных пользователей цена останется без изменений.
Частые ошибки и как их исправить
- Изменение цены не применяется в админке — убедитесь, что хук
woocommerce_before_calculate_totalsвызывается не в админке (проверкаis_admin()иDOING_AJAXобязательна). - Цена изменяется для всех пользователей — проверьте условие
is_user_logged_in(), возможно, его нужно заменить на более точную проверку ролей. - Цена в заказе не совпадает с ценой в корзине — обязательно реализуйте изменение цены и в хуке
woocommerce_checkout_create_order_line_item. - Ошибки с типом данных — используйте
floatval()для конвертации цен и проверяйте, что получаете число, а не строку.
Практические советы по производительности и безопасности
- Избегайте тяжелых вычислений или запросов к внешним сервисам внутри хуков изменения цены — это может замедлить процесс оформления заказа.
- Кэшируйте результаты, если необходимо вычислять динамическую цену на основе внешних данных.
- Не сохраняйте измененную цену в свойствах товара, изменяйте только цену экземпляра в корзине или заказе.
- Тестируйте на staging-сайте перед выводом кода в продакшен.
Сравнение способов изменения цены в WooCommerce
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
Изменение цены в woocommerce_before_calculate_totals | Корректировка цены в корзине перед расчетом | Работает для всех товаров в корзине, гибко | Не влияет на цену в уже созданных заказах |
Изменение цены в woocommerce_checkout_create_order_line_item | Корректировка цены при создании заказа | Цена сохраняется в заказе, точное соответствие | Не влияет на отображение в корзине |
| Изменение цены товара напрямую | Изменение цены в базе товара | Постоянное изменение цены | Неприемлемо для динамических скидок, влияет на всех |