Настройка продажи подарочных карт на 1С-Битрикс
Подарочный сертификат — это товар, оплата которого создаёт купон на сумму, равную номиналу карты. Покупатель получает код, приходит снова, вводит код, и с его баланса списывается сумма заказа. Три точки отказа: некорректное создание купона, неправильное списание, двойное использование.
Сертификат как товар с типом SERVICE
В Битриксе подарочная карта реализуется как товар с типом TYPE_SERVICE (значение 7) в b_catalog_product.TYPE, либо через модуль sale.gift.certificate если он подключён в редакции. Разберём реализацию через тип SERVICE — она доступна в Business и Enterprise без дополнительных модулей.
Товар-сертификат создаётся как обычный элемент инфоблока каталога. На него устанавливается тип 7:
\Bitrix\Catalog\ProductTable::update($productId, [
'TYPE' => \Bitrix\Catalog\ProductTable::TYPE_SERVICE,
'QUANTITY_TRACE' => 'N',
'CAN_BUY_ZERO' => 'Y',
]);
При TYPE_SERVICE Битрикс не учитывает остатки и не создаёт складских движений при покупке.
Создание купона при оплате
После оплаты заказа с сертификатом нужно создать купон на соответствующую сумму. Это делается в обработчике OnSaleOrderPaid:
AddEventHandler('sale', 'OnSaleOrderPaid', function(\Bitrix\Main\Event $event) {
$order = $event->getParameter('ENTITY');
foreach ($order->getBasket() as $item) {
if ($item->getField('TYPE') == \Bitrix\Catalog\ProductTable::TYPE_SERVICE) {
// Проверить что это сертификат по свойству товара
$isCert = checkIsGiftCertificate($item->getProductId());
if (!$isCert) continue;
$code = generateCertificateCode();
$amount = $item->getPrice() * $item->getQuantity();
// Создать купон
\Bitrix\Sale\DiscountCouponsManager::add([
'COUPON' => $code,
'TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER,
'ACTIVE' => 'Y',
'ACTIVE_FROM' => new \Bitrix\Main\Type\DateTime(),
'MAX_USE' => 1,
'COUPON_APPLY' => \Bitrix\Sale\DiscountCouponsManager::COUPON_APPLY_ANY,
]);
// Сохранить связь: код → сумма → пользователь
saveCertificateToCustomTable($code, $amount, $order->getUserId());
// Отправить код на email покупателя
sendCertificateEmail($code, $amount, $order);
}
}
});
Скидка на сумму сертификата
Купон в Битриксе привязывается к скидке через b_sale_discount. Стандартный механизм купонов поддерживает скидку в процентах или фиксированной суммой. Для сертификата нужна фиксированная скидка на полную сумму номинала.
Создание скидки под сертификат:
$discountResult = \Bitrix\Sale\Internals\DiscountTable::add([
'LID' => 's1',
'ACTIVE' => 'Y',
'NAME' => 'Подарочный сертификат ' . $code,
'TYPE' => 'D', // скидка
'COUPON_TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER,
'MAX_DISCOUNT' => $amount,
'VALUE_TYPE' => 'F', // фиксированная сумма
'VALUE' => $amount,
'CURRENCY' => 'BYN',
'SORT' => 100,
]);
Купон добавляется к созданной скидке через \Bitrix\Sale\DiscountCouponsManager::add() с DISCOUNT_ID = $discountResult->getId().
Защита от двойного использования
Поле MAX_USE в купоне ограничивает количество применений. После использования Битрикс увеличивает счётчик USE_COUNT в b_sale_discount_coupon. При USE_COUNT >= MAX_USE купон деактивируется.
Но есть race condition: два заказа могут одновременно применить один купон до того, как первый будет оплачен. Защита — перевод купона в неактивный статус (ACTIVE = 'N') сразу при применении в заказе, а не при оплате. Это делается в обработчике OnSaleOrderBeforeSaved.
Частичное использование
Если сумма заказа меньше номинала сертификата, остаток сохраняется. Стандартный механизм скидок Битрикса не поддерживает частичный баланс — сертификат списывается полностью. Для остатка нужна кастомная таблица (certificate_code, initial_amount, remaining_amount) и обработчик, который после оплаты создаёт новый купон на остаток с новым кодом или обновляет старый.







