Технологии
BillingMeld: почему покупку должен проверять сервер, а не приложение
BillingMeld становится центральным источником информации о покупках и подписках. Он проверяет операции через App Store и Google Play, отслеживает изменения их состояния, а подключённые сервисы работают только с подтверждённым статусом BillingMeld.
Покупка внутри мобильного приложения обычно выглядит простой только для пользователя. Он нажимает кнопку, подтверждает оплату, получает доступ к функции или подписке — и ожидает, что дальше всё будет работать автоматически.
Для разработчика за этой кнопкой начинается гораздо более сложный процесс. Нужно подтвердить саму покупку, учитывать продления, окончание подписки, возвраты, отзывы операций, смену устройства и различия между магазинами Apple и Google.
Главная проблема возникает, когда сервер начинает считать клиентское приложение источником истины.
Если приложение сообщило: «Покупка совершена», сервер открывает доступ и продолжает ориентироваться на однажды полученное состояние. Но жизненный цикл покупки на этом не заканчивается.
Подписка может быть продлена, автопродление может быть отключено, платёж может быть возвращён, а сама операция — отозвана магазином.
Именно поэтому в BillingMeld покупку подтверждает не приложение, а сервер.
Клиент сообщает, но не решает
В архитектуре BillingMeld мобильное приложение не является главным источником информации о покупке.
Клиент может передать данные о совершённой операции, но это только основание для проверки. Окончательное решение принимает серверная часть BillingMeld, которая проверяет информацию через инфраструктуру Apple или Google.
Это принципиальная разница.
Приложение на телефоне может работать со старым состоянием, не получить очередное изменение вовремя или передать данные, которые уже не соответствуют текущему состоянию покупки.
Кроме того, клиент не должен иметь возможности самостоятельно решить, что пользователю положен платный доступ.
BillingMeld проверяет, например:
действительно ли существует такая покупка;
относится ли она к нужному приложению и продукту;
действует ли оплаченный период сейчас;
произошло ли очередное продление;
отключено ли дальнейшее автопродление;
был ли оформлен возврат;
не была ли операция отозвана;
не закончился ли оплаченный период.
Таким образом, сообщение клиента становится не доказательством покупки, а поводом проверить её реальное состояние.
Единый источник истины для серверов
Подключённым сервисам не нужно самостоятельно реализовывать полный набор интеграций одновременно с Apple и Google.
Они обращаются к BillingMeld и получают уже нормализованное состояние покупки.
Например: доступ активен, оплаченный период закончился, очередное продление подтверждено, автопродление отключено или покупка отозвана.
Это позволяет чётко разделить ответственность.
Apple и Google являются источниками состояния самой магазинной операции. BillingMeld проверяет эти данные, приводит их к общей модели и сохраняет актуальное состояние. А конечный продукт принимает решение о доступе уже на основании статуса BillingMeld.
Для серверов продуктов это означает единый контракт вместо нескольких независимых интеграций.
Не нужно в каждом сервисе отдельно реализовывать правила App Store, отдельно — Google Play, а затем пытаться привести разные форматы, события и статусы к общей логике.
Почему клиенту нельзя доверять полностью
Клиентское приложение работает на устройстве пользователя.
Его можно закрыть, перезапустить, восстановить из резервной копии, обновить позже или запустить на другом устройстве. Оно может некоторое время работать со старой информацией или вообще не получить событие, которое произошло после первоначальной покупки.
Даже без какого-либо вмешательства пользователя это делает клиент плохим источником окончательного состояния подписки.
Например, пользователь оформил подписку и получил доступ. Позже для покупки был оформлен возврат или магазин отозвал операцию.
Если сервер знает только о первоначальном сообщении клиента, он продолжит считать покупку действующей.
В другой ситуации пользователь может отключить автопродление. При этом уже оплаченный период всё ещё должен оставаться активным до даты его окончания.
Если система оперирует только примитивным состоянием «подписка есть / подписки нет», она легко начнёт закрывать доступ слишком рано или, наоборот, оставлять его после того, как право на использование уже закончилось.
BillingMeld построен вокруг другой логики: клиент не подтверждает собственные права. Он сообщает о событии, а сервер определяет фактическое состояние покупки.
Покупка — это не одно событие
Одна из основных ошибок в биллинговой архитектуре — рассматривать покупку как единичное событие.
Фактически у неё есть жизненный цикл.
Сначала появляется операция. Затем она подтверждается магазином. Для подписки начинается оплаченный период. Позже может произойти очередное продление.
Пользователь может отключить автопродление, но продолжить пользоваться подпиской до окончания уже оплаченного периода.
Платёж может не пройти при следующем продлении.
Может быть оформлен возврат.
В отдельных случаях покупка может быть отозвана.
Поэтому одного факта «эта покупка когда-то существовала» недостаточно.
Серверу важно понимать, что с ней происходит сейчас.
Отзыв покупки не остаётся незамеченным
Особенно хорошо необходимость серверной архитектуры видна при возвратах и отзывах операций.
Первоначальная покупка могла быть совершенно корректной. Пользователь действительно оплатил продукт и получил доступ.
Но позже состояние операции изменилось.
Если BillingMeld получает информацию об изменении, он обновляет собственное состояние покупки и, при необходимости, дополнительно проверяет данные через магазин.
После этого подключённый сервис уже работает с новым статусом.
Таким образом, приложение не продолжает бесконечно доверять факту, что несколько недель или месяцев назад клиент однажды сообщил об успешной покупке.
Если магазин больше не считает соответствующее право действующим, BillingMeld отражает это в своём состоянии.
Отмена подписки и окончание доступа — не одно и то же
Здесь есть важное различие.
Если пользователь отключил автопродление подписки, это обычно не означает, что доступ должен закрыться немедленно.
Текущий оплаченный период может продолжать действовать.
В таком случае BillingMeld должен сохранить информацию о том, что дальнейшее продление отключено, но одновременно понимать дату окончания уже оплаченного периода.
И только после его завершения доступ перестаёт считаться активным, если нового подтверждённого продления не произошло.
Это один из примеров того, почему простого булевого значения subscription = true для нормального биллинга недостаточно.
Состояние подписки всегда связано со временем и событиями её жизненного цикла.
Продление — это тоже отдельная проверка
Подписка не заканчивается на первой оплате.
Сервер должен понимать, произошло ли очередное продление и действительно ли следующий оплаченный период подтверждён магазином.
BillingMeld отслеживает такие изменения и обновляет состояние подписки.
Если продление подтверждено, право на доступ продолжается.
Если очередное списание не произошло или магазин больше не подтверждает следующий период, система не должна просто продлевать доступ по собственному предположению.
Для пользователя это выглядит естественно: доступ существует столько, сколько реально действует оплаченная подписка.
Для разработчиков это означает, что одну и ту же логику продления не приходится повторно реализовывать в каждом приложении.
Как выглядит обычный сценарий
Пользователь оформляет подписку в мобильном приложении.
Клиент получает информацию о покупке и передаёт необходимые данные BillingMeld. Но само это сообщение ещё не является основанием считать покупку окончательно подтверждённой.
BillingMeld проверяет операцию через соответствующий магазин.
Если App Store или Google Play подтверждает покупку и её состояние соответствует правилам продукта, BillingMeld фиксирует активное право.
После этого подключённый сервис предоставляет пользователю оплаченные возможности.
Дальше состояние продолжает жить уже независимо от первоначального сообщения клиента.
Если подписка продлевается, BillingMeld учитывает новый оплаченный период.
Если пользователь отключает автопродление, текущий период продолжает действовать до своего окончания.
Если происходит возврат или отзыв операции, состояние снова изменяется.
В этой схеме приложение не хранит собственную отдельную «истину» о покупке. Оно работает с состоянием, которое подтверждено и сохранено BillingMeld.
Что происходит при смене устройства
Серверная модель особенно полезна, когда пользователь меняет телефон или устанавливает приложение повторно.
Право на покупку не должно существовать только потому, что конкретный экземпляр приложения когда-то видел успешную транзакцию.
И наоборот, переустановка приложения не должна уничтожать подтверждённое право пользователя.
Если состояние покупки находится на серверной стороне и связано с подтверждённой магазинной операцией, новое устройство может получить актуальное состояние через сервер.
Это ещё одна причина не хранить логику доступа исключительно внутри мобильного клиента.
Что это даёт разработчикам
Для команды, которая выпускает несколько мобильных приложений или работает одновременно с iOS и Android, биллинг довольно быстро превращается в отдельную инфраструктурную задачу.
Нужно учитывать:
разные форматы данных Apple и Google;
подтверждение первоначальной покупки;
продления подписок;
окончание оплаченного периода;
отключение автопродления;
возвраты;
отзыв операций;
повторную установку приложения;
смену устройства;
восстановление покупок;
изменение состояния, произошедшее без участия клиента.
BillingMeld выносит эту логику в отдельный специализированный слой.
Серверы продуктов работают с ним по единому контракту и не должны самостоятельно трактовать все особенности каждого магазина.
Это уменьшает количество дублирующего кода и, что ещё важнее, снижает вероятность того, что разные приложения одной компании будут по-разному понимать один и тот же платёжный сценарий.
Главным становится не чек, а актуальное право
Меня в этой архитектуре больше всего заинтересовал переход от проверки отдельной покупки к контролю актуального состояния.
Исторический факт оплаты сам по себе ещё не отвечает на главный вопрос продукта:
имеет ли пользователь право на платную функцию сейчас?
У операции может быть успешная первоначальная покупка, но законченный период.
У подписки может быть отключено автопродление, но всё ещё действовать уже оплаченный срок.
Может существовать подтверждённое продление.
Может быть выполнен возврат.
Магазин может отозвать операцию.
Поэтому главным объектом становится не чек и не первоначальный ответ клиента, а актуальное право пользователя, рассчитанное на основании подтверждённого состояния покупки.
Именно это состояние BillingMeld передаёт остальным сервисам.
BillingMeld как граница между магазинами и продуктами
В результате появляется довольно чёткая архитектурная граница.
С одной стороны находятся App Store и Google Play со своими форматами, событиями, правилами и жизненными циклами покупок.
С другой — приложения и внутренние сервисы, которым в большинстве случаев нужен гораздо более простой ответ: какие права есть у пользователя сейчас.
Между ними находится BillingMeld.
Он принимает магазинные данные, проверяет их, приводит к собственной модели и предоставляет остальной инфраструктуре уже нормализованный результат.
За счёт этого продуктам не нужно знать все внутренние особенности каждой платёжной платформы.
Почему это важно для пользователя
Для пользователя правильная биллинговая архитектура в идеале вообще должна оставаться незаметной.
Если покупка подтверждена и оплаченный период действует, доступ должен работать.
Если пользователь отключил дальнейшее продление, уже оплаченный срок не должен исчезнуть раньше времени.
Если произошло новое успешное продление, доступ должен продолжиться.
Если магазин подтвердил возврат или отзыв, система должна корректно отразить изменение права.
При смене устройства или повторной установке приложения человеку не должно приходиться вручную доказывать каждой части инфраструктуры, что покупка действительно существует.
В итоге правило получается достаточно простым:
клиент сообщает о покупке, магазин является внешним источником её состояния, BillingMeld проверяет и нормализует это состояние, а остальные сервисы принимают решение уже на основании подтверждённых данных BillingMeld.
Именно поэтому BillingMeld — это не просто ещё один модуль оплаты.
Это серверный слой доверия между мобильным приложением, магазинами Apple и Google и продуктами, которым необходимо точно понимать, какие платные права принадлежат пользователю в данный момент.
Подробнее о проекте: billingmeld.de.