EXPI: от оплаты к действующему доступу
Биллинг, подписки и сверка оплат с доступом. Как я связал платёжные события и жизненный цикл подписки, отвечая за архитектуру, код и эксплуатацию платформы.
Задача
В EXPI я был единственным инженером: отвечал за архитектуру, реализацию, инфраструктуру и выпуск изменений. Для биллинга недостаточно получить подтверждение оплаты. Первая покупка должна открыть доступ, повторная — продлить оплаченный период, а возврат и отказ от автопродления имеют разные последствия. Требовалось согласовать эти сценарии между платёжной системой, кабинетом и сервисами доступа, пока перенос старой PHP-системы ещё продолжался.
Технические подробности
Решение
Единый владелец состояния. Я сосредоточил изменение статуса и оплаченного периода подписки в отдельном модуле. Кабинет и административные инструменты обращались к его командам вместо самостоятельной записи статусов. Платёжное событие и изменение подписки сохранялись в одной транзакции. Повторное уведомление об уже учтённой оплате не должно было продлевать доступ повторно. Разные причины — разные переходы. Продление действующей подписки, поздняя оплата истёкшей подписки и возврат не сводились к одному переключателю «оплачено». Отказ от следующего списания сохранял доступ до конца оплаченного периода; отмена при возврате обрабатывалась отдельно. Так правила оставались явными и общими для разных точек входа. Проверка результата за пределами callback. Отдельная сверка выявляла расхождения между оплатой и доступом. Успешный HTTP-ответ платёжной системе сам по себе не доказывал, что доступ выдан. Для таких исключений сохранялся след для разбора, а опасные ветки обработки проверялись автоматическими тестами. Обнаружение расхождения не означало безусловную автоматическую выдачу доступа или возврат денег.
Результат
К завершению моей работы первая оплата, продление, обработка возврата и сверка оплат с доступом работали в системе автоматически. Биллинг связывал платёжные события с явными правилами подписки, а исключения оставались видимыми для разбора. Это был работающий участок платформы; перенос остального кабинета продолжался.