Setting up cashback accrual for 1C-Bitrix purchases

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
    1175
  • 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

Configuring Cashback Accrual for Purchases in 1C-Bitrix

Cashback accrual is one component of a cashback system that can be configured even without full custom development. 1C-Bitrix has a built-in bonus points mechanism through the sale module. If requirements are simple (a fixed percentage on all purchases, without category-based rules), this can be launched using standard tooling.

1C-Bitrix Built-in Bonus Mechanism

1C-Bitrix stores bonus points in the following tables:

  • b_sale_user_account — user account
  • b_sale_account_user_balance — account balance

Management via \Bitrix\Sale\PersonalBonus (D7) or CSaleUserAccount (legacy API).

Configuration in the admin panel: Store → Cumulative Discounts → Bonuses.

Accrual via Order Payment Event

If the standard mechanism does not meet requirements, programmatic accrual:

\Bitrix\Main\EventManager::getInstance()->addEventHandler(
    'sale',
    'OnSaleOrderPaid',
    function (\Bitrix\Main\Event $event) {
        $order   = $event->getParameter('ENTITY');
        $userId  = $order->getUserId();
        $total   = $order->getPrice();

        // Cashback percentage from settings
        $percent = (float)\Bitrix\Main\Config\Option::get(
            'local.cashback', 'base_percent', '3'
        );

        $cashback = round($total * $percent / 100, 2);
        if ($cashback <= 0) {
            return;
        }

        \Local\Cashback\AccountManager::earn(
            $userId,
            $cashback,
            "Cashback {$percent}% for order #{$order->getId()}",
            $order->getId()
        );
    }
);

Accrual Only for Confirmed Orders

To avoid accruing cashback for returned orders, use a two-step accrual process:

  1. On order creation — transaction with pending status
  2. On transition to "Fulfilled" — confirmation (status confirmed)
  3. On cancellation — annulment of pending transactions
// Confirm accrual on order fulfillment
$em->addEventHandler('sale', 'OnSaleOrderStatusChange', function ($event) {
    $order = $event->getParameter('ENTITY');
    if ($order->getField('STATUS_ID') === 'F') {
        \Local\Cashback\AccountManager::confirmByOrderId($order->getId());
    } elseif ($order->getField('STATUS_ID') === 'X') {
        \Local\Cashback\AccountManager::cancelByOrderId($order->getId());
    }
});

Displaying Cashback on the Product Page

The customer sees "You will earn 45 cashback" before placing an order — this increases conversion.

// In the product page template
$price   = \CPrice::GetBasePrice($elementId);
$percent = (float)\Bitrix\Main\Config\Option::get('local.cashback', 'base_percent', '3');
$cashbackPreview = $price ? round($price['PRICE'] * $percent / 100, 0) : 0;
<?php if ($cashbackPreview > 0): ?>
<div class="cashback-preview">
    Cashback: <strong><?= $cashbackPreview ?></strong>
</div>
<?php endif; ?>

Exclusions from Accrual

Products, categories, or brands excluded from cashback accrual (already discounted items, zero-margin products):

function isExcludedFromCashback(int $productId): bool
{
    $props = \CIBlockElement::GetProperty(
        CATALOG_IBLOCK_ID, $productId,
        [], ['CODE' => 'CASHBACK_EXCLUDED']
    )->Fetch();

    return $props && $props['VALUE'] === 'Y';
}

The CASHBACK_EXCLUDED Yes/No property is added to the catalog and set by a manager manually or during import from 1C.

Implementation Timeline

Payment event handler with accrual, two-step confirmation, cashback display on the product page, exclusions — 1–2 business days.