Реалізація підписки на торговельні сигнали в мобільному додатку
Торговельні сигнали — це час, критичний момент. Користувач сплатив за підписку, але отримав push-сповіщення про сигнал через 40 секунд після його генерації. До цього часу ціна вже змінилась. Вся технічна задача здесь — мінімізувати затримку від генерації сигналу на сервері до відображення на екрані.
Архітектура доставки сигналів
FCM / APNS для доставки сигналів поодинці — ненадійне рішення. Apple і Google не гарантують latency push-сповіщень: під час навантаження затримка може досягати 1–5 хвилин. Правильна схема — два канали паралельно:
WebSocket (основний). Поки додаток активний (foreground) — підключений до сервера через WebSocket (URLSessionWebSocketTask на iOS, OkHttp WebSocket на Android). Сигнал надходить протягом 100–500 мс від генерації. При розриві з'єднання — exponential backoff reconnect (1s → 2s → 4s → 8s → max 30s).
Push (резервний). Коли додаток у фоні або закритий — FCM/APNS Data Message (silent push на iOS) пробуджує додаток через BGProcessingTask або UNNotificationServiceExtension. NSE запускається для кожного push й може показати сповіщення з розшифрованим вмістом — додайте тикер, напрямок (BUY/SELL), ціну входу.
Важливий нюанс iOS: UNNotificationServiceExtension має ~30 секунд на обробку. Якщо за цей час не викликається contentHandler — система показує оригінальний push. NSE не повинен виконувати важкі мережеві запити.
Підписка і доступ до сигналів
Модель: платний доступ через Auto-Renewable Subscription (StoreKit 2 / Play Billing Library 6+). Користувачі без активної підписки бачать сигнали з затримкою (демо-режим) або не бачать їх взагалі.
Валідація entitlement на сервері через App Store Server Notifications V2 (APNS-підписані JWT-события від Apple) і Google Play Real-time Developer Notifications (Pub/Sub). Не покладайтеся на клієнтське валідування — сервер WebSocket при встановленні з'єднання перевіряє subscription_status із своєї БД, оновлюється через webhook'и від магазинів.
Grace period: якщо підписка не поновилась через біллінг — не рубіть доступ миттєво. StoreKit 2 Transaction.currentEntitlements повертає трансакцію зі статусом inGracePeriod — покажіть banner «Проблема з оплатою, оновіть картку» і дайте 3–6 днів. Це знижує involuntary churn.
UI: Стрічка сигналів у реальному часі
Стрічка сигналів — UICollectionView з DiffableDataSource (iOS) або LazyColumn (Compose, Android). Новий сигнал вставляється на початок списку з анімацією без перерисування всього списку. Для сигналів з цінових даних — форматування через NumberFormatter з локаллю користувача (різні ринки — різні формати цін).
Кожен сигнал: тикер, тип (BUY/SELL/CLOSE), ціна входу, stop-loss, take-profit, часова мітка (UTC → локальна timezone через TimeZone.current). Кольори — зелений/червоний — не тільки кольором, але й іконкою (доступність: користувачі з дальтонізмом).
Архів сигналів з фільтрацією — пагінація через cursor (cursor-based pagination, не offset), нескінченний скрол через Paging 3 (Android) або власний PaginatedRepository (iOS).
Процес
Проектування схеми підписок (тарифи, trial) → розробка WebSocket + Push delivery → реалізація StoreKit 2 / Play Billing підписки → серверна валідація entitlements → UI стрічки сигналів → тестування latency доставки → публікація.
Орієнтири за часом
Реалізація підписки + WebSocket стрічка сигналів + push fallback — 3–5 робочих днів при готовому API. Якщо включає проектування серверної частини (WebSocket сервер, Pub/Sub інтеграція з магазинів) — 2–3 тижні.







