Уявіть: ви запускаєте SaaS, через місяць — 1000 користувачів, кожен з різним планом, частина на тріалі, частина скасовує. Без білінгової системи — хаос. Stripe Billing — готове рішення, яке покриває 95% сценаріїв: підписки, пробні періоди, апгрейди/даунгрейди, prorated billing, метеринг, автоматичний retry при невдачі. На відміну від самописної системи, Stripe Billing скорочує час розробки з 2–3 місяців до 1–2 тижнів — це в 5–10 разів швидше. І мінімізує помилки завдяки перевіреним алгоритмам. Економія на розробці — від $15 000, а на підтримці — $5 000 на рік. Ми інтегрували Stripe у 30+ проєктах, гарантуючи стабільну роботу білінгу під ключ. Наш досвід дозволяє передбачити та уникнути типових проблем: некоректна обробка trial, помилки prorating, збої у вебхуках.
Ключові сутності
Product → Price → Subscription → Invoice → PaymentIntent. Продукт — план (Basic, Pro, Enterprise). До нього прив'язуються ціни (місячна/річна). Підписка прив'язує customer до ціни. Invoice виставляється автоматично.
Як Stripe Billing вирішує проблему білінгу?
Stripe бере на себе всю рутину: створення інвойсів, спроби списання, prorating, trial. Вам потрібно лише налаштувати продукти та вебхуки для синхронізації статусів. Це скорочує час розробки з місяців до 1–2 тижнів.
Створення продуктів і цін
$product = \Stripe\Product::create([ 'name' => 'Pro Plan', 'metadata' => ['plan_id' => 'pro'], ]); $monthlyPrice = \Stripe\Price::create([ 'product' => $product->id, 'unit_amount' => 2900, 'currency' => 'usd', 'recurring' => ['interval' => 'month'], 'lookup_key' => 'pro_monthly', ]); $yearlyPrice = \Stripe\Price::create([ 'product' => $product->id, 'unit_amount' => 27900, 'currency' => 'usd', 'recurring' => ['interval' => 'year'], 'lookup_key' => 'pro_yearly', ]); Реєстрація користувача та створення підписки
Процес складається з чотирьох кроків: створення Stripe-клієнта, створення підписки з trial, передача client_secret на фронтенд, обробка вебхуків. Розглянемо кожен.
$stripeCustomer = \Stripe\Customer::create([ 'email' => $user->email, 'name' => $user->name, 'metadata' => ['user_id' => $user->id], ]); $subscription = \Stripe\Subscription::create([ 'customer' => $user->stripe_customer_id, 'items' => [['price' => 'pro_monthly']], 'trial_period_days' => 14, 'payment_behavior' => 'default_incomplete', 'payment_settings' => ['save_default_payment_method' => 'on_subscription'], 'expand' => ['latest_invoice.payment_intent'], ]); $clientSecret = $subscription->latest_invoice->payment_intent->client_secret; payment_behavior: default_incomplete — підписка активується лише після успішного першого платежу. Важливо для безкоштовних trial: картка прив'язується, але не списується.
Апгрейд/даунгрейд
public function changePlan(User $user, string $newPriceLookupKey): void { $prices = \Stripe\Price::all(['lookup_keys' => [$newPriceLookupKey]]); $newPrice = $prices->data[0]; $subscription = \Stripe\Subscription::retrieve($user->stripe_subscription_id); \Stripe\Subscription::update($subscription->id, [ 'items' => [[ 'id' => $subscription->items->data[0]->id, 'price' => $newPrice->id, ]], 'proration_behavior' => 'create_prorations', 'billing_cycle_anchor'=> 'unchanged', ]); } При апгрейді з proration Stripe автоматично кредитує невикористаний час і виставляє інвойс на різницю. Річна підписка — proration_behavior: none.
Чому варто використовувати Stripe Customer Portal?
Готовий UI для керування підпискою: зміна картки, скасування, історія інвойсів. Не потрібно писати з нуля. Достатньо створити сесію BillingPortal.Session і перенаправити користувача. Це економить до 40 годин розробки інтерфейсу.
Webhook: синхронізація статусів
Вся бізнес-логіка будується на вебхуках, а не на синхронних відповідях API. Основні події:
| Событие | Дія |
|---|---|
| customer.subscription.created | Зберегти subscription_id, активувати користувача |
| customer.subscription.updated | Оновити статус у БД |
| customer.subscription.deleted | Позначити як скасовану |
| invoice.payment_succeeded | Оновити дату next_payment |
| invoice.payment_failed | Повідомити користувача, не блокувати одразу |
| customer.subscription.trial_will_end | Нагадати про швидке списання |
Також важливо обробляти customer.subscription.paused та resumed, якщо підтримуєте паузу.
protected array $handlers = [ 'customer.subscription.created' => 'onSubscriptionCreated', 'customer.subscription.updated' => 'onSubscriptionUpdated', 'customer.subscription.deleted' => 'onSubscriptionCancelled', 'invoice.payment_succeeded' => 'onInvoicePaid', 'invoice.payment_failed' => 'onInvoicePaymentFailed', 'customer.subscription.trial_will_end'=> 'onTrialEndingSoon', ]; public function onInvoicePaymentFailed(array $event): void { $subscription = $event['data']['object']['subscription']; $user = User::where('stripe_subscription_id', $subscription)->firstOrFail(); $nextRetry = $event['data']['object']['next_payment_attempt']; Notification::send($user, new PaymentFailedNotification($nextRetry)); } Як обробляти невдалі платежі?
Stripe автоматично робить до 3 спроб списання з інтервалами 2, 3 та 5 днів. Ваше завдання — повідомляти користувача та оновлювати статус підписки на past_due. Після третьої невдачі підписка переходить у canceled. Щоб уникнути втрати клієнтів, реалізуйте сценарій: при першій невдачі — лист, при другій — push-повідомлення, при третій — блокування доступу з можливістю продовження.
Metered billing
Для оплати за споживання (API виклики, сховище):
$price = \Stripe\Price::create([ 'product' => $product->id, 'currency' => 'usd', 'recurring' => [ 'interval' => 'month', 'usage_type' => 'metered', 'aggregate_usage'=> 'sum', ], 'billing_scheme' => 'per_unit', 'unit_amount' => 1, ]); \Stripe\SubscriptionItem::createUsageRecord( $subscriptionItemId, ['quantity' => $apiCallsThisPeriod, 'action' => 'set'] ); action: set — абсолютне значення, increment — додати до поточного. set безпечніше при retry.
Порівняння моделей білінгу
| Параметр | Flat-rate | Per-unit | Tiered |
|---|---|---|---|
| Складність реалізації | Низька | Середня | Висока |
| Гнучкість для клієнта | Низька | Висока | Середня |
| Ризик помилок prorating | Мінімальний | Середній | Високий |
| Рекомендується для | Базові плани | API, сховище | Enterprise |
Чек-лист для безпечної інтеграції вебхуків
- Підтверджуйте подію за підписом (Webhook-Signature header).
- Ідемпотентність: використовуйте
idempotency_keyпри створенні підписок. - Логуйте всі вебхуки для налагодження.
- Додайте health-check endpoint для моніторингу.
- Тестуйте сценарії: успішний платіж, невдача, trial, апгрейд.
Що входить у роботу
- Налаштування продуктів і цін у Stripe Dashboard.
- Створення міграцій для синхронізації планів.
- Реалізація реєстрації та створення підписки з trial.
- Налаштування вебхуків та обробка ключових подій.
- Інтеграція Customer Portal.
- Документація по API та пост-релізна підтримка 1 місяць.
Як гарантувати 99.9% uptime білінгу?
Використовуйте failover-логіку: якщо Stripe API недоступний, кешуйте запити та повторюйте їх з експоненційною затримкою. Налаштуйте моніторинг вебхуків з оповіщенням у Telegram/Slack. Завжди обробляйте події invoice.payment_failed — це знижує churn на 20% при своєчасному повідомленні.
Зв'яжіться з нами для точної оцінки вашого проекту. Базова інтеграція — від 5 до 10 робочих днів. Складні сценарії (metered billing, кілька валют) — до 3 тижнів. Отримайте консультацію щодо інтеграції Stripe Billing — налаштуйте білінг під ваш SaaS без головного болю.







