Почему важно запретить изменение стоимости товара после оформления заказа в WooCommerce
В WooCommerce по умолчанию стоимость товара в заказе фиксируется на момент оформления. Однако при использовании сторонних плагинов, кастомных скриптов или прямом изменении заказа в админке стоимость может быть изменена, что нарушает бизнес-логику и приводит к несоответствиям в учёте и оплате.
Отключение возможности изменить стоимость после оформления — важная задача для крупных магазинов, где требуется строгий контроль заказов и бухгалтерии.
Диагностика проблемы: как понять, что стоимость меняется после оформления
- Проверить логи заказов и сравнить цены товаров на момент создания и после редактирования в админке.
- Отследить случаи, когда стоимость заказа изменилась без обновления статуса оплаты.
- Убедиться, что сторонние плагины (например, для скидок, кастомизации заказа) не влияют на итоговую цену после оформления.
Пошаговое решение: запрет изменения стоимости товара после оформления
1. Запрет изменения цены в админке редактирования заказа
Добавим запрет на изменение цены позиции заказа через хук woocommerce_before_order_itemmeta. Вставьте следующий код в файл functions.php вашей темы или в кастомный плагин:
add_action('woocommerce_before_order_itemmeta', function($item_id, $item, $order) {
// Запрещаем редактирование цены для заказов со статусом, отличным от 'pending' или 'failed'
if (!in_array($order->get_status(), ['pending', 'failed'])) {
remove_action('woocommerce_before_order_itemmeta', 'woocommerce_order_item_editable_fields', 10);
echo '<style>.wc-order-item-price, .wc-order-item-subtotal { pointer-events: none; opacity: 0.6; }</style>';
}
}, 5, 3);Этот код блокирует визуальное редактирование цены товара в админке для заказов, которые уже в обработке или выполнены.
2. Фиксация цены на уровне сохранения заказа
Чтобы полностью исключить изменение цены даже программно, нужно «заморозить» цену при обновлении заказа. Добавьте следующий фильтр:
add_action('woocommerce_before_save_order_items', function($order_id) {
$order = wc_get_order($order_id);
if (!$order) return;
// Разрешаем изменение только для неоплаченных заказов
if (in_array($order->get_status(), ['pending', 'failed'])) return;
foreach ($order->get_items() as $item_id => $item) {
$original_price = $item->get_meta('_original_product_price');
if ($original_price === '') {
$item->update_meta_data('_original_product_price', $item->get_total() / $item->get_quantity());
$item->save();
} else {
$item->set_subtotal($original_price * $item->get_quantity());
$item->set_total($original_price * $item->get_quantity());
$item->save();
}
}
$order->calculate_totals();
$order->save();
});Этот код при сохранении заказа проверяет, есть ли сохранённая изначальная цена, и восстанавливает её, не позволяя изменять стоимость товара.
Проверка результата после внедрения
- В админке попробуйте изменить цену товара в заказе со статусом «Обработка» или «Завершён» — поле должно быть заблокировано.
- Попытайтесь изменить цену программно (через REST API или кастомные функции) — цена должна автоматически восстановиться к изначальному значению при сохранении.
- Создайте новый заказ, попробуйте изменить цену до оплаты — изменение должно работать, так как ограничение действует только для оплаченных заказов.
Частые ошибки и как их исправить
- Цена не фиксируется при повторном сохранении заказа: убедитесь, что функция сохраняет исходную цену в мета-поле
_original_product_priceпри первом сохранении. Если вы используете сторонние плагины, они могут сбрасывать это значение. - Цена остается редактируемой в админке: возможно, приоритет хука или порядок загрузки кода нарушен. Проверьте, что код добавлен с приоритетом ниже 10 и в правильном месте.
- Расчёт итогов заказа не обновляется: после изменения цены вызывайте
calculate_totals()иsave()для заказа, как показано в примере.
Практические советы по безопасности и производительности
- При блокировке редактирования в админке используйте CSS и JS осторожно, чтобы не нарушить другие элементы интерфейса WooCommerce.
- Фиксация цены на уровне сохранения помогает избежать ошибок при массовом редактировании заказов или при интеграции с внешними сервисами.
- Всегда тестируйте изменения на копии сайта, чтобы избежать сбоев в работе магазина.
- Если у вас много заказов и нагрузка на сайт высокая, оптимизируйте обработку хуков, чтобы не замедлять сохранение заказа.
Сравнение вариантов реализации запрета изменения цены
| Метод | Плюсы | Минусы | Использование |
|---|---|---|---|
| Отключение редактирования в админке через CSS/JS | Просто реализовать, быстро | Не защищает от программных изменений | Для визуального ограничения |
| Фиксация цены на уровне сохранения заказа | Надежно защищает от изменений | Усложняет обновление с особыми условиями (скидки) | Для строгого контроля цен |
| Использование плагинов контроля заказов | Готовые решения с поддержкой | Может замедлять сайт, добавляет нагрузку | Для комплексного управления заказами |