Настройка единой программы лояльности онлайн и оффлайн 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка единой программы лояльности онлайн и оффлайн 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1181
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    813
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка единой программы лояльности онлайн и оффлайн 1С-Битрикс

Клиент накопил 500 бонусов на сайте и пришёл в магазин их потратить. Кассир не видит бонусов — они в другой системе. Или наоборот: покупка в магазине не начисляет баллы на онлайн-аккаунт. Разрыв между онлайн и оффлайн программой лояльности — это не только UX-проблема, но и прямые потери на повторных покупках.

Как устроена лояльность в Битрикс

Модуль sale реализует дисконтную систему через b_sale_user_discount (персональные скидки) и бонусную систему через b_sale_discount (правила корзины). Для полноценной программы лояльности (накопительные баллы) используется отдельный модуль или интеграция с внешней системой.

В Битрикс24 есть CRM-модуль с бонусами (b_crm_loyalty_bonus_transaction), но для интернет-магазина без Битрикс24 чаще применяется либо модуль marketingcrm, либо собственная таблица транзакций.

Структура хранения бонусов

Минимальная структура для единой программы:

CREATE TABLE bl_loyalty_account (
    id          SERIAL PRIMARY KEY,
    user_id     INT UNIQUE,           -- b_user.ID (онлайн)
    card_number VARCHAR(20) UNIQUE,   -- номер карты для оффлайн
    balance     NUMERIC(10,2) DEFAULT 0,
    created_at  TIMESTAMP DEFAULT NOW()
);

CREATE TABLE bl_loyalty_transaction (
    id          SERIAL PRIMARY KEY,
    account_id  INT NOT NULL REFERENCES bl_loyalty_account(id),
    amount      NUMERIC(10,2) NOT NULL,  -- положительное=начисление, отрицательное=списание
    type        VARCHAR(20) NOT NULL,    -- 'earn_online', 'earn_offline', 'spend', 'expire'
    order_id    INT,                     -- b_sale_order.ID или внешний ID оффлайн-чека
    source      VARCHAR(20) NOT NULL,    -- 'web', 'pos', 'mobile'
    created_at  TIMESTAMP DEFAULT NOW()
);

Транзакционная модель с историей — единственный надёжный способ хранить бонусы. Никогда не обновляйте balance напрямую без записи транзакции. balance — это либо денормализованный агрегат (обновляется триггером БД), либо считается как SUM(amount) по таблице транзакций.

Идентификация клиента на оффлайн-кассе

Ключевая задача: кассир должен найти аккаунт клиента. Способы идентификации:

  • Номер карты лояльности (физическая карта или штрихкод в мобильном приложении)
  • Номер телефона
  • QR-код с токеном (генерируется в личном кабинете сайта)

При идентификации по телефону кассовое ПО отправляет запрос к API Битрикс:

// /local/ajax/loyalty/find-account.php
$phone     = normalizePhone($_POST['phone']);
$bitrixUser = \CUser::GetList([], ['PERSONAL_PHONE' => $phone])->Fetch();

if ($bitrixUser) {
    $account = getLoyaltyAccount($bitrixUser['ID']);
    echo json_encode(['balance' => $account['balance'], 'account_id' => $account['id']]);
}

Начисление бонусов при онлайн-заказе

Обработчик смены статуса заказа — после доставки/завершения:

AddEventHandler('sale', 'OnSaleStatusOrderChange', function(\Bitrix\Main\Event $event) {
    $order  = $event->getParameter('ENTITY');
    $status = $order->getField('STATUS_ID');

    if ($status !== 'F') return; // Только завершённые заказы

    $userId = $order->getUserId();
    $bonus  = round($order->getPrice() * BONUS_RATE); // BONUS_RATE = 0.05 (5%)

    addLoyaltyTransaction($userId, $bonus, 'earn_online', $order->getId(), 'web');
});

Списание бонусов при онлайн-оплате

Бонусы применяются через правило корзины или через кастомный платёжный метод. Правило корзины (b_sale_discount) может давать скидку фиксированной суммой. Для более гибкой схемы — собственный «платёжный метод» типа «Оплата бонусами», который при проведении заказа списывает транзакцию из bl_loyalty_transaction.

Синхронизация через API для оффлайн-кассы

Оффлайн-касса вызывает три endpoint:

  1. GET /loyalty/balance?phone=... — проверить баланс
  2. POST /loyalty/spend — списать бонусы при продаже (должен быть транзакционным: начало продажи → резервирование → подтверждение)
  3. POST /loyalty/earn — начислить бонусы после продажи

Резервирование при списании — критически важный шаг. Без него два параллельных запроса от разных касс могут одновременно прочитать баланс 500 бонусов и дважды списать по 500, уйдя в минус. Резервирование через SELECT ... FOR UPDATE в PostgreSQL или через строгое UPDATE с проверкой результата:

UPDATE bl_loyalty_account
SET balance = balance - :amount
WHERE id = :account_id AND balance >= :amount
RETURNING balance;
-- Если обновлено 0 строк — недостаточно бонусов

Что настраиваем

  • Таблицы bl_loyalty_account и bl_loyalty_transaction
  • API-endpoints для кассовых систем (баланс, начисление, списание)
  • Обработчики событий OnSaleStatusOrderChange для онлайн-начислений
  • Механизм идентификации клиента по телефону/карте
  • Транзакционное списание с защитой от race condition
  • Административный интерфейс для просмотра истории транзакций