Настройка холдирования средств на 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка холдирования средств на 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1175
  • 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 — Холд (авторизация): магазин отправляет запрос в платёжную систему на резервирование суммы. Деньги не списаны, но заблокированы на карте. Банк-эквайер выдаёт pre_auth_code или аналогичный идентификатор авторизации.

Стадия 2 — Подтверждение (capture): магазин подтверждает списание, когда товар готов к отгрузке. Деньги переходят на счёт магазина. Либо — отмена (void/cancel): если товара нет, резерв снимается без комиссий.

Битрикс реализует это через модуль sale, класс \Bitrix\Sale\PaySystem\Manager и конкретные обработчики платёжных систем.

Поддержка двухстадийной оплаты в модуле sale

Не все платёжные системы в Битрикс поддерживают двухстадийную оплату. Встроенная поддержка есть у:

  • Сбербанк (через SberPayment handler)
  • Тинькофф (TinkoffPayment)
  • ЮКасса — YooKassa (YandexMoney)
  • Альфа-Банк (AlfaPayment)

Конфигурация платёжной системы в административной панели: «Магазин» → «Оплата» → выбрать платёжную систему → вкладка «Настройки» → параметр «Двухстадийная оплата» или «Режим холдирования».

Конфигурация холдирования в таблице базы данных

Параметры платёжной системы хранятся в таблице b_sale_pay_system и b_sale_pay_system_handler:

-- Найти ID платёжной системы
SELECT ID, NAME, HANDLER_TYPE FROM b_sale_pay_system WHERE ACTIVE = 'Y';

-- Параметры конкретной платёжной системы
SELECT PS_ID, CODE, VALUE FROM b_sale_pay_system_params WHERE PS_ID = 5;

Программная работа с холдированием

Статусы оплаты в b_sale_payment:

  • N — не оплачен
  • Y — оплачен (деньги списаны)

Кастомные статусы холдирования обычно хранятся в дополнительных полях или через b_sale_order_props.

Подтверждение оплаты (capture) через API:

use Bitrix\Sale;

// Получить заказ
$order = Sale\Order::load($orderId);

// Получить оплату
$paymentCollection = $order->getPaymentCollection();
foreach ($paymentCollection as $payment) {
    if (!$payment->isPaid()) {
        // Подтвердить холдированный платёж
        $result = Sale\PaySystem\Manager::confirm($payment);
        if (!$result->isSuccess()) {
            // Обработать ошибку
            $errors = $result->getErrorMessages();
        }
    }
}

Отмена холдирования:

foreach ($paymentCollection as $payment) {
    $result = Sale\PaySystem\Manager::cancel($payment);
    if ($result->isSuccess()) {
        // Обнуляем сумму оплаты
        $payment->setField('SUM', 0);
    }
}
$order->save();

Обработчик события подтверждения заказа

Автоматическое подтверждение (capture) при переводе заказа в статус «Подтверждён»:

// /bitrix/php_interface/init.php
use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandler(
    'sale',
    'OnSaleStatusOrderChange',
    function(\Bitrix\Main\Event $event) {
        $order = $event->getParameter('ENTITY');
        $value = $event->getParameter('VALUE');

        // Статус "подтверждён" — подтвердить холд
        if ($value === 'C') { // ID вашего статуса подтверждения
            $paymentCollection = $order->getPaymentCollection();
            foreach ($paymentCollection as $payment) {
                if (!$payment->isPaid()) {
                    \Bitrix\Sale\PaySystem\Manager::confirm($payment);
                }
            }
        }

        // Статус "отменён" — снять холд
        if ($value === 'F') {
            $paymentCollection = $order->getPaymentCollection();
            foreach ($paymentCollection as $payment) {
                \Bitrix\Sale\PaySystem\Manager::cancel($payment);
            }
        }
    }
);

Срок действия холдирования

Банки ограничивают срок холдирования. Сбербанк — до 30 дней, большинство зарубежных эквайеров — 7 дней. Если за этот срок не подтвердить или не отменить, банк автоматически снимает резерв.

Настроить агент Битрикс, который проверяет просроченные холды:

// Агент: ProccessExpiredHolds()
function ProccessExpiredHolds() {
    // Найти оплаты в статусе холд, старше 5 дней
    $cutoffDate = new \Bitrix\Main\Type\DateTime();
    $cutoffDate->add('-5D');

    $res = \Bitrix\Sale\Internals\PaymentTable::getList([
        'filter' => [
            'PAID' => 'N',
            '<DATE_BILL' => $cutoffDate,
            '!SUM' => 0
        ],
        'select' => ['ID', 'ORDER_ID']
    ]);

    while ($row = $res->fetch()) {
        // Отправить уведомление менеджеру о необходимости обработать заказ
        \CEvent::Send('HOLD_EXPIRING', 's1', [
            'ORDER_ID' => $row['ORDER_ID']
        ]);
    }

    return 'ProccessExpiredHolds();';
}