Автоматичні списання за підписками роблять дохід від підписок стабільним. Але до 30% рекурентних платежів відхиляються: картки прострочені, не вистачає коштів, банк блокує операцію. Без автоматичної обробки відмов ви втрачаєте до 15% виручки від підписок. При щомісячному обороті це відчутні втрати. Інтеграція рекурентних платежів з токенізацією та dunning стратегією повертає до 80% невдалих списань. Ми реалізували такі системи для Stripe та CloudPayments у проєктах із тисячами підписників. Досвід — 10+ років в обробці платежів та понад 50 проєктів з підписками. Отримайте консультацію з інтеграції вже сьогодні.
Як реалізувати інтеграцію рекурентних платежів за допомогою токенізації?
Токенізація — збереження платіжних даних у вигляді токена у шлюзу. Перший платіж проходить за участю користувача, наступні ініціює сервер. Stripe використовує SetupIntent для безпечного збору картки, потім PaymentIntent з параметром off_session: true для списання без 3DS. Це стандартний підхід у документації Stripe.
Сервер — збереження методу оплати
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$stripeCustomer = \Stripe\Customer::create([
'email' => $user->email,
'metadata' => ['user_id' => $user->id],
]);
$user->update(['stripe_customer_id' => $stripeCustomer->id]);
$setupIntent = \Stripe\SetupIntent::create([
'customer' => $user->stripe_customer_id,
'usage' => 'off_session',
'automatic_payment_methods' => ['enabled' => true],
]);
return response()->json(['clientSecret' => $setupIntent->client_secret]);
Сервер — наступне списання без участі користувача
public function chargeRecurring(User $user, int $amountCents): void
{
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$paymentMethod = $user->default_payment_method_id;
try {
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => $amountCents,
'currency' => 'usd',
'customer' => $user->stripe_customer_id,
'payment_method' => $paymentMethod,
'confirm' => true,
'off_session' => true,
'description' => "Subscription - {$user->id}",
]);
if ($paymentIntent->status === 'succeeded') {
$this->recordSuccessfulCharge($user, $paymentIntent);
}
} catch (\Stripe\Exception\CardException $e) {
$this->handleFailedCharge($user, $e->getError()->decline_code);
} catch (\Stripe\Exception\InvalidRequestException $e) {
if ($e->getStripeCode() === 'authentication_required') {
$this->sendAuthenticationEmail($user, $e->getError()->payment_intent->id);
}
}
}
Чому до 30% платежів відхиляються?
Основні причини: минув термін дії картки, недостатньо коштів, банківський фрод-моніторинг, технічні збої. При ручній обробці кожна відмова — втрачений дохід. Автоматична стратегія повторів (dunning) дозволяє повернути більшу частину цих платежів. Наприклад, у нас на проєктах з хмарним сервісом після впровадження dunning відмова знизилася з 25% до 8%.
Обробка невдалих списань
Невдачі — норма для рекурентних платежів. Застосовуємо dunning з експоненційною затримкою: перша спроба через 1 день, друга через 3 дні, третя через 7 днів. Якщо після трьох спроб списання не проходить, підписка переводиться в статус past_due, клієнт отримує листа з проханням оновити картку. Додатково запускається dunning-процес — серія з 3-5 нагадувань. Ось приклад класу для обробки:
class RecurringChargeJob implements ShouldQueue
{
public int $tries = 3;
public function backoff(): array
{
return [86400, 259200, 604800];
}
public function handle(): void
{
$subscription = Subscription::find($this->subscriptionId);
if ($subscription->failed_attempts >= 3) {
$subscription->update(['status' => 'past_due']);
Mail::to($subscription->user)->send(new PaymentFailedMail($subscription));
return;
}
try {
app(RecurringPaymentService::class)->charge($subscription);
$subscription->update([
'failed_attempts' => 0,
'status' => 'active',
'next_charge_at' => now()->addMonth(),
]);
} catch (PaymentFailedException $e) {
$subscription->increment('failed_attempts');
throw $e;
}
}
}
Stripe Billing — готове рішення
Якщо керувати розкладом самостійно не хочеться, Stripe Billing робить це за вас. Просто створіть продукт і ціну, потім підписку. Webhook обробить всі події: успішні платежі, збої, продовження. Stripe Billing реалізується в 2 рази швидше, ніж власна токенізація, і знижує навантаження на сервер.
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$product = \Stripe\Product::create(['name' => 'Pro Plan']);
$price = \Stripe\Price::create([
'unit_amount' => 2900,
'currency' => 'usd',
'recurring' => ['interval' => 'month'],
'product' => $product->id,
]);
$subscription = \Stripe\Subscription::create([
'customer' => $user->stripe_customer_id,
'items' => [['price' => $price->id]],
'payment_behavior' => 'default_incomplete',
'expand' => ['latest_invoice.payment_intent'],
]);
Webhook-обробник повинен слухати події invoice.payment_succeeded, invoice.payment_failed, customer.subscription.updated. Кожна подія оновлює статус підписки в локальній БД. Важно ідемпотентно обробляти повторні сповіщення — перевіряти за Stripe Event ID. Для тестування використовуйте Stripe CLI з командою stripe listen --forward-to localhost/webhook.
Який підхід обрати: токенізація чи Subscription API?
Вибір між токенізацією та Subscription API визначає рівень контролю та швидкість розробки. Токенізація дає повний контроль над розкладом і даними, але потребує більше коду та тестування. Subscription API спрощує управління підписками за рахунок шлюзу, але прив'язує до нього та обмежує гнучкість.
Порівняння токенізації та Subscription API
| Критерій | Токенізація | Subscription API |
|---|---|---|
| Контроль | повний | частковий |
| Надійність | нижча (вище навантаження) | вища (шлюз керує) |
| Прив'язка до шлюзу | слабка (можна мігрувати) | жорстка |
| Складність реалізації | середня | низька |
| Час розробки | 3-6 тижнів | 1-3 тижні |
Отримайте консультацію з вибору підходу для вашого бізнесу.
Що входить в роботу
- Документація: API-специфікація інтеграції, опис webhook-подій, схема бази даних підписок.
- Доступи: налаштування середовищ (dev/staging/prod), створення акаунтів шлюзів, налаштування webhook-секретів.
- Навчання: передача знань команді, демонстрація адмін-панелі управління підписками.
- Підтримка: гарантійне обслуговування 1 місяць після здачі, виправлення багів по hotfix.
Процес роботи
- Аналітика — вивчаємо вашу бізнес-логіку, частоту списань, вимоги до dunning.
- Проектування — обираємо стек (Stripe, CloudPayments), модель токенізації або Subscription API.
- Реалізація — інтеграція платіжного шлюзу, створення таблиці підписок, webhook-обробники, джоби.
- Тестування — перевірка оплати, відмов, grace-періодів, повторних спроб.
- Деплой та моніторинг — налаштування алертів, логування помилок, оновлення документації.
Зв'яжіться з нами для обговорення деталей вашого проєкту.
Терміни та вартість
| Варіант | Термін розробки |
|---|---|
| Токенізація | 3–6 тижнів |
| Stripe Billing | 1–3 тижні |
Базова інтеграція з одним шлюзом — від 3 до 6 тижнів. Якщо потрібні складні білінг-цикли, кілька шлюзів або нестандартні стратегії повторів — термін збільшується до 8–10 тижнів. Вартість розраховується індивідуально.
Замовте інтеграцію рекурентних платежів під ключ — ми гарантуємо надійність та прозорість на всіх етапах.







