Проблема: изменение стоимости товара после оформления заказа в WooCommerce
В WooCommerce часто встречается ситуация, когда администратор или сторонний плагин меняет цену товара уже после того, как заказ был оформлен. Это приводит к некорректному отображению стоимости в заказах, проблемам с бухгалтерией и недовольству покупателей. Такой баг особенно критичен для магазинов с динамическими ценами или акциями.
Диагностика проблемы: как понять, что цена меняется неправомерно
- Проверьте историю изменений заказа в админке WooCommerce — есть ли там обновления цены после оформления.
- Отключите все сторонние плагины, которые влияют на ценообразование (акции, скидки, расчёт доставки), и проверьте, сохраняется ли проблема.
- Просмотрите логи сервера и WooCommerce (если включены) на предмет вызовов функций, изменяющих цену после оформления.
- Проверьте, не используются ли хуки, модифицирующие
$orderили$itemв момент обновления заказа.
Пошаговое решение: блокируем изменение стоимости в заказах
Чтобы запретить изменение цены товара в уже оформленном заказе, нужно на уровне кода отключить обновление полей стоимости в заказе. Это можно сделать, перехватив соответствующие хуки WooCommerce.
Добавьте следующий код в файл functions.php вашей темы (лучше в дочерней) или в кастомный плагин:
add_action('woocommerce_before_calculate_totals', 'lock_order_item_prices', 10, 1);
function lock_order_item_prices($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if (isset($cart_item['data']) && $cart_item['data'] instanceof WC_Product) {
// Получаем цену из базы, чтобы не дать менять
$product_id = $cart_item['product_id'];
$product = wc_get_product($product_id);
if ($product) {
$cart_item['data']->set_price($product->get_price());
}
}
}
}
}
// Блокируем изменение цены в админке заказа
add_action('woocommerce_before_order_object_save', 'prevent_order_price_change', 10, 1);
function prevent_order_price_change($order) {
if (is_admin()) {
foreach ($order->get_items() as $item_id => $item) {
$product = $item->get_product();
if ($product) {
$original_price = $product->get_price();
$item->set_subtotal($original_price * $item->get_quantity());
$item->set_total($original_price * $item->get_quantity());
}
}
$order->calculate_totals();
}
}Этот код запрещает изменение цены товара в корзине и в заказах, принудительно подставляя актуальную цену из каталога.
Проверка результата
- Создайте тестовый заказ с товаром.
- Попробуйте изменить цену товара вручную в админке заказа — она должна сбрасываться на цену из каталога.
- Обновите страницу заказа, убедитесь, что стоимость не изменяется.
- Проверьте, что при изменении цены товара в каталоге (до оформления заказа) новая цена применяется.
Частые ошибки и способы их исправления
- Изменение цены происходит из-за сторонних плагинов. Решение: временно отключите плагины, влияющие на цены, и поэтапно включайте для выявления виновника.
- Кэширование цен в WooCommerce. Иногда цены кешируются плагинами кэширования или самим WooCommerce. Очистите кэш сайта и браузера.
- Код не работает для вариативных товаров. В этом случае дополнительно нужно проверять вариации и их цены через
WC_Product_Variation. - Ошибка в хуках — например, код применён не в правильном месте. Убедитесь, что код добавлен в
functions.phpили кастомный плагин и активен.
Практические советы по безопасности и производительности
- Не используйте отключение изменения цены как единственный способ контроля — лучше блокировать редактирование заказа для ролей, которым нельзя менять цены.
- Используйте транзакции и бэкапы перед массовыми изменениями заказов.
- Для сложных сценариев динамического ценообразования лучше использовать проверенные плагины с поддержкой WooCommerce.
- Минимизируйте количество вызовов
wc_get_product()внутри циклов, кешируя результаты при необходимости.
Сравнение подходов: плагин vs собственный код
| Метод | Плюсы | Минусы |
|---|---|---|
| Собственный код (хуки) | Легко кастомизировать, не нагружает сайт, бесплатно | Нужны навыки программирования, может не покрыть все кейсы |
| Плагины блокировки редактирования заказов | Простота настройки, поддержка разработчика, дополнительные функции | Могут конфликтовать, нагрузка, плата за лицензии |