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

Выставление счетов в криптовалюте — это не просто прием платежей, а полноценный процесс с юридическими документами и сверкой. Мы разрабатываем системы криптобиллинга, которые автоматизируют генерацию счетов, отслеживание транзакций и интеграцию с бухгалтерией. Наша команда реализует проект под ключ — от концепции до сопровождения, обеспечивая надежность и масштабируемость решения.
Часто задаваемые вопросы

Разница между «принять крипто-платёж» и «выставить счёт в криптовалюте» — принципиальная. Счёт — это юридический документ с зафиксированной суммой, сроком оплаты, идентификатором контрагента и возможностью сверки. Большинство готовых решений останавливаются на первом — дают адрес для оплаты. Полноценный биллинг требует учёта, напоминаний, частичных оплат, мультивалютности и интеграции с бухгалтерией. В этой статье разберём, как построить систему криптобиллинга с нуля: генерация уникальных платёжных адресов через 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 недели каждый. Для точной оценки свяжитесь с нами — мы проанализируем вашу спецификацию и предложим реалистичный план.

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

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

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

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

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1141