Інтеграція API Binance в мобільний криптододаток
Помилка -1021 при підписі — типовий головний біль при інтеграції Binance API в мобільний додаток. Клієнт скаржиться, що ордери не проходять, а в логах Timestamp for this request is outside of the recvWindow. Наш досвід показує: проблема найчастіше в розсинхронізації часу на бюджетних Android-пристроях. Ми вирішуємо це синхронізацією з /api/v3/time та кастомним менеджером підписів, що гарантує стабільну роботу навіть при агресивному поллінгу.
REST + WebSocket — не взаємозамінні. Binance надає обидва транспорти, і більшість помилок при інтеграції виникають саме через те, що команда намагається підписатися на ринкові дані через REST замість WebSocket Streams, або навпаки — намагається виставити ордер через wss://stream.binance.com:9443. Розберемо обидва сценарії чесно.
Чому REST і WebSocket не можна використовувати як взаємозамінні?
REST API обмежений за частотою — кожен ендпоінт має вагу (weight). Наприклад, /api/v3/depth?limit=1000 коштує 50 одиниць, а хвилинний ліміт — 6000. Мобільний додаток з поллінгом стаканів на 5 пар вилітає в бан за 30 секунд. WebSocket Streams не мають таких лімітів: підписка на btcusdt@depth1000 дає постійний потік даних без обмежень.
Порівняння транспортів
| Характеристика | REST API | WebSocket Streams |
|---|---|---|
| Тип запиту | Запит-відповідь | Постійний потік |
| Аутентифікація | HMAC-SHA256 | ListenKey (приватні потоки) |
| Затримка | ~100-500 мс | ~1-10 мс (у 10-50 разів менше) |
| Навантаження | Вагові ліміти (6000/хв) | Необмежено |
| Типове використання | Ордери, баланс, історія | Ринкові дані, угоди |
WebSocket краще REST в 10-50 разів за затримкою, що критично для мобільної торгівлі.
REST API: ліміти, підпис і типові краші на мобілці
Binance REST API версії 3 (/api/v3/) використовує HMAC-SHA256 для підпису приватних ендпоінтів. Підпис формується з рядка queryString + body, до якої додається timestamp і необов'язковий recvWindow. Типова помилка — {"code":-1021,"msg":"Timestamp for this request is outside of the recvWindow."} — виникає не через кривий підпис, а тому що системний годинник на Android-пристрої від'їхав від серверного часу на 2–3 секунди. На iOS це рідкість (менше 1% випадків), на Android бюджетних пристроях — до 30%.
Правильне рішення: не хардкодити recvWindow=5000, а синхронізувати локальний час з /api/v3/time при кожному холодному старті додатку та зберігати serverTimeOffset в пам'яті.
Ліміти вагові, а не запитні. Кожен ендпоінт має weight — /api/v3/depth?limit=1000 коштує 50 одиниць, тоді як /api/v3/ticker/price — 1. Хвилинний ліміт — 6000 одиниць. Мобільний додаток з агресивним поллінгом стаканів на 5 пар вилітає в бан (HTTP 429) за 30 секунд. Потрібен WeightBudget-менеджер: черга запитів з пріоритетами, дебаунс на ручне оновлення та миттєвий перехід на WebSocket при перевищенні 80% квоти.
WebSocket Streams: життєвий цикл з'єднання на мобілці
wss://stream.binance.com:9443/ws/<streamName> — окремий хост, без авторизації для публічних потоків. Для приватних (ордери, баланс) потрібен listenKey, який отримують через POST /api/v3/userDataStream і продовжують кожні 30 хвилин через PUT /api/v3/userDataStream.
Проблема мобіля: фоновий режим. На iOS додаток іде в background, сокет закривається з кодом 1001 (going away). При поверненні в foreground потрібно:
- Перевірити, чи закінчився
listenKey(TTL — 60 хвилин з моменту останньогоPUT). - Якщо закінчився — отримати новий, перепідписатися.
- Відновити всі публічні стрими заново.
На Android ситуація інша: агресивний Doze Mode обриває TCP-сокет раніше, ніж WebSocket встигає прислати ping. Бібліотека OkHttp з pingInterval(20, TimeUnit.SECONDS) справляється, але тільки якщо WakeLock тримається на рівні WorkManager.
Для Flutter використовуємо web_socket_channel з кастомним ReconnectingWebSocketChannel — wrapper з exponential backoff (старт 1 с, максимум 30 с) і журналом пропущених подій для reconciliation при перепідключенні.
Як правильно підписувати ордери на мобільному пристрої?
Критична деталь: параметри в query string та в body вважаються разом. Якщо POST /api/v3/order відправляється з тілом symbol=BTCUSDT&side=BUY&...×tamp=..., то підпис формується з цього рядка цілком — без знака ?. Типова помилка — підписувати тільки body або тільки query, отримувати {"code":-1022,"msg":"Signature for this request is not valid."} і шукати баг в алгоритмі хешування.
Як зазначено в документації Binance API, підпис чутливий до регістру та повинен бути закодований HMAC-SHA256. Ще нюанс: порядок параметрів важливий тільки для підпису, але не для виконання — Binance приймає їх у будь-якому порядку, але HMAC чутливий до порядку конкатенації.
Як будуємо інтеграцію: архітектура та перевірений стек
Наш досвід включає 5+ років роботи з мобільними криптододатками. Ми виконали інтеграції для 20+ проектів, скоротивши час налагодження підписів на 30% за допомогою кастомного інтерцептора.
Архітектура: Clean Architecture з окремим BinanceDataSource (network layer), TradeRepository (бізнес-логіка) та ViewModel-шаром для UI.
Для REST: Retrofit 2 + OkHttpClient з інтерцептором підпису та інтерцептором синхронізації часу. Перехоплюємо 429 та 418 (IP-бан) — при 418 показуємо користувачеві таймер до розбану (заголовок Retry-After).
Для WebSocket: окремий BinanceStreamManager — Singleton в DI-контейнері (Hilt), керує пулом стримів, дедуплікує підписки (якщо два екрани хочуть btcusdt@trade — один сокет, два observer'и через SharedFlow).
Тестування: Binance Testnet (testnet.binance.vision) з окремим ключем. MockWebServer в unit-тестах для перевірки підпису без мережі.
Що входить в інтеграцію
- Архітектурна документація та схема потоків даних
- Вихідний код з коментарями та прикладами підпису
- Доступ до тестового середовища (Testnet)
- Навчання команди з підтримки та усунення несправностей
- Гарантія стабільної роботи протягом 3 місяців
Оцінка та терміни
Базова інтеграція (маркет-дані + один тип торгівлі) — від $2000 до $4000, тривалість від 2 до 4 тижнів. Повний торговий термінал з кількома типами ордерів, стаканом, історією та аналітикою — від $6000 до $12000, від 6 до 12 тижнів залежно від платформи (нативна iOS/Android vs Flutter). Вартість розраховується індивідуально, але ми гарантуємо економію до $1000 порівняно з середньоринковими цінами завдяки оптимізації архітектури.
Покрокова інструкція з інтеграції API Binance
-
Налаштуйте синхронізацію часу: отримайте серверний час через
GET /api/v3/timeта зберігайте зміщення. -
Створіть підпис HMAC-SHA256: використовуйте бібліотеку (наприклад,
javax.crypto.Macна Android абоCryptoSwiftна iOS). - Встановіть з'єднання WebSocket: для публічних даних підпишіться на streams, для приватних — отримайте listenKey.
- Реалізуйте обробку лімітів: додайте WeightBudget-менеджер для REST та автовідновлення при 429 помилках.
- Протестуйте на Testnet: перевірте всі сценарії (ордери, скасування, помилки) без реальних коштів.
Дотримання цих кроків дозволяє уникнути 90% типових помилок при інтеграції Binance API в мобільний додаток. Для уточнення деталей отримайте консультацію — ми допоможемо вибрати оптимальний стек та уникнути типових помилок.







