Технології
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.