Купон настроен в админке, но на витрине он «оживает» только в компонентах корзины и оформления заказа. Разберём, где именно покупатель вводит промокод, как Битрикс пересчитывает скидку и почему код иногда «не применяется».
Где покупатель вводит купон
В стандартном шаблоне решения купон можно ввести в двух местах: в корзине (компонент bitrix:sale.basket.basket) и на странице оформления заказа (компонент bitrix:sale.order.ajax). Оба места работают с одной и той же сущностью — коллекцией купонов заказа, поэтому купон, введённый в корзине, «переезжает» в оформление и наоборот.
Поле ввода — это обычный <input>, значение которого уходит на сервер AJAX-запросом. В корзине за отображение блока купонов отвечает параметр компонента USE_GIFTS и связанные шаблонные части, а сам ввод обрабатывается методом, добавляющим код в текущую корзину. Важно: скидка по купону — это результат работы правил корзины (Sale Discount), а поле — лишь способ передать код в расчёт.
template.php шаблона bitrix:sale.basket.basket.Как купон применяется технически
Когда покупатель отправляет код, Битрикс не «ищет скидку по купону» напрямую. Он кладёт код в коллекцию купонов заказа через менеджер Bitrix\Sale\DiscountCouponsManager, после чего запускает пересчёт корзины. Дальше движок скидок (Bitrix\Sale\Discount) прогоняет все активные правила корзины, и те из них, у которых в условии стоит проверка купона, срабатывают именно для введённого кода.
- Ввод кода —
DiscountCouponsManager::add($coupon)помещает купон в сессию/заказ. - Пересчёт — вызывается
Basket::refresh()или пересчёт заказа при оформлении. - Применение — правило корзины с типом купона находит совпадение и меняет цену позиций или доставку.
Отсюда следствие: если для купона не создано ни одного правила корзины, код будет «валидным», но скидки не даст. Это одна из самых частых причин обращений в поддержку.
Отображение скидки и итогов
После успешного применения покупатель должен видеть результат. В корзине и оформлении Битрикс показывает несколько связанных значений: сумму скидки, итог со скидкой и статус самого купона.
| Что показываем | Откуда берётся |
|---|---|
| Сумма скидки по позиции | Разница базовой и итоговой цены товара после правил корзины |
| Общая скидка заказа | Поле DISCOUNT_PRICE заказа / итоги корзины |
| Статус купона | Состояние из DiscountCouponsManager: применён, не найден, не подошёл |
В шаблоне корзины итоги отдаёт секция result['DISCOUNT_PRICE_FORMATED'] и массив применённых купонов. Хорошая практика — показывать не только «−500 ₽», но и имя купона со статусом, чтобы покупатель понимал, что именно сработало.
Ошибки применения и их причины
Битрикс различает несколько статусов купона, и от статуса зависит текст, который видит покупатель. Понимание этих статусов экономит часы отладки.
- Купон не найден (
STATUS_NOT_FOUND) — кода нет в базе или он деактивирован. - Купон не подошёл к заказу (
STATUS_APPLYEDне достигнут) — код валиден, но ни одно условие правила корзины не выполнено (например, не набрана минимальная сумма). - Лимит исчерпан — для одноразовых купонов или ограниченных серий число активаций закончилось.
- Истёк срок — вышли за даты активности купона или самого правила корзины.
Ещё один источник ошибок — кэширование. Компонент корзины должен работать без агрессивного кэша по составу заказа, иначе покупатель увидит устаревшие итоги. Для витрины со скидками следите за корректной инвалидацией.
Вывод и управление купоном через API
Когда нужно кастомное поведение — свой блок «Мои промокоды», автоприменение из ссылки или вывод статуса в личном кабинете — работают напрямую с DiscountCouponsManager. Перед вызовами инициализируйте менеджер:
use Bitrix\Sale\DiscountCouponsManager;DiscountCouponsManager::init();
- Добавить купон:
DiscountCouponsManager::add($code)— вернётtrueпри успешном добавлении в коллекцию. - Удалить купон:
DiscountCouponsManager::delete($code). - Получить список:
DiscountCouponsManager::get(true)— массив применённых кодов с их статусами. - Проверить купон:
DiscountCouponsManager::isExist($code).
После любых изменений коллекции обязательно пересчитайте корзину или заказ ($basket->refresh()), иначе итоги не обновятся. Автоприменение из URL реализуют так: ловят GET-параметр, вызывают add() и делают пересчёт до вывода корзины.
Практические рекомендации
Чтобы витрина с купонами работала предсказуемо, придерживайтесь нескольких правил.
- Синхронизируйте даты активности купона и правила корзины — расхождения дают «немую» ошибку.
- Показывайте покупателю понятный статус: применён, не подошёл, истёк — не глухое «ошибка».
- Держите поле купона и в корзине, и в оформлении, чтобы код можно было ввести на любом шаге.
- Тестируйте одноразовые и многоразовые купоны отдельно — логика лимитов у них разная.
- Проверяйте пересчёт после AJAX: итоги, сумма скидки и стоимость доставки должны меняться сразу.
Отдельно протестируйте поведение при выходе из личного кабинета и при смене корзины — купоны хранятся в контексте текущего заказа, и при очистке корзины их коллекция обычно сбрасывается.
Итог
В публичной части купон — это связка из трёх звеньев: поле ввода в компонентах sale.basket.basket и sale.order.ajax, коллекция купонов заказа в DiscountCouponsManager и правила корзины, которые реально считают скидку. Большинство проблем на витрине сводится к рассинхрону дат, отсутствию правила под купон или незавершённому пересчёту после AJAX.
Если нужно нестандартное поведение — автоприменение из ссылки, блок промокодов в кабинете, скидки для API-заказов — это уже доработка компонентов и логики скидок. Мы в B2Bsite настраиваем купоны в публичной части под реальные сценарии магазина: от корректных статусов и текстов ошибок до интеграции скидок с внешними системами.
Частые вопросы
В каком компоненте выводится поле ввода купона?
В корзине это bitrix:sale.basket.basket, а на странице оформления — bitrix:sale.order.ajax. Оба работают с общей коллекцией купонов заказа.
Почему купон принимается, но скидки нет?
Скорее всего, для купона не создано правило корзины или его условия не выполнены (не набрана минимальная сумма, не тот раздел). Купон лишь передаёт код, а считает скидку правило корзины.
Как применить купон программно?
Инициализируйте DiscountCouponsManager::init() и вызовите DiscountCouponsManager::add($code), затем пересчитайте корзину методом refresh(). Без пересчёта итоги не обновятся.
Как получить список применённых купонов через API?
Используйте DiscountCouponsManager::get(true) — он вернёт массив кодов вместе с их текущими статусами применения.
Что означает статус STATUS_NOT_FOUND?
Купон с таким кодом не найден в базе или деактивирован. Покупателю обычно показывается сообщение, что промокод не существует.
Можно ли автоматически применять купон из ссылки?
Да. Поймайте GET-параметр с кодом, вызовите DiscountCouponsManager::add() и пересчитайте корзину до её вывода, чтобы скидка отобразилась сразу.
Почему после ввода купона итоги не меняются?
Чаще всего не выполнен пересчёт корзины или заказа после AJAX-запроса, либо мешает кэш компонента. Проверьте вызов refresh() и инвалидацию кэша.
Купон и правило корзины имеют разные сроки действия — это проблема?
Да, это частая причина ошибок. Если срок правила уже вышел, купон формально валиден, но скидки не даст. Синхронизируйте даты обеих сущностей.
Поможем с настройкой и поддержкой 1С-Битрикс: Управление сайтом
Поможем с настройкой, доработкой и поддержкой 1С-Битрикс: Управление сайтом.