Crypto Payment Widget 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 Payment Widget Development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1215
  • 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
    1043
  • 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

Development of Cryptocurrency Payment Widget

Typical requirement: "we want to accept crypto on the website, like PayPal but for USDT". In practice, this means solving several non-trivial tasks simultaneously: generating unique addresses for each payment, detecting incoming transactions, handling different networks and tokens, correctly working with confirmations and reorgs. Ready-made solutions like Coinbase Commerce or NOWPayments charge 0.5–1% fees and have limited customization. A custom widget is justified when volume is several thousand dollars per month or when you need deep integration with business logic.

Architecture: What's Inside the Widget

The widget is just the UI part. The real work happens on the backend:

Frontend Widget
    │ create order / show address and QR
    ▼
Backend API
    │ address generation → database record → polling/webhook
    ▼
Blockchain Monitoring Service
    │ tracks transactions on addresses
    ▼
Payment Processor
    │ confirmation → callback to application

Address Generation: HD Wallet

Each payment needs a unique address — otherwise it's impossible to match an incoming payment to a specific order. The standard approach is BIP-44 HD Wallet:

import { ethers } from 'ethers';

const masterWallet = ethers.HDNodeWallet.fromMnemonic(
  ethers.Mnemonic.fromPhrase(process.env.PAYMENT_MNEMONIC!)
);

function derivePaymentAddress(orderId: number): string {
  // path: m/44'/60'/0'/0/{orderId}
  const child = masterWallet.derivePath(`m/44'/60'/0'/0/${orderId}`);
  return child.address;
}

The mnemonic is stored in HSM or Vault, private keys are never materialized on the server in plain text. For multi-currency: different coin types per BIP-44 (60 for Ethereum/EVM, 0 for Bitcoin, 195 for Tron).

For EVM networks with identical addresses (Ethereum, BNB Chain, Polygon, Arbitrum), one address works on all networks — but you need to monitor each network separately.

Transaction Monitoring

Two approaches: polling RPC and webhook subscriptions.

Polling — simpler, but creates load:

async function pollAddress(address: string, network: string) {
  const provider = getProvider(network);

  // For ERC-20 tokens we listen to Transfer events
  const usdtContract = new ethers.Contract(USDT_ADDRESS, ERC20_ABI, provider);

  const filter = usdtContract.filters.Transfer(null, address);
  const latestBlock = await provider.getBlockNumber();

  // Check last N blocks
  const events = await usdtContract.queryFilter(filter, latestBlock - 10, latestBlock);

  for (const event of events) {
    await processIncomingPayment({
      txHash: event.transactionHash,
      amount: event.args.value,
      token: 'USDT',
      network,
    });
  }
}

Webhooks — via Alchemy, QuickNode, or Moralis. Subscribe to address events, receive push notifications on each transaction. More reliable than polling, but depends on the provider:

// Alchemy Notify webhook
const webhook = await alchemy.notify.createWebhook(
  'https://your-api.com/webhook/payment',
  WebhookType.ADDRESS_ACTIVITY,
  { addresses: [paymentAddress] }
);

Confirmations and Double-Spend Protection

Different assets require different numbers of confirmations:

Asset/Network Recommended Confirmations Time
ETH / ERC-20 (Ethereum) 12–20 blocks ~3–4 min
BNB Chain 15–20 blocks ~1 min
Polygon 100–150 blocks ~4–6 min
TRON TRC-20 20 blocks ~1 min
Bitcoin 3–6 blocks ~30–60 min

Polygon requires more confirmations due to higher probability of reorg. Don't count payment as final until reaching the required threshold.

For stablecoins: additionally verify that the token contract is official. A user may send a fake token named "USDT". Whitelisting contract addresses is mandatory.

Widget UI/UX Components

Minimal set for conversion:

┌─────────────────────────────────────┐
│  Pay: 47.50 USDT                    │
│                                     │
│  Network: [Ethereum ▼] [BNB Chain ▼]│
│                                     │
│  [QR-code]   0x7f3a...b2c4          │
│             [Copy]                  │
│                                     │
│  ⏱ Waiting for payment: 14:32      │
│  ● Expecting transaction...        │
└─────────────────────────────────────┘

Critical: session timer (usually 15–30 minutes), after which the address is released and the rate is recalculated. Status updates via WebSocket or SSE — polling every 5 seconds is annoying and creates load.

Fiat-to-crypto conversion: use Chainlink Price Feeds or CoinGecko API with caching. Add 1–2% buffer to the rate accounting for volatility during waiting time.

Handling Underpayment and Overpayment

Real users often pay inexact amounts:

  • Underpayment (sent less): either block the order until additional payment, or accept with "partial payment" note — depends on business logic
  • Overpayment (sent more): credit the user's account, or return the difference automatically
  • Network fee: for native coins (ETH, BNB) the user must have it in the wallet separately — a UX moment that's important to explain

Security

  • Mnemonic in Vault (HashiCorp Vault or AWS Secrets Manager), never in .env
  • Rate limiting on address generation endpoint
  • Idempotency: same orderId always returns the same address
  • Audit log of all transactions with confirmations
  • Periodic reconciliation: sum of confirmed payments in DB should match on-chain balances