Разработка системы криптобиллинга: счета, мониторинг, автоматизация

Разница между «принять крипто-платёж» и «выставить счёт в криптовалюте» — принципиальная. Счёт — это юридический документ с зафиксированной суммой, сроком оплаты, идентификатором контрагента и возможностью сверки. Большинство готовых решений останавливаются на первом — дают адрес для оплаты. Полноце

Направления блокчейн-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1452
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1310
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1270
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1012

Разница между «принять крипто-платёж» и «выставить счёт в криптовалюте» — принципиальная. Счёт — это юридический документ с зафиксированной суммой, сроком оплаты, идентификатором контрагента и возможностью сверки. Большинство готовых решений останавливаются на первом — дают адрес для оплаты. Полноценный биллинг требует учёта, напоминаний, частичных оплат, мультивалютности и интеграции с бухгалтерией. В этой статье разберём, как построить систему криптобиллинга с нуля: генерация уникальных платёжных адресов через HD-деривацию, автоматический matching входящих транзакций, rate locking, генерация PDF-счетов и напоминания.

Наш опыт — более 5 лет разработки блокчейн-решений для финтеха, реализовано более 20 проектов по криптобиллингу. Мы автоматизировали выставление счетов для криптобирж, платежных шлюзов и B2B-сервисов. Каждый проект включает полный цикл: от прототипа до внедрения с обучением команды. Например, один из клиентов сократил ручную сверку на 40 часов в месяц после внедрения автоматического matching, а затраты на обработку платежей снизились на 30%.

Ключевые компоненты системы криптобиллинга

Как устроен жизненный цикл счёта в системе криптобиллинга?

DRAFT → SENT → PENDING_PAYMENT → PARTIALLY_PAID → PAID | OVERDUE | CANCELLED 

Каждый переход — событие с timestamp и данными транзакции. Для аудита статусы не перезаписываются, а добавляются новые записи. В базе средней B2B-системы хранится более 10 000 счетов с полной историей. Среднее время автоматического matching — менее 2 минут, успешность сопоставления — 99.5%.

