Проблема: изменение цены товара при выборе подписки в WooCommerce
В стандартном WooCommerce нет встроенной поддержки подписок без установки отдельного плагина Subscription. Если вы хотите реализовать ежемесячную подписку с изменением стоимости товара динамически, например, снижать цену при выборе подписки, нужно делать кастомную доработку. Рассмотрим как автоматически менять цену товара при выборе варианта «Ежемесячная подписка» с помощью хуков и кастомного поля.
Диагностика проблемы
Часто пользователи создают вариативные товары с атрибутом подписки, но не знают, как менять цену динамически в корзине и на странице товара без плагинов.
- Цена не меняется при выборе варианта подписки на странице товара.
- В корзине и на странице оформления заказа отображается базовая цена без скидки.
- Нужно изменить цену только если выбран именно вариант подписки.
Шаги для решения задачи
1. Добавляем атрибут для вариаций
Создайте атрибут «Подписка» со значениями «Один раз» и «Ежемесячно» в настройках товара (вариативный товар).
2. Добавляем фильтр для изменения цены в корзине
Используем хук woocommerce_before_calculate_totals, чтобы изменить цену товара в корзине при выборе подписки.
add_action('woocommerce_before_calculate_totals', 'custom_change_price_for_subscription', 20, 1); function custom_change_price_for_subscription($cart) { if (is_admin() && !defined('DOING_AJAX')) return; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { if (isset($cart_item['variation']['attribute_pa_podpiska']) && $cart_item['variation']['attribute_pa_podpiska'] === 'ezhemesyachno') { $original_price = $cart_item['data']->get_regular_price(); $discount_price = $original_price * 0.8; // скидка 20% $cart_item['data']->set_price($discount_price); } } }В этом примере attribute_pa_podpiska — системное имя атрибута (pa — product attribute), а «ezhemesyachno» — слаг вариации подписки. Цена уменьшается на 20%.
3. Изменение цены на странице товара через JavaScript
Чтобы отразить цену сразу на странице выбора вариации, используйте следующий скрипт в файле темы или через wp_footer:
jQuery(document).ready(function($) { $('form.variations_form').on('found_variation', function(event, variation) { if(variation.attributes['attribute_pa_podpiska'] === 'ezhemesyachno') { var new_price = variation.display_price * 0.8; $('.woocommerce-Price-amount.amount').text(new_price.toFixed(2) + ' ₽'); } else { $('.woocommerce-Price-amount.amount').text(variation.display_price.toFixed(2) + ' ₽'); } }); });Проверка результата
- На странице товара при выборе вариации с подпиской цена должна изменяться и отображаться со скидкой.
- В корзине и на странице оформления заказа цена должна соответствовать скидочной.
- Добавьте в корзину вариацию без подписки — цена должна оставаться базовой.
Частые ошибки и их исправление
- Неверное имя атрибута в коде — проверьте slug атрибута в WooCommerce (pa_podpiska), он чувствителен к регистру.
- Скрипт JS не срабатывает — убедитесь, что jQuery подключен и нет конфликтов с другими скриптами.
- Цена не меняется в корзине — проверьте, что фильтр добавлен с правильным приоритетом и что цена сбрасывается при обновлении корзины.
- Кэширование страниц — отключите кэш на страницах корзины, товара и оформления заказа для правильного отображения динамической цены.
Практические советы по безопасности и производительности
- Избегайте тяжелых вычислений в хуках, используйте кеширование, если цена рассчитывается по сложным формулам.
- Проверяйте все пользовательские данные, если добавляете новые поля для подписки, чтобы предотвратить XSS и другие уязвимости.
- Включите защиту от кэширования корзины и страниц оформления заказа, чтобы цены всегда были актуальными.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
| Кастомный код с хуками | Полный контроль, без лишних плагинов | Требует знания PHP и JS, поддержка на разработчике |
| Плагины подписки WooCommerce Subscriptions | Готовое решение, поддержка подписок и платежей | Платный, может замедлить сайт, избыточен для простой скидки |
| Использование скидок и купонов | Простая настройка без кода | Менее гибко, не меняет цену в реальном времени |