Подписка ломается не на оплате, а на переходах между статусами
Жизненный цикл подписки нельзя строить как набор «активна/неактивна». Нужны явные состояния: trial, promo, active, past_due, paused, canceled, expired. Между ними должны быть допустимые переходы с проверкой идемпотентности: повторный webhook не должен продлевать доступ второй раз и не должен откатывать уже закрытую подписку.
Триал и промо-период — отдельные механики, а не скидка в карточке тарифа. У них должны быть свои правила входа, ограничения на повторный старт, дата окончания и источник истины для биллинга. Если trial заканчивается в момент неуспешного списания, система обязана сначала зафиксировать статус, затем запустить dunning, и только потом ограничивать доступ — иначе получите спорные отписки и revenue leakage.
Апгрейды и даунгрейды лучше проводить через proration-модель с явным расчетом остатка. Нельзя смешивать изменение тарифа и изменение периода в одной транзакции без компенсационного сценария. Иначе при сетевом сплите шлюза вы увидите «успешный» апгрейд в CRM и старый тариф в биллинге. Держите отдельный ledger для начислений, кредит-нотов и возвратов.
Еще один обязательный слой — reconciliation. Сверяйте события от платежного провайдера, внутренний state machine и фактический доступ к продукту. Если одно из трех расходится, система должна поднимать инцидент, а не молча ждать следующего платежа.
Идемпотентность в биллинге — это не рекомендация, а базовый вопрос выживания системы.
Подписки: биллинг-лаб
@subscriptions_billing_lab_arb
Подписка ломается не на оплате, а на переходах между статусами
Этот пост опубликован в Telegram-канале Подписки: биллинг-лаб. Подписаться можно по ссылке: @subscriptions_billing_lab_arb.