Настройка рекуррентных платежей на 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С-Битрикс

Рекуррентный платёж — автоматическое списание по сохранённым платёжным данным без участия покупателя. Ключевой нюанс, который часто упускают при проектировании: данные карты (номер, CVV) никогда не хранятся на сервере магазина. Магазин хранит только токен — непрозрачный идентификатор, выданный банком. При следующих списаниях передаётся только он.

Механизм токенизации

При первой оплате покупатель вводит карту на форме банка. Если в запросе передан флаг рекурренции, банк возвращает rebill_id (или payment_method_id — называния у разных эквайеров разные). Этот ID привязан к карте внутри банковской системы. Магазин хранит его в базе.

Поддержка по эквайерам

Эквайер Флаг первого платежа Метод повторного списания
Тинькофф Recurrent: 'Y' POST /v2/Charge + RebillId
ЮКасса save_payment_method: true POST /payments + payment_method_id
CloudPayments createToken: true POST /payments/tokens/charge
Сбербанк clientId в Init paymentOrderBinding.do

Первый платёж: инициализация токена (Тинькофф)

$params = [
    'TerminalKey' => TINKOFF_TERMINAL,
    'Amount'      => (int)($order->getPrice() * 100),
    'OrderId'     => $order->getAccountNumber(),
    'Description' => 'Подписка — первый платёж',
    'Recurrent'   => 'Y',             // ← флаг токенизации
    'CustomerKey' => (string)$userId,  // уникальный ключ покупателя
    'NotificationURL' => 'https://shop.ru/bitrix/tools/sale_ps_result.php',
];
$params['Token'] = tinkoffSign($params, TINKOFF_SECRET);

$response = tinkoffPost('/v2/Init', $params);
// Редирект на $response['PaymentURL']

В webhook после успешной оплаты придёт RebillId:

$data = json_decode(file_get_contents('php://input'), true);

if ($data['Status'] === 'CONFIRMED' && !empty($data['RebillId'])) {
    // Сохраняем rebill_id для будущих списаний
    $db->query("INSERT INTO b_user_payment_tokens
        (user_id, paysystem, rebill_id, card_mask, card_type)
        VALUES (?, 'tinkoff', ?, ?, ?)",
        [$data['CustomerKey'], $data['RebillId'], $data['Pan'] ?? '', $data['CardType'] ?? '']
    );
}

Повторное списание без участия покупателя

function chargeRecurring(string $customerKey, int $amountKopecks, string $newOrderId): bool
{
    $rebillId = getRebillId($customerKey, 'tinkoff');

    // Шаг 1: инициализируем новый платёж
    $init = tinkoffPost('/v2/Init', [
        'TerminalKey' => TINKOFF_TERMINAL,
        'Amount'      => $amountKopecks,
        'OrderId'     => $newOrderId,
        'CustomerKey' => $customerKey,
        'Recurrent'   => 'Y',
        'Token'       => tinkoffSign([...], TINKOFF_SECRET),
    ]);

    // Шаг 2: списываем по RebillId
    $charge = tinkoffPost('/v2/Charge', [
        'TerminalKey' => TINKOFF_TERMINAL,
        'PaymentId'   => $init['PaymentId'],
        'RebillId'    => $rebillId,
        'Token'       => tinkoffSign([...], TINKOFF_SECRET),
    ]);

    return $charge['Success'] ?? false;
}

Хранение токенов

CREATE TABLE b_user_payment_tokens (
    id          SERIAL PRIMARY KEY,
    user_id     INT          NOT NULL,
    paysystem   VARCHAR(32)  NOT NULL,
    rebill_id   VARCHAR(128) NOT NULL,
    card_mask   VARCHAR(20),
    card_type   VARCHAR(10),
    created_at  TIMESTAMP    DEFAULT NOW(),
    is_active   BOOLEAN      DEFAULT TRUE
);

Retry-логика при отказе карты

foreach (getFailedCharges() as $sub) {
    // Повторяем через 1, 3, 7 дней
    $delays = [1, 3, 7];
    $delay  = $delays[$sub['retry_count']] ?? 7;

    if (daysSinceLastAttempt($sub) < $delay) continue;

    if ($sub['retry_count'] >= 3) {
        suspendSubscription($sub['id']);
        sendSuspendedEmail($sub['user_id']);
        continue;
    }

    $success = chargeRecurring($sub['customer_key'], $sub['amount'], generateOrderId());
    updateRetryCount($sub['id'], $success);
}

Сроки

Задача Срок
Первый платёж с токенизацией 1 день
Автосписание + хранение токенов 1–2 дня
Retry-логика и уведомления 0.5–1 день
ЛК управления картами 1–2 дня