Разработка системы аукциона на 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка системы аукциона на 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • 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С-Битрикс

Аукцион на сайте — это механизм продаж, где цена товара определяется конкуренцией покупателей: побеждает тот, кто в отведённое время предложил наибольшую сумму. 1С-Битрикс не содержит аукционной логики — её нужно разрабатывать поверх стандартных модулей catalog и sale.

Типы аукционов

Перед разработкой важно зафиксировать бизнес-требования по типу аукциона:

Тип Описание Особенности
Английский (открытый) Ставки растут, побеждает максимальная Самый распространённый
Нидерландский (обратный) Цена снижается, побеждает первый согласившийся Нужен таймер снижения цены
Авто-ставка Указывается максимум, система торгуется автоматически Сложная логика
«Купи сейчас» Аукцион + фиксированная цена для мгновенной покупки Параллельный канал продажи

Структура данных

Аукционный лот — расширение товарной карточки. Хранение через свойства инфоблока или отдельные таблицы.

Таблица b_local_auction:

Поле Тип Описание
ID int Первичный ключ
PRODUCT_ID int Ссылка на элемент инфоблока
START_PRICE decimal Стартовая цена
MIN_STEP decimal Минимальный шаг ставки
CURRENT_PRICE decimal Текущая максимальная ставка
CURRENT_WINNER_ID int ID пользователя с ведущей ставкой
RESERVE_PRICE decimal Резервная цена (скрытая)
BUY_NOW_PRICE decimal Цена «Купить сейчас» (опционально)
START_TIME datetime Начало аукциона
END_TIME datetime Конец аукциона
STATUS enum PENDING, ACTIVE, ENDED, CANCELLED
BIDS_COUNT int Количество ставок

Таблица b_local_auction_bid — история ставок:

Поле Описание
AUCTION_ID Ссылка на аукцион
USER_ID Участник
AMOUNT Сумма ставки
AUTO_MAX Максимум для авто-ставки
CREATED_AT Время ставки
IP IP-адрес (для антифрода)

Логика принятия ставки

Принятие новой ставки — критическая секция: несколько пользователей могут делать ставки одновременно. Без блокировок возникнут гонки данных.

function placeBid(int $auctionId, int $userId, float $amount): BidResult
{
    // Начало транзакции с блокировкой строки аукциона
    $connection = \Bitrix\Main\Application::getConnection();
    $connection->startTransaction();

    try {
        // SELECT FOR UPDATE — блокируем строку
        $auction = $connection->query(
            "SELECT * FROM b_local_auction WHERE ID = {$auctionId} FOR UPDATE"
        )->fetch();

        // Валидации
        if ($auction['STATUS'] !== 'ACTIVE') {
            throw new \Exception('Аукцион не активен');
        }
        if (new DateTime() > new DateTime($auction['END_TIME'])) {
            throw new \Exception('Аукцион завершён');
        }
        if ($amount < $auction['CURRENT_PRICE'] + $auction['MIN_STEP']) {
            throw new \Exception('Ставка ниже минимальной: ' . ($auction['CURRENT_PRICE'] + $auction['MIN_STEP']));
        }
        if ($auction['CURRENT_WINNER_ID'] === $userId) {
            throw new \Exception('Вы уже лидируете');
        }

        // Записать ставку
        AuctionBidTable::add([
            'AUCTION_ID' => $auctionId,
            'USER_ID' => $userId,
            'AMOUNT' => $amount,
            'CREATED_AT' => new DateTime(),
        ]);

        // Обновить текущую ставку
        AuctionTable::update($auctionId, [
            'CURRENT_PRICE' => $amount,
            'CURRENT_WINNER_ID' => $userId,
            'BIDS_COUNT' => $auction['BIDS_COUNT'] + 1,
        ]);

        // Продление времени при ставке в последние минуты
        if ((new DateTime($auction['END_TIME']))->getTimestamp() - time() < 300) {
            AuctionTable::update($auctionId, [
                'END_TIME' => (new DateTime())->modify('+5 minutes'),
            ]);
        }

        $connection->commitTransaction();

        // Уведомить предыдущего лидера
        notifyOutbid($auction['CURRENT_WINNER_ID'], $auctionId, $amount);

    } catch (\Exception $e) {
        $connection->rollbackTransaction();
        throw $e;
    }
}

Real-time обновления

Аукцион требует отображения текущей ставки без перезагрузки страницы. Варианты:

Polling — самый простой: JavaScript делает AJAX-запрос каждые 5-10 секунд.

setInterval(() => {
    fetch('/local/ajax/auction_state.php?id=' + auctionId)
        .then(r => r.json())
        .then(data => updateUI(data));
}, 5000);

Server-Sent Events (SSE) — сервер сам отправляет события при изменении. Меньше нагрузки, чем polling.

WebSocket — максимально real-time, но требует отдельного сервера (Node.js, Ratchet). На Битрикс-хостинге может быть недоступно.

Для большинства аукционов polling с интервалом 5-10 секунд — достаточное решение.

Завершение аукциона и создание заказа

Агент проверяет аукционы, у которых истекло END_TIME:

$ended = AuctionTable::getList([
    'filter' => ['STATUS' => 'ACTIVE', '<END_TIME' => new DateTime()]
])->fetchAll();

foreach ($ended as $auction) {
    AuctionTable::update($auction['ID'], ['STATUS' => 'ENDED']);

    if ($auction['CURRENT_WINNER_ID'] && $auction['CURRENT_PRICE'] >= $auction['RESERVE_PRICE']) {
        // Уведомить победителя
        notifyWinner($auction['CURRENT_WINNER_ID'], $auction);
        // Создать заказ или отправить ссылку на оплату
        createAuctionOrder($auction);
    } else {
        // Резервная цена не достигнута
        notifyReserveNotMet($auction);
    }
}

Антифрод и правила

  • Один пользователь не может делать ставки от нескольких аккаунтов — проверка по IP + cookies + истории аккаунта.
  • Ставки только от авторизованных пользователей.
  • Опционально: верификация телефона или предоплата (блокировка суммы) для доступа к аукциону.
  • Минимальный аккаунт: зарегистрирован N дней назад, сделал хотя бы один заказ.

Сроки разработки

Вариант Состав Срок
Базовый аукцион Английский, ставки, таймер, polling 8-10 дней
Расширенный Авто-ставка, «купить сейчас», уведомления 12-16 дней
Полная платформа Несколько типов, WebSocket, аналитика, антифрод 20-30 дней