Crypto invoicing system development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Crypto invoicing system development
Medium
~5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Developing Crypto Invoicing

Crypto invoicing is not "accepting payment in crypto". This is creating a system where a customer receives an invoice for a specific fiat amount (or crypto amount), pays it in one of the supported currencies, and the vendor receives confirmation with correctly matched invoice. The main engineering problem is volatility: if a customer sees an invoice for $500 and ETH moves 3% while they transfer, you need to decide whose problem that is and how to handle it.

Invoice Pricing Models

Fixed crypto amount: invoice for 0.5 ETH. Customer pays exactly 0.5 ETH. No volatility — fiat volatility is entirely on vendor. Suitable for crypto-native B2B settlements.

Fixed fiat amount with lock-in: invoice for $500, system converts to crypto amount at creation time and fixes it for 15–30 minutes. Customer must pay the fixed crypto amount within window. If window expires — recalculate exchange rate. This is the most common model.

Floating with tolerance: accept payment in range ±1–2% of expected amount. Minor discrepancies from network fees or insignificant price movement don't block payment. Underpayment policy: credit at paid amount or require top-up — configurable by merchant.

System Architecture

Invoice Lifecycle

DRAFT → PENDING_PAYMENT (address assigned, timer started)
     → PARTIALLY_PAID (partial amount received)
     → PAID (full amount received, awaiting confirmations)
     → CONFIRMED (N confirmations)
     → EXPIRED (expired without payment)
     → OVERPAID (received more — requires manual decision)
interface Invoice {
  id: string;
  merchantId: string;
  fiatAmount: Decimal;
  fiatCurrency: 'USD' | 'EUR' | 'GBP';
  cryptoAmount: Decimal;
  cryptoCurrency: 'ETH' | 'USDT' | 'USDC' | 'BTC';
  depositAddress: string;
  exchangeRateLockedAt: Date;
  expiresAt: Date;
  status: InvoiceStatus;
  paidAmount: Decimal;
  txHashes: string[];
}

Address Generation

For each invoice — unique address derived from HD wallet xpub. This allows unambiguous matching of incoming payment to invoice without memo/tags:

function deriveInvoiceAddress(
  xpub: string, 
  invoiceIndex: number,
  network: Network
): string {
  const node = HDNodeWallet.fromExtendedKey(xpub);
  // path: m/44'/60'/0'/0/{invoiceIndex} for EVM
  return node.deriveChild(invoiceIndex).address;
}

For Bitcoin — native SegWit (bech32) addresses via BIP84 derivation. For TRON USDT — same logic, separate xpub for TRC-20 namespace.

Monitoring Incoming Payments

EVM networks: subscribe via WebSocket eth_subscribe("logs") to Transfer events for ERC-20 tokens, filter by active deposit address list. For native ETH — monitor via eth_subscribe("newHeads") + eth_getTransactionReceipt.

const monitorERC20Transfers = async (
  activeAddresses: Set<string>,
  provider: WebSocketProvider
) => {
  const filter = {
    topics: [
      ethers.id("Transfer(address,address,uint256)"),
      null,
      [...activeAddresses].map(addr => ethers.zeroPadValue(addr, 32))
    ]
  };
  
  provider.on(filter, async (log) => {
    const invoiceAddress = ethers.getAddress('0x' + log.topics[2].slice(26));
    const amount = BigInt(log.data);
    await handleIncomingPayment(invoiceAddress, amount, log.transactionHash);
  });
};

Multi-Currency and Exchange Rates

For inbound rate conversion — price aggregation from multiple sources with anomaly protection:

class PriceAggregator:
    SOURCES = ['binance', 'coinbase', 'kraken']
    MAX_DEVIATION_PCT = 1.0  # if one source deviates > 1% from median
    
    async def get_price(self, base: str, quote: str) -> Decimal:
        prices = await asyncio.gather(*[
            self.fetch_price(source, base, quote) 
            for source in self.SOURCES
        ])
        
        valid_prices = [p for p in prices if p is not None]
        median = statistics.median(valid_prices)
        
        # Filter anomalous values
        filtered = [
            p for p in valid_prices 
            if abs(p - median) / median * 100 < self.MAX_DEVIATION_PCT
        ]
        
        return Decimal(str(statistics.mean(filtered)))

Webhooks and Merchant Integration

Merchants receive invoice status notifications via signed webhooks:

function signWebhookPayload(payload: object, secret: string): string {
  const body = JSON.stringify(payload);
  const timestamp = Math.floor(Date.now() / 1000);
  const signature = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${body}`)
    .digest('hex');
  
  return `t=${timestamp},v1=${signature}`;
}

Recipient verifies signature and timestamp (replay attack protection — reject events older than 5 minutes). Same scheme as Stripe.

Retry policy for failed deliveries: exponential backoff (1min → 5min → 30min → 2h → 24h), after 5 failed attempts — alert in admin panel.

Accounting and Reporting

For B2B applications, automatic generation of:

  • PDF invoice with fiat amount, crypto amount, exchange rate at creation, txHash
  • CSV export of transactions with fiat equivalent for accountant
  • Accounting API integration (Xero, QuickBooks) via their REST API

Fiat equivalent for tax reporting is calculated at transaction confirmation rate — fixed and stored with invoice unchanged.

Stack and Deployment

  • Backend: Node.js/TypeScript or Go, REST API + WebSocket for statuses
  • Queue: BullMQ (Redis) for confirmation workers and webhook delivery
  • DB: PostgreSQL (invoices, transactions) + Redis (price cache, active addresses)
  • Nodes: Alchemy/QuickNode with failover or own nodes for high volumes

MVP with ETH, USDT (ERC-20), USDC support and basic merchant portal — 3–4 weeks. Full system with multi-currency, reporting, and partner APIs — 8–10 weeks.