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.