advanced
Платежи и подписки
Моделирование checkout, billing state, жизненного цикла подписки, idempotency webhook, reconciliation, refunds, fraud checks и восстановления после сбоев.
Платежи и подписки — **распределённые workflow** между приложением, payment provider (Stripe, Adyen и др.) и внутренним entitlement state. Корректность — idempotent handlers, durable ledger-like state, верификация webhook, reconciliation и восстановление для пользователя — не redirect в браузере.
| Concern | Паттерн | |---------|---------| | Checkout | Session/intent с сервера; не доверять суммам с клиента | | Billing state | Явный автомат: trialing, active, past_due, canceled, paused | | Webhooks | Проверка подписи; idempotent processing по provider event ID | | Idempotency | Keys на create/charge API; dedupe table для доставки webhook | | Reconciliation | Ночные jobs: отчёты provider vs внутренний ledger | | Refunds & disputes | Audit trail; partial refunds; правила отзыва доступа | | Fraud | Velocity checks, 3DS где нужно, risk signals от provider |
Happy path: Checkout Session → webhook payment_intent.succeeded →
idempotent entitlement grant → email receipt
Retry: duplicate webhook → тот же event_id → без double grant
Не используйте success page как source of truth — вкладки закрывают, webhooks ретраят, сети падают. Храните provider customer/subscription ID и маппинг на user.
На интервью: продление подписки, webhook приходит дважды. Idempotency storage, детект drift, audit history для support без ручного DB.
Типовые ошибки: одна строка `subscriptions` без events; нет past_due; нет grace period; charge без SCA где regulated; секреты во frontend.
Компромисс — опора на примитивы provider против большего in-house billing (invoicing, tax, dunning).
Чеклист:
- Webhook handler idempotent; fast-ack + async queue при необходимости.
- Внутреннее state из event log.
- Alerts reconciliation при mismatch.
- Support tooling читает event history, не только raw tables.