Как через API Битрикс программно применить купон к корзине покупателя?

Как через API добавить купон в корзину? Перерыл всю документацию и код компонента корзины, но купон всё равно не сохраняется — в чём может быть проблема?
  • 24 марта 2026 г. 14:01
Ответы на вопрос 2
Коротко — купон нужно не просто «записать в БД», а пройти через менеджер купонов и заново пересчитать корзину/заказ. Частая ошибка — добавление купона в «нетот» контекст (неинициализированный site/fuser, неправильный режим менеджера) или отсутствие перерасчёта корзины, поэтому визуально купон не «сохраняется».

Ниже — рабочие варианты и чеклист для отладки.

1) Серверный (D7) — пример
(предполагается, что подключён модуль sale)

use Bitrix\Main\Loader;
use Bitrix\Sale;

Loader::includeModule('sale');

$siteId = SITE_ID;                     // или 's1'
$fuserId = Sale\Fuser::getId();        // ID временного покупателя

// Инициализируем менеджер купонов для текущего сайта
Sale\DiscountCouponsManager::init($siteId);
// Режим: для API/сценариев управления можно использовать MODE_MANAGER
Sale\DiscountCouponsManager::setMode(Sale\DiscountCouponsManager::MODE_MANAGER);

// Добавляем купон
Sale\DiscountCouponsManager::add($couponCode);

// Загружаем корзину и делаем перерасчёт, чтобы купон применился к позициям
$basket = Sale\Basket::loadItemsForFUser($fuserId, $siteId);

// Пересчитать скидки для корзины
\Bitrix\Sale\Discount::calculateBasket($basket);

// Получить список применённых купонов (если нужно)
$applied = Sale\DiscountCouponsManager::get(true);

// Сохранение/дальнейшие действия — например создание заказа с этой корзиной
// $order = Sale\Order::create($siteId, $userId); $order->setBasket($basket); $order->save();

2) Через AJAX (компонент корзины)
Если вы хотите «как делает корзина» — можно вызвать тот же AJAX-обработчик компонента:
POST /bitrix/components/bitrix/sale.basket.basket/ajax.php
параметры примерно: sessid, siteId, action = applyCoupon, coupon = 'CODE'
(точные параметры посмотрите в коде компонента в папке /bitrix/components/bitrix/sale.basket.basket)

3) Проблемы, из‑за которых купон «не сохраняется»
- Не подключён модуль sale (Loader::includeModule('sale')).
- Неинициализирован DiscountCouponsManager для текущего SITE_ID (важно при мультисайтах).
- Вы добавляете купон после того, как уже сделали финальный расчёт/сохранение заказа; нужно добавлять до расчёта.
- Не выполняете перерасчёт корзины/заказа после add(). Купон будет виден только после расчёта.
- Купон невалиден/истёк/привязан к другому сайту или пользователю, или имеет ограничения по товарам (тогда он не применится).
- Кеширование компонента корзины: компонент может показывать закешированные данные — почистите кеш или обновите компонент.
- Неправильный FUSER_ID / SITE_ID — купоны для fuser хранятся в привязке к fuser/site.
- Вы думаете, что «добавили в БД», но менеджер не создал запись в таблицах — лучше использовать DiscountCouponsManager, он правильно сохранит привязку.

4) Как проверить (дебаг)
- После add() вызовите Sale\DiscountCouponsManager::get(true) — должен вернуть массив с добавленным кодом.
- Посмотрите таблицу b_sale_discount_coupon (или через ORM \Bitrix\Sale\Internals\DiscountCouponTable) — должен появиться купон с FUSER_ID/SITE_ID.
- Включите логирование / var_dump результата \Bitrix\Sale\Discount::calculateBasket($basket) — посмотрите применённые скидки.

Если хотите, пришлите:
- фрагмент кода, как вы добавляете купон,
- SITE_ID и где/когда вы это выполняете (в момент запроса, в cron, после создания заказа),
— я проверю и укажу точную причину и правки.
примерно так: <br/> <pre><code>$couponinfo = \Bitrix\Sale\DiscountCouponsManager::getData($cupon, true); // получаем информацио о купоне
$addCoupon = \Bitrix\Sale\DiscountCouponsManager::add($cupon);</code></pre>
Похожие вопросы