Мы часто слышим от клиентов: "Хотим принимать крипту как обычный Stripe, только без посредников". Сначала кажется, что достаточно подключить Blockchain listener и генерировать адреса. Но на практике всплывают проблемы: детекция платежей без постоянного polling, волатильность при конвертации, partial payments, confirmations thresholds в разных сетях, идемпотентность при сбоях. Мы решаем волатильность фиксацией курса через Chainlink Price Feed. Мы разобрали каждый из этих вопросов в продакшене и предлагаем готовое архитектурное решение под ключ. Наша команда имеет более 5 лет опыта в блокчейн-разработке и реализовала более 20 интеграций платежных шлюзов. Экономия на комиссиях за счёт отсутствия посредников может достигать 2% от оборота — это существенный фактор при высоких объёмах. Закажите консультацию, чтобы оценить проект.
Как устроен шлюз приёма криптоплатежей
Минимально жизнеспособный payment gateway состоит из четырёх компонентов:
[Клиент] → [API Gateway] → [Payment Service] ↓ [Blockchain Listener] ↓ [Event Queue (Redis/Kafka)] ↓ [Settlement Service] → [ERP/CRM] Payment Service — создаёт заказ, генерирует уникальный адрес (или payment ID), возвращает клиенту данные для оплаты. Stateful — хранит mapping address → order. Blockchain Listener — мониторит входящие транзакции. Это самый критичный компонент с точки зрения надёжности. Два подхода:
- WebSocket подписка (
eth_subscribe("logs", filter)илиeth_subscribe("newHeads")) — низкая латентность, но соединение рвётся, нужен reconnect с backoff и replay пропущенных блоков. - Polling + cursor — менее элегантно, но предсказуемо. Храним последний обработанный блок, опрашиваем
eth_getLogsс фильтром по адресам. Устойчивее к сетевым сбоям.
Для production: hybrid подход — WebSocket для низкой латентности, polling как fallback с cursor-based recovery.
Event Queue — буфер между listener и settlement. Kafka для высоких нагрузок, Redis Streams для средних. Ключевой момент: listener публикует TransactionDetected event, settlement подписывается. Это развязывает компоненты и гарантирует обработку при временном падении settlement service.
Settlement Service — проверяет confirmations, конвертирует сумму, обновляет статус заказа, нотифицирует upstream систему (webhook).
Почему детекция платежей — самый сложный компонент?
EVM-сети (ETH, BNB, Polygon, Arbitrum...) — разработка шлюза приема
Нативные переводы ETH: мониторим через eth_subscribe("newHeads") + eth_getBlockByNumber и фильтруем транзакции по to адресу.
ERC-20 токены (USDT, USDC, DAI): мониторим событие Transfer(address indexed from, address indexed to, uint256 value) через eth_getLogs с фильтром:
const filter = { fromBlock: 'latest', topics: [ ethers.id('Transfer(address,address,uint256)'), null, // from: любой ethers.zeroPadValue(paymentAddress, 32), // to: наш адрес ], }; Важно для USDT (Tether): у него нестандартный ERC-20 — функция transfer не возвращает bool. Вызов через стандартный интерфейс упадёт. Используем safeTransfer или низкоуровневый call с проверкой returndata.
Bitcoin и UTXO-модель
Для BTC нет понятия "адрес → транзакция" на уровне ноды. Используем либо:
- Electrum Server (Electrs) — индексирует UTXO по адресам, позволяет подписаться на адрес
- BlockCypher / Blockcypher WebHook API — hosted решение, но зависимость от третьей стороны
- Bitcoin Core с
importaddress— добавляем адрес в wallet node, получаем нотификации через ZMQ
Минимальные confirmations для BTC: 1 для small amounts (<$100), 3 для medium, 6 для large. Для Ethereum достаточно 12–20 блоков.
TON
TON транзакции асинхронны: входящий transfer это bounce-able сообщение, и вы должны проверять, что это именно transfer, а не bounce. Используем TonAPI или TON Center API с webhook на адрес.
Как обеспечить идемпотентность webhook?
Нотификация upstream системы через webhook должна быть идемпотентной — возможны повторные доставки при retry. В payload включаем payment_id (уникальный) + tx_hash + status. Upstream система должна проверять, не обрабатывала ли она уже этот payment_id. Retry policy: экспоненциальный backoff, 5–10 попыток, после — dead letter queue для ручного разбора.
Confirmation threshold и защита от double-spend
Нельзя считать платёж завершённым после первого обнаружения транзакции в mempool — это pending состояние, не подтверждённое. Минимальные пороги:
| Сеть | Порог | Обоснование |
|---|---|---|
| Ethereum | 12 блоков (~2.5 мин) | После merge finality через checkpoint, но 12 блоков — практический стандарт |
| BNB Chain | 15 блоков (~45 сек) | Централизован, но реорги бывают |
| Polygon PoS | 128 блоков (~4 мин) | Checkpoint на Ethereum каждые ~30 мин, до этого реорги возможны |
| Bitcoin | 3–6 блоков (30–60 мин) | Классика, для крупных сумм |
| Arbitrum/Optimism | 1 блок (L2 finality) | Реорги на L2 практически невозможны |
Partial payments и overpayments
Реальные пользователи иногда платят не точную сумму — биржи снимают комиссии, люди ошибаются. Нужна политика:
- Underpayment: если получено 99–100% суммы — считаем оплаченным (tolerance 1%). Если меньше —
partially_paid, ждём доплаты 30 минут, потомexpired. - Overpayment: автоматически принимаем, разницу возвращаем (нужен refund flow) или зачисляем как кредит.
Сравнение подходов к детекции
| Критерий | WebSocket | Polling | Hybrid |
|---|---|---|---|
| Латентность | Низкая | Средняя | Низкая |
| Надёжность | Требует reconnect | Предсказуемая | Высокая |
| Сложность реализации | Средняя | Низкая | Высокая |
| Нагрузка на RPC | Минимальная | Зависит от интервала | Оптимальная |
Пример настройки listener для production
# config.yml listener: networks: - name: ethereum rpc: wss://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY polling_interval: 12s confirmations: 12 addresses: - 0xYourPaymentAddress - name: bitcoin rpc: http://user:pass@localhost:18332 confirmations: 3 addresses: - bc1q... - name: polygon rpc: wss://polygon-mainnet.infura.io/ws/v3/YOUR_KEY confirmations: 128 addresses: - 0x... Этот конфиг используется в нашем референсном проекте и обеспечивает баланс между latency и надёжностью.
Стек
- Node.js + TypeScript или Go для listener и API — хорошая поддержка web3 библиотек
- ethers.js v6 или viem для EVM взаимодействия
- PostgreSQL для хранения платежей (ACID, транзакционность при обновлении статусов)
- Redis для rate limiting и кеша курсов
- Kafka или Redis Streams для event queue
- Grafana + Prometheus — мониторинг: lag listener vs chain head, скорость обработки, ошибки
Кастомный шлюз имеет смысл при объёме >500 платежей/день или при специфических требованиях к приватности и контролю. Для меньших объёмов — NOWPayments, CoinGate или аналоги закрывают задачу дешевле.
Как настроить listener: пошаговая инструкция
- Выберите сеть и определите необходимый порог подтверждений.
- Разверните WebSocket или polling listener с реконнектом.
- Настройте фильтр по адресам через
eth_getLogsдля токенов или поtoдля нативных монет. - Подключите Event Queue (Redis Streams для средних нагрузок).
- Реализуйте Settlement Service с проверкой идемпотентности.
- Протестируйте на тестовой сети, имитируя partial и double-spend платежи.
Что входит в работу
- Документация API шлюза в формате OpenAPI
- Исходный код репозитория (GitLab/GitHub) с лицензией на использование
- Деплой на вашу инфраструктуру или облако
- Обучение команды (2-часовой workshop)
- Техническая поддержка в течение 30 дней после запуска
Инвестиции в разработку окупаются за счёт снижения комиссий и полного контроля над потоком платежей. Получите бесплатную консультацию инженера — мы поможем определиться с архитектурой. Свяжитесь с нами для оценки вашего проекта.