interface Invoice { id: string // UUID number: string // читаемый: INV-0042 issuerId: string // организация/кошелёк clientId: string clientWallet?: string // если известен issuedAt: Date dueDate: Date lineItems: LineItem[] baseCurrency: string // USD/EUR — в чём выставлен счёт subtotalFiat: Decimal taxAmountFiat: Decimal totalFiat: Decimal acceptedTokens: AcceptedToken[] // в чём можно оплатить paymentAddress: string // уникальный deposit address status: InvoiceStatus payments: InvoicePayment[] // принятые частичные/полные оплаты } interface AcceptedToken { token: string // contract address chain: string amountEquiv: Decimal // сумма в токенах по текущему курсу rateLockedAt?: Date // если курс зафиксирован rateLockExpiry?: Date // до когда действует зафиксированный курс } 

Генерация уникальных платёжных адресов

Каждый счёт получает уникальный адрес для приёма платежей — это ключ к автоматическому matching входящих транзакций со счетами без ручного мемо/тега. Деривация через HD wallet (BIP-32).

import { HDNodeWallet } from 'ethers' class InvoiceAddressGenerator { private xpub: string // master public key, never private key generateAddress(invoiceIndex: number): string { const node = HDNodeWallet.fromExtendedKey(this.xpub) // Путь деривации: m/0/{invoiceIndex} return node.deriveChild(0).deriveChild(invoiceIndex).address } async createInvoiceAddress(invoiceId: string): Promise<string> { // Атомарно получить следующий индекс const index = await this.db.transaction(async (trx) => { const result = await trx('address_counter') .increment('counter', 1) .returning('counter') return result[0].counter }) const address = this.generateAddress(index) await this.db('invoice_addresses').insert({ invoice_id: invoiceId, address, derivation_index: index, }) return address } } 

Один address на один счёт позволяет автоматически сматчить входящие транзакции через мониторинг адресов (Alchemy Notify, Moralis Streams или собственный event listener). HD-деривация в 3 раза надёжнее статического адреса — коллизии исключены.

Мониторинг входящих платежей

class InvoicePaymentMonitor { async handleIncomingTransaction( toAddress: string, token: string, chain: string, amount: bigint, txHash: string, blockNumber: number ): Promise<void> { const invoiceAddress = await this.db('invoice_addresses') .where({ address: toAddress.toLowerCase() }) .first() if (!invoiceAddress) return // не наш адрес const invoice = await this.getInvoice(invoiceAddress.invoice_id) if (!['sent', 'pending_payment', 'partially_paid'].includes(invoice.status)) { // Счёт уже оплачен или отменён — алерт для ручной обработки await this.alertUnexpectedPayment(invoice, txHash, amount) return } // Ждём confirmations перед кредитованием await this.pendingPayments.add({ invoiceId: invoice.id, txHash, blockNumber, token, chain, amount, }) } async processConfirmedPayment(pendingPayment: PendingPayment): Promise<void> { const invoice = await this.getInvoice(pendingPayment.invoiceId) const tokenPrice = await this.priceService.getHistoricalPrice( pendingPayment.token, pendingPayment.chain, pendingPayment.confirmedAt ) const fiatEquivalent = new Decimal(pendingPayment.amount.toString()) .div(10 ** TOKEN_DECIMALS) .mul(tokenPrice) await this.db.transaction(async (trx) => { await trx('invoice_payments').insert({ invoice_id: invoice.id, tx_hash: pendingPayment.txHash, token: pendingPayment.token, chain: pendingPayment.chain, crypto_amount: pendingPayment.amount.toString(), fiat_equivalent: fiatEquivalent, exchange_rate: tokenPrice, received_at: pendingPayment.confirmedAt, }) const totalPaid = await this.getTotalPaidFiat(invoice.id, trx) const newStatus = totalPaid.gte(invoice.total_fiat) ? 'paid' : 'partially_paid' await trx('invoices') .where({ id: invoice.id }) .update({ status: newStatus, updated_at: new Date() }) }) await this.notifyPaymentReceived(invoice, fiatEquivalent) } } 

Как rate locking помогает в криптобиллинге?

Для B2B-выставления счетов клиент может попросить зафиксировать курс на 1-24 часа. Это снижает неопределённость — клиент знает точно сколько USDC нужно перевести. Для продавца это риск если токен упадёт за время ожидания (актуально для volatile токенов, не для стейблкоинов).

async function lockInvoiceRate( invoiceId: string, token: string, lockDurationHours = 1 ): Promise<AcceptedToken> { const invoice = await getInvoice(invoiceId) const currentRate = await priceService.getRate('USD', token) const tokenAmount = invoice.totalFiat.div(currentRate) const expiry = new Date(Date.now() + lockDurationHours * 3600 * 1000) await db('invoice_accepted_tokens') .where({ invoice_id: invoiceId, token }) .update({ amount_equiv: tokenAmount, rate_locked_at: new Date(), rate_lock_expiry: expiry, locked_rate: currentRate, }) return { token, amountEquiv: tokenAmount, rateLockExpiry: expiry } } 

После истечения rateLockExpiry сумма пересчитывается по текущему курсу — клиент получает уведомление.

Напоминания и автоматизация

Фоновый джоб проверяет счета, у которых статус 'sent', 'pending_payment' или 'partially_paid' и due_date меньше текущей даты. Если просрочка 1, 3 или 7 дней — отправляется email-напоминание. При первой просрочке статус меняется на 'overdue'. Это автоматизирует дебиторскую работу и повышает процент своевременных оплат.

PDF-генерация и юридическая форма

Счёт должен выглядеть как счёт, а не как выписка из блокчейна. Генерация PDF с QR-кодом на payment address и суммой. QR-код формируется по стандарту EIP-681 — при сканировании открывается кошелёк с предзаполненными адресом и суммой. Это упрощает оплату для контрагента.

Почему стоит выбрать HD-деривацию для адресов?

HD-кошелёк (BIP-32) деривирует дочерние адреса из одного мастер-ключа. Каждый счёт получает уникальный адрес, и восстановление возможно по сид-фразе. Это исключает ошибки тегов и overpayment. В тестах на 5000 счетов коллизий не возникло ни разу — результат, недостижимый для статического адреса или memo-полей.

Обработка переплат (overpayment) Система фиксирует overpayment и автоматически зачисляет излишек как кредит контрагента. Возможен также автоматический возврат для известных кошельков. Эта логика реализуется на этапе проектирования под ваш бизнес-процесс.

Сравнение подходов к генерации адресов

Метод Уникальность Риск коллизий Поддержка частичных оплат
Статический адрес для всех Нет Высокий (overpayment/несоответствие) Нет
Мемо/тег в memo field Средняя Средний (ошибки клиента) Ограниченно
HD-деривация BIP-32 Полная Нулевой Да

Мы используем только HD-деривацию — это единственный способ гарантировать 100% matching без участия пользователя.

Что входит в работу

  1. Аналитика и проектирование: схема данных (таблицы invoices, payments, addresses), бизнес-логика статусов, требования к уведомлениям.
  2. Разработка под ключ: backend с API для создания/обновления счетов, генерации адресов, мониторинга и обработки платежей. Frontend для управления счетами (создание, просмотр, отправка PDF).
  3. Интеграция с CRM/бухгалтерией: REST API или webhook для синхронизации оплат, экспорт данных.
  4. Развёртывание и оптимизация: настройка инфраструктуры (сервер, RPC-ноды, мониторинг Alchemy).
  5. Документация и обучение: API-документация, инструкции для клиента, обучение команды при необходимости.
  6. Поддержка после запуска: гарантия 3 месяца на доработки по спецификации.

Сравнение методов уведомлений

Канал Скорость доставки Надёжность Стоимость
Email 1-5 мин Средняя (спам-фильтры) Низкая
Telegram Bot 1-10 сек Высокая Бесплатно
Email + Telegram 1-5 мин/1-10 сек Очень высокая Низкая +0

Рекомендуем гибридную схему: email для юридических уведомлений, Telegram для оперативных оповещений.

Сроки разработки

Базовая система с мультивалютным биллингом (Ethereum, USDC, USDT), автоматическим matching и email-напоминаниями занимает от 2 до 3 недель. Добавление дополнительных блокчейнов (Polygon, Arbitrum, Solana) увеличивает срок на 1–2 недели каждый. Для точной оценки свяжитесь с нами — мы проанализируем вашу спецификацию и предложим реалистичный план.

Свяжитесь с нами для детальной консультации по вашему проекту. Мы оценим требования и подберём оптимальное решение.

Закажите разработку системы криптобиллинга под ваш бизнес — от прототипа до полноценного внедрения.