Настройка интернет-эквайринга на 1С-Битрикс
Задача «подключить оплату картой» кажется тривиальной до первого инцидента в продакшне: статусы заказов не обновляются, деньги пришли — а заказ висит в «Ожидает оплаты». Причина — webhook от банка не доходит до сервера из-за WAF или ошибки PHP. Разберём полный цикл: от выбора схемы до диагностики таких ситуаций.
Три подхода к интеграции
Готовый модуль из Маркетплейса — Сбербанк, Тинькофф, ЮКасса, Альфа-Банк имеют официальные модули. Устанавливаются через /bitrix/admin/update_system.php. Плюс — быстро, поддерживается вендором. Минус — ограниченная гибкость.
Кастомный обработчик в /local/ — когда стандартный модуль не покрывает нужды: нестандартный маппинг статусов, кастомная фискализация, несколько эквайеров.
JS-виджет эквайера — CloudPayments, Robokassa встраиваются скриптом. Часть работы выполняется на клиенте, сервер только верифицирует результат.
Установка и настройка (пример: Тинькофф)
После установки модуля из Маркетплейса: Магазин → Настройки → Платёжные системы → Добавить → Тинькофф.
| Параметр | Источник |
|---|---|
| Terminal Key | ЛК Тинькофф Бизнес → Интернет-эквайринг |
| Secret Key | Там же |
| Notification URL | https://shop.ru/bitrix/tools/sale_ps_result.php |
| Success URL | Страница успешной оплаты |
Кастомный обработчик: минимальный каркас
<?php
// local/php_interface/include/sale_payment/mybank/handler.php
use Bitrix\Sale\PaySystem\BaseServiceHandler;
use Bitrix\Sale\PaySystem\ServiceResult;
use Bitrix\Sale\Payment;
use Bitrix\Main\Request;
class MyBankHandler extends BaseServiceHandler
{
public function initiatePay(Payment $payment, Request $request): ServiceResult
{
$result = new ServiceResult();
$order = $payment->getCollection()->getOrder();
$session = $this->createGatewaySession(
$order->getId(),
$payment->getSum()
);
if (empty($session['payUrl'])) {
$result->addError(new \Bitrix\Main\Error('Gateway error: ' . ($session['error'] ?? '')));
return $result;
}
$result->setPaymentUrl($session['payUrl']);
return $result;
}
public function processRequest(Payment $payment, Request $request): ServiceResult
{
$result = new ServiceResult();
$data = json_decode(file_get_contents('php://input'), true);
// ВСЕГДА верифицируем подпись — не доверяем данным из запроса
if (!$this->verifySignature($data)) {
$result->addError(new \Bitrix\Main\Error('Invalid signature'));
return $result;
}
if (($data['status'] ?? '') === 'PAID') {
$result->setOperationType(ServiceResult::MONEY_COMING);
}
return $result;
}
}
Диагностика: webhook не доходит
Самая частая причина — статусы заказов не меняются, хотя деньги списаны. Алгоритм диагностики:
# 1. Проверяем доступность endpoint извне
curl -v -X POST https://shop.ru/bitrix/tools/sale_ps_result.php -d 'test=1'
# Должен вернуть 200, не 403
# 2. Смотрим access.log на запросы от IP банка
grep "sale_ps_result" /var/log/nginx/access.log | tail -50
# 3. Временное логирование (только при отладке!)
file_put_contents('/tmp/ps_debug.log',
date('Y-m-d H:i:s') . ' ' . $_SERVER['REMOTE_ADDR'] . ' '
. file_get_contents('php://input') . PHP_EOL, FILE_APPEND
);
Типичные виновники:
- Cloudflare Bot Fight Mode блокирует POST-запросы без User-Agent браузера
- fail2ban заблокировал IP банка по количеству запросов
- PHP fatal error в обработчике без записи в лог
- HTTP → HTTPS редирект теряет тело POST-запроса
Двухстадийный эквайринг
Для магазинов, отгружающих после резервирования товара:
// При оформлении заказа — холдируем (PayType=T у Тинькофф)
// При смене статуса на "Отгружен" — подтверждаем списание
AddEventHandler('sale', 'OnSaleStatusOrder', function(\Bitrix\Main\Event $event) {
$order = $event->getParameter('ENTITY');
if ($order->getField('STATUS_ID') !== 'OD') return;
foreach ($order->getPaymentCollection() as $payment) {
if ($payment->getField('PS_STATUS') === 'hold') {
capturePayment($payment->getField('PS_INVOICE_ID'));
}
}
});
Сроки
| Задача | Срок |
|---|---|
| Установка и настройка готового модуля | 0.5–1 день |
| Кастомный обработчик с нуля | 2–4 дня |
| Двухстадийный эквайринг | +1–2 дня |
| Отладка webhook и тестирование | 0.5–1 день |







