Development of an auction system on 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Developing an Auction System for 1C-Bitrix

An auction on a website is a sales mechanism where the product's price is determined by buyer competition: the winner is the one who offered the highest amount within the allotted time. 1C-Bitrix does not contain auction logic — it must be developed on top of the standard catalog and sale modules.

Types of Auctions

Before development, it's important to define business requirements by auction type:

Type Description Features
English (Open) Bids rise, highest wins Most common
Dutch (Reverse) Price drops, first to agree wins Needs price drop timer
Auto-bid Maximum bid set, system bids automatically Complex logic
"Buy Now" Auction + fixed price for instant purchase Parallel sales channel

Data Structure

An auction lot is an extension of the product card. Storage via infoblock properties or separate tables.

Table b_local_auction:

Field Type Description
ID int Primary key
PRODUCT_ID int Link to infoblock element
START_PRICE decimal Starting price
MIN_STEP decimal Minimum bid increment
CURRENT_PRICE decimal Current maximum bid
CURRENT_WINNER_ID int User ID with leading bid
RESERVE_PRICE decimal Reserve price (hidden)
BUY_NOW_PRICE decimal "Buy Now" price (optional)
START_TIME datetime Auction start
END_TIME datetime Auction end
STATUS enum PENDING, ACTIVE, ENDED, CANCELLED
BIDS_COUNT int Number of bids

Table b_local_auction_bid — bid history:

Field Description
AUCTION_ID Link to auction
USER_ID Participant
AMOUNT Bid amount
AUTO_MAX Maximum for auto-bid
CREATED_AT Bid time
IP IP address (for anti-fraud)

Bid Acceptance Logic

Accepting a new bid is a critical section: multiple users can place bids simultaneously. Without locks, data races occur.

function placeBid(int $auctionId, int $userId, float $amount): BidResult
{
    // Start transaction with row locking
    $connection = \Bitrix\Main\Application::getConnection();
    $connection->startTransaction();

    try {
        // SELECT FOR UPDATE — lock the row
        $auction = $connection->query(
            "SELECT * FROM b_local_auction WHERE ID = {$auctionId} FOR UPDATE"
        )->fetch();

        // Validations
        if ($auction['STATUS'] !== 'ACTIVE') {
            throw new \Exception('Auction is not active');
        }
        if (new DateTime() > new DateTime($auction['END_TIME'])) {
            throw new \Exception('Auction is finished');
        }
        if ($amount < $auction['CURRENT_PRICE'] + $auction['MIN_STEP']) {
            throw new \Exception('Bid below minimum: ' . ($auction['CURRENT_PRICE'] + $auction['MIN_STEP']));
        }
        if ($auction['CURRENT_WINNER_ID'] === $userId) {
            throw new \Exception('You are already leading');
        }

        // Record the bid
        AuctionBidTable::add([
            'AUCTION_ID' => $auctionId,
            'USER_ID' => $userId,
            'AMOUNT' => $amount,
            'CREATED_AT' => new DateTime(),
        ]);

        // Update current bid
        AuctionTable::update($auctionId, [
            'CURRENT_PRICE' => $amount,
            'CURRENT_WINNER_ID' => $userId,
            'BIDS_COUNT' => $auction['BIDS_COUNT'] + 1,
        ]);

        // Extend time if bid in last minutes
        if ((new DateTime($auction['END_TIME']))->getTimestamp() - time() < 300) {
            AuctionTable::update($auctionId, [
                'END_TIME' => (new DateTime())->modify('+5 minutes'),
            ]);
        }

        $connection->commitTransaction();

        // Notify previous leader
        notifyOutbid($auction['CURRENT_WINNER_ID'], $auctionId, $amount);

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

Real-time Updates

An auction requires displaying the current bid without page reload. Options:

Polling — simplest: JavaScript makes AJAX request every 5-10 seconds.

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

Server-Sent Events (SSE) — server sends events when it changes. Less load than polling.

WebSocket — maximum real-time, but requires separate server (Node.js, Ratchet). May be unavailable on Bitrix hosting.

For most auctions, polling with 5-10 second intervals is sufficient.

Auction Completion and Order Creation

An agent checks auctions with expired 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']) {
        // Notify winner
        notifyWinner($auction['CURRENT_WINNER_ID'], $auction);
        // Create order or send payment link
        createAuctionOrder($auction);
    } else {
        // Reserve price not met
        notifyReserveNotMet($auction);
    }
}

Anti-fraud and Rules

  • One user cannot place bids from multiple accounts — check by IP + cookies + account history.
  • Bids only from authorized users.
  • Optional: phone verification or prepayment (amount reservation) for auction access.
  • Minimum account: registered N days ago, made at least one purchase.

Development Timeline

Option Scope Timeline
Basic Auction English, bids, timer, polling 8-10 days
Extended Auto-bid, "buy now", notifications 12-16 days
Full Platform Multiple types, WebSocket, analytics, anti-fraud 20-30 days