Setting up notifications about the 1C-Bitrix return status

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
    1173
  • 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
    745
  • 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 Return Status Notifications in 1C-Bitrix

Notifications upon a return status change are a touchpoint where a store either builds trust or loses a customer. A buyer waiting for a return decision is anxious. A timely email with a status update eliminates calls to support and creates a positive experience even in a return situation. In Bitrix, this is handled by the mail template system (b_event_type, b_event_message) in conjunction with events from the sale module.

Notification Mechanism in Bitrix

Notifications are built on three levels:

  1. Mail event type (b_event_type) — defines the set of available variables
  2. Mail event template (b_event_message) — HTML body, subject, and recipient
  3. CEvent::Send() call — the sending trigger, passes variable values

Registering Event Types for Return Statuses

One event type per status where the buyer needs to be notified:

// /local/install/register_return_events.php
$returnEventTypes = [
    [
        'EVENT_NAME'  => 'RETURN_STATUS_REVIEW',
        'NAME'        => 'Return: Accepted for review',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, ORDER_ACCOUNT_NUMBER, USER_NAME, USER_EMAIL, STATUS_NAME",
        'SORT'        => 100,
    ],
    [
        'EVENT_NAME'  => 'RETURN_STATUS_NEED_DOCS',
        'NAME'        => 'Return: Documents required',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, ORDER_ACCOUNT_NUMBER, USER_NAME, USER_EMAIL, STATUS_NAME, MANAGER_COMMENT",
        'SORT'        => 110,
    ],
    [
        'EVENT_NAME'  => 'RETURN_STATUS_APPROVED',
        'NAME'        => 'Return: Approved',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, REFUND_AMOUNT, SHIPPING_INSTRUCTIONS",
        'SORT'        => 120,
    ],
    [
        'EVENT_NAME'  => 'RETURN_STATUS_RECEIVED',
        'NAME'        => 'Return: Item received at warehouse',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, REFUND_AMOUNT",
        'SORT'        => 130,
    ],
    [
        'EVENT_NAME'  => 'RETURN_STATUS_REFUND',
        'NAME'        => 'Return: Funds refunded',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, REFUND_AMOUNT, REFUND_DATE, PAYMENT_METHOD",
        'SORT'        => 140,
    ],
    [
        'EVENT_NAME'  => 'RETURN_STATUS_REJECTED',
        'NAME'        => 'Return: Rejected',
        'DESCRIPTION' => "RETURN_ID, ORDER_ID, MANAGER_COMMENT, APPEAL_INSTRUCTIONS",
        'SORT'        => 150,
    ],
];

$eventType = new \CEventType();

foreach ($returnEventTypes as $type) {
    $existing = \CEventType::GetList(['EVENT_NAME' => $type['EVENT_NAME']])->Fetch();
    if (!$existing) {
        $eventType->Add(array_merge($type, ['LID' => LANGUAGE_ID]));
    }
}

Sending Notifications on Status Change

namespace Local\Returns;

class Notifications
{
    private const STATUS_EVENT_MAP = [
        'REVIEW'    => 'RETURN_STATUS_REVIEW',
        'NEED_DOCS' => 'RETURN_STATUS_NEED_DOCS',
        'APPROVED'  => 'RETURN_STATUS_APPROVED',
        'RECEIVED'  => 'RETURN_STATUS_RECEIVED',
        'REFUND'    => 'RETURN_STATUS_REFUND',
        'REJECTED'  => 'RETURN_STATUS_REJECTED',
    ];

    public static function sendStatusChange(int $returnId, string $newStatus): void
    {
        $eventName = self::STATUS_EVENT_MAP[$newStatus] ?? null;
        if (!$eventName) return;

        $data = self::buildEventData($returnId, $newStatus);
        if (!$data) return;

        \CEvent::Send($eventName, SITE_ID, $data);
    }

