Налаштування рекурентних платежів на 1С-Бітрікс
Рекурентний платіж — автоматичне списання з картки покупця без його повторної участі. Картка прив'язується один раз, далі магазин ініціює списання самостійно. Застосовується для: автоматичного продовження підписок, регулярних доставок, оплати за графіком. Технічно це не стандартний функціонал модуля sale 1С-Бітрікс — потребує додаткової реалізації.
Як це працює технічно
Рекурентні платежі спираються на токенізацію картки. При першій оплаті:
- Покупець вводить картку, платіжна система проводить транзакцію
- Система повертає токен картки (RebillId, RecurringId — у кожного еквайрингу свій термін)
- Магазин зберігає токен, прив'язавши його до покупця
- Для наступних списань магазин надсилає запит з токеном — картку повторно вводити не потрібно
Збереження токена картки (ЮКаса)
// При першому платежі запитуємо збереження картки
$payment = $yookassaClient->createPayment([
'amount' => ['value' => $amount, 'currency' => 'RUB'],
'payment_method_data' => ['type' => 'bank_card'],
'confirmation' => ['type' => 'redirect', 'return_url' => $returnUrl],
'save_payment_method' => true, // ключовий параметр
'capture' => true,
'description' => 'Перший платіж, прив\'язка картки',
], uniqid('', true));
// Після успішної оплати в callback:
$completedPayment = $yookassaClient->getPaymentInfo($paymentId);
$paymentMethodId = $completedPayment->getPaymentMethod()->getId();
// Зберігаємо $paymentMethodId у профілі покупця
UserCardTable::add([
'USER_ID' => $userId,
'PAYMENT_METHOD_ID'=> $paymentMethodId,
'LAST4' => $completedPayment->getPaymentMethod()->getLast4(),
'CARD_TYPE' => $completedPayment->getPaymentMethod()->getCardType(),
'ACTIVE' => 'Y',
]);
Повторне списання за токеном
public function chargeRecurrent(int $userId, float $amount, string $description): bool
{
$card = UserCardTable::getActiveCard($userId);
if (!$card) {
return false;
}
try {
$payment = $yookassaClient->createPayment([
'amount' => ['value' => number_format($amount, 2, '.', ''), 'currency' => 'RUB'],
'payment_method_id' => $card['PAYMENT_METHOD_ID'], // токен збереженої картки
'capture' => true,
'description' => $description,
], uniqid('', true));
// Рекурентні платежі одразу в статусі succeeded або pending
if ($payment->getStatus() === 'succeeded') {
return true;
}
// Обробимо через webhook
return false;
} catch (\Exception $e) {
// Логуємо, повідомляємо користувача
return false;
}
}
Планувальник завдань 1С-Бітрікс
Для регулярних списань використовуємо агентів 1С-Бітрікс:
// Реєстрація агента при оформленні підписки
\CAgent::AddAgent(
'\MyModule\RecurringAgent::run(' . $subscriptionId . ');',
'my_module',
'N',
86400, // інтервал у секундах (1 день)
date('d.m.Y H:i:s', strtotime('+1 month')), // дата першого запуску
'Y',
date('d.m.Y H:i:s', strtotime('+1 month'))
);
// Клас агента
class RecurringAgent
{
public static function run(int $subscriptionId): string
{
$subscription = SubscriptionTable::getById($subscriptionId)->fetch();
if (!$subscription || $subscription['STATUS'] !== 'ACTIVE') {
return ''; // порожній рядок = видалити агента
}
$charged = (new RecurringPaymentService())->chargeRecurrent(
$subscription['USER_ID'],
$subscription['AMOUNT'],
'Продовження підписки №' . $subscriptionId
);
if (!$charged) {
// Позначити підписку як проблемну, повідомити
}
// Повертаємо назву методу для наступного запуску
return '\MyModule\RecurringAgent::run(' . $subscriptionId . ');';
}
}
Обробка помилок списання
Картка може бути заблокована, ліміт перевищено, коштів недостатньо. Стандартна стратегія retry:
- День 0: перша спроба — невдача
- День 1: повторна спроба
- День 3: повторна спроба + email покупцю
- День 7: фінальна спроба + повідомлення про скасування підписки
Терміни
| Завдання | Термін |
|---|---|
| Збереження токена картки при першому платежі | 1 день |
| Механізм повторних списань + агенти | 1–2 дні |
| Обробка помилок та повідомлення | 1 день |







