Диагностика задачи: зачем менять стоимость товара по дисконным кодам
В WooCommerce стандартная система купонов позволяет назначить скидку на корзину или отдельные товары, но иногда требуется более гибкое решение — например, менять цену товара динамически при вводе определенного дисконтного кода, влияя на отображаемую стоимость прямо на странице товара и в корзине. Это полезно для закрытых акций, персональных предложений или уникальных скидок для определенных клиентов.
Пошаговое решение: динамическое изменение стоимости товара по дисконным кодам
1. Создаем пользовательское поле для ввода дисконтного кода
Добавим на страницу товара поле для ввода дисконтного кода с помощью хука woocommerce_before_add_to_cart_button:
add_action('woocommerce_before_add_to_cart_button', function() {
echo '<label for="discount_code">Дисконный код:</label>';
echo '<input type="text" id="discount_code" name="discount_code" placeholder="Введите код скидки" />';
});2. Обработка дисконтного кода при добавлении товара в корзину
Для передачи введенного кода в корзину и изменения цены используем хук woocommerce_add_cart_item_data, а для изменения цены — хук woocommerce_before_calculate_totals:
add_filter('woocommerce_add_cart_item_data', function($cart_item_data, $product_id, $variation_id) {
if (!empty($_POST['discount_code'])) {
$cart_item_data['discount_code'] = sanitize_text_field($_POST['discount_code']);
// Добавим уникальный ключ, чтобы товары с разными кодами не сливались
$cart_item_data['unique_key'] = md5(microtime() . rand());
}
return $cart_item_data;
}, 10, 3);
add_action('woocommerce_before_calculate_totals', function($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
if (isset($cart_item['discount_code'])) {
$code = $cart_item['discount_code'];
// Здесь проверяем код и задаем новую цену
if ($code === 'SPECIAL10') {
$discounted_price = $cart_item['data']->get_regular_price() * 0.9; // 10% скидка
$cart_item['data']->set_price($discounted_price);
} elseif ($code === 'VIP20') {
$discounted_price = $cart_item['data']->get_regular_price() * 0.8; // 20% скидка
$cart_item['data']->set_price($discounted_price);
}
// Добавьте дополнительные коды по необходимости
}
}
});3. Отображение дисконтного кода в корзине и оформлении заказа
Чтобы покупателю было видно, что цена изменена по дисконтному коду, добавим отображение кода в списке товаров корзины:
add_filter('woocommerce_get_item_data', function($item_data, $cart_item) {
if (!empty($cart_item['discount_code'])) {
$item_data[] = array(
'key' => 'Дисконный код',
'value' => esc_html($cart_item['discount_code'])
);
}
return $item_data;
}, 10, 2);Проверка результата после внедрения
- Перейдите на страницу товара, введите один из заданных дисконтовых кодов (например,
SPECIAL10илиVIP20) и добавьте товар в корзину. - В корзине цена товара должна измениться согласно заданной скидке, а под названием товара отобразится дисконтный код.
- При оформлении заказа в деталях заказа также должен отображаться дисконтный код для каждого товара.
Частые ошибки и как исправить
- Цена не меняется в корзине: проверьте, что функция изменения цены подключена к
woocommerce_before_calculate_totalsи что в ней нет ошибок. Также убедитесь, что условие проверки кода корректно. - Товары с разными кодами сливаются в корзине: для решения используйте уникальный ключ в данных корзины (
unique_key), как показано в примере — это предотвратит объединение позиций. - Дисконный код не передается из формы: убедитесь, что поле ввода имеет атрибут
name="discount_code"и что данные передаются через POST. - Цена меняется для всех товаров: проверьте, что скидка применяется только к товарам с установленным дисконтным кодом.
Практические советы по безопасности и производительности
- Используйте
sanitize_text_fieldдля обработки пользовательского ввода дисконтного кода, чтобы избежать XSS-уязвимостей. - Если кодов много и они регулярно меняются, храните их в отдельной таблице или опции, а не прописывайте в коде.
- Для более сложной логики скидок используйте фильтр
woocommerce_cart_calculate_fees, если нужно добавить фиксированную скидку или сбор. - Избегайте изменения цены товара глобально — меняйте цену только в объекте товара в корзине, чтобы не влиять на данные в базе.
Сравнение вариантов реализации
| Метод | Преимущества | Недостатки |
|---|---|---|
| Использовать стандартные купоны WooCommerce | Простая настройка, интеграция с отчетами | Меньше гибкости, нельзя менять цену на странице товара |
Изменять цену через woocommerce_before_calculate_totals по пользовательскому коду | Гибкость, можно менять цену на лету | Требует кастомного кода, сложнее поддерживать |
| Плагины для динамических скидок | Много функций и удобный интерфейс | Часто платные, могут влиять на производительность |