    private static function buildEventData(int $returnId, string $status): ?array
    {
        $return = \Bitrix\Sale\OrderReturnTable::getList([
            'filter' => ['ID' => $returnId],
            'select' => ['ID', 'ORDER_ID', 'REFUND_AMOUNT', 'STATUS_ID', 'MANAGER_COMMENT'],
        ])->fetch();

        if (!$return) return null;

        $order = \Bitrix\Sale\Order::load($return['ORDER_ID']);
        if (!$order) return null;

        $user = \CUser::GetByID($order->getUserId())->Fetch();

        $data = [
            'RETURN_ID'           => $returnId,
            'ORDER_ID'            => $return['ORDER_ID'],
            'ORDER_ACCOUNT_NUMBER'=> $order->getField('ACCOUNT_NUMBER'),
            'USER_NAME'           => trim(($user['NAME'] ?? '') . ' ' . ($user['LAST_NAME'] ?? '')),
            'USER_EMAIL'          => $user['EMAIL'] ?? '',
            'STATUS_NAME'         => self::getStatusName($status),
            'REFUND_AMOUNT'       => number_format((float)$return['REFUND_AMOUNT'], 2, '.', ' ') . ' RUB',
            'MANAGER_COMMENT'     => $return['MANAGER_COMMENT'] ?? '',
            'RETURN_URL'          => self::getReturnUrl($returnId),
        ];

        // Status-specific data
        if ($status === 'APPROVED') {
            $data['SHIPPING_INSTRUCTIONS'] = self::getShippingInstructions();
        }

        if ($status === 'REFUND') {
            $data['REFUND_DATE']    = (new \Bitrix\Main\Type\DateTime())->format('d.m.Y');
            $data['PAYMENT_METHOD'] = self::getPaymentMethodName($order);
        }

        if ($status === 'REJECTED') {
            $data['APPEAL_INSTRUCTIONS'] = 'You may contact us by phone +7 (800) 555-35-35';
        }

        return $data;
    }

    private static function getStatusName(string $statusId): string
    {
        $result = \CSaleOrderReturnStatus::GetByID($statusId);
        return $result['NAME'] ?? $statusId;
    }

    private static function getReturnUrl(int $returnId): string
    {
        return 'https://' . SITE_SERVER_NAME . '/personal/returns/' . $returnId . '/';
    }
}

Hooking into the Status Change Handler

// In init.php — attach notifications to sale module events
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
    'sale',
    'OnSaleOrderReturnStatusChange',
    function (\Bitrix\Main\Event $event) {
        $returnId  = $event->getParameter('RETURN_ID');
        $newStatus = $event->getParameter('NEW_STATUS_ID');

        \Local\Returns\Notifications::sendStatusChange($returnId, $newStatus);
    }
);

SMS Notifications

For critical statuses (funds refunded, approved) add SMS via SMSC, SMS.ru, or another provider:

class SmsNotifier
{
    private const SMS_STATUSES = ['APPROVED', 'REFUND', 'REJECTED'];

    public static function maybeSend(int $returnId, string $status): void
    {
        if (!in_array($status, self::SMS_STATUSES, true)) return;

        $phone = self::getCustomerPhone($returnId);
        if (!$phone) return;

        $text = self::buildSmsText($returnId, $status);

        $client = new \Local\Sms\SmsClient();
        $client->send($phone, $text);
    }

    private static function buildSmsText(int $returnId, string $status): string
    {
        return match ($status) {
            'APPROVED' => "Return #{$returnId} approved. Please ship the item to: ...",
            'REFUND'   => "Return #{$returnId}: funds sent. Will arrive within 3–5 business days.",
            'REJECTED' => "Return #{$returnId} rejected. Reason sent to your email.",
            default    => "Return request #{$returnId} status has been updated.",
        };
    }
}

Push Notifications in the Personal Account

In addition to email and SMS — browser notifications via Web Push or through the personal account notification mechanism:

// Add notification to the Bitrix personal account (if im module or custom mechanism is available)
class LkNotifier
{
    public static function notify(int $userId, int $returnId, string $status): void
    {
        // Via the im module (corporate portal)
        if (\Bitrix\Main\Loader::includeModule('im')) {
            \CIMNotify::Add([
                'FROM_USER_ID' => 0, // from system
                'TO_USER_ID'   => $userId,
                'NOTIFY_TYPE'  => IM_NOTIFY_SYSTEM,
                'NOTIFY_MODULE'=> 'local.returns',
                'NOTIFY_TAG'   => 'RETURN_' . $returnId,
                'NOTIFY_MESSAGE' => "Return request #{$returnId} status changed to «" .
                    \Local\Returns\Notifications::getStatusName($status) . "»",
                'NOTIFY_MESSAGE_OUT' => 'Return request status updated',
            ]);
        }
    }
}

Email Template: "Approved" Status

Sample HTML template for the RETURN_STATUS_APPROVED event:

Subject: Your return request #[RETURN_ID] has been approved

Dear [USER_NAME],

Your request to return an item from order [ORDER_ACCOUNT_NUMBER] has been approved.

Refund amount: [REFUND_AMOUNT]

To complete the return, please ship the item to:
[SHIPPING_INSTRUCTIONS]

Once we receive the item at our warehouse, funds will be transferred within 3 business days.

Track your return status: [RETURN_URL]

Scope of Work

  • Register mail event types for each status
  • HTML email templates: subject, body, variable lists
  • OnSaleOrderReturnStatusChange handler → CEvent::Send() call
  • SMS notifications for critical statuses
  • Personal account notifications via the IM module or custom mechanism
  • Testing: verify all status transitions and email delivery

Timeline: full set of notifications for all statuses — 1–2 weeks.