Custom Cryptocurrency Payment Widget Development
We often get requests: "We want to accept crypto on the site, 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, and correctly dealing 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 turnover exceeds $10,000 per month—savings on fees can reach $100–$500 monthly. Our experience: 10+ years in blockchain development and over 50 deployed payment solutions. We guarantee complete control over transactions and no hidden fees. A basic widget costs from $5,000, saving you up to $500 monthly on fees.
Why a Custom Widget?
| Criteria | Ready-made gateways (Coinbase Commerce, NOWPayments) | Custom widget |
|---|---|---|
| Fee | 0.5–1% + possible hidden charges — custom widget is 100% cheaper (0% fee) | Only gas and infrastructure costs |
| Customization | Only color and logo selection — custom widget offers unlimited UI/UX control | Full control: UI/UX, currencies, callbacks |
| Integration | Closed API, limited webhooks — custom widget gives direct DB writes and custom events | Custom webhook events, direct DB writes |
| Security | Keys on provider side — custom widget keeps your keys, your infrastructure | Your keys, your infrastructure |
| Supported networks | Limited list — custom widget supports any EVM networks, Bitcoin, Tron, Solana | Any EVM networks, Bitcoin, Tron, Solana |
Architecture
The widget is only the UI part. The real work happens on the backend:
Frontend Widget │ create order / show address and QR ▼ Backend API │ address generation → DB write → polling/webhook ▼ Blockchain Monitoring Service │ monitors transactions on addresses ▼ Payment Processor │ confirmation → callback to application Integration
- Place the JavaScript widget script on the page and initialize it with an API key.
- Call
createPayment({orderId, amount, currency})—the widget generates an address and QR code. - Handle the
onPaymentConfirmed(paymentData)callback in your application to update the order status.
Technical Implementation
HD Wallet Address Generation
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 (see BIP-44): "BIP-44 defines hierarchical deterministic wallets" (Wikipedia).
import { ethers } from 'ethers'; const masterWallet = ethers.HDNodeWallet.fromMnemonic( ethers.Mnemonic.fromPhrase(process.env.PAYMENT_MNEMONIC!) ); function derivePaymentAddress(orderId: number): string { 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. For multi-currency, different coin types are used according to BIP-44 (60 for Ethereum/EVM, 0 for Bitcoin, 195 for Tron). For EVM networks with identical addresses, one address works across all networks—but each network must be monitored separately.
Transaction Monitoring
Two approaches: polling RPC and webhook subscriptions. Polling is simpler but creates load:
async function pollAddress(address: string, network: string) { const provider = getProvider(network); const usdtContract = new ethers.Contract(USDT_ADDRESS, ERC20_ABI, provider); const filter = usdtContract.filters.Transfer(null, address); const latestBlock = await provider.getBlockNumber(); 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 on each transaction:
const webhook = await alchemy.notify.createWebhook( 'https://your-api.com/webhook/payment', WebhookType.ADDRESS_ACTIVITY, { addresses: [paymentAddress] } ); Private Key Security
The key risk is compromise of the master mnemonic. We apply multi-layer protection:
- Mnemonic is stored in HashiCorp Vault with on-the-fly encryption and access policies.
- Never use .env files in production.
- Private keys for each address are derived via BIP-44 and never materialized in the application.
- All wallet operations are logged, alerting is set up for suspicious activity.
For particularly sensitive projects, we use a hardware security module (HSM)—for example, AWS CloudHSM or YubiHSM. Multi-signature for withdrawals is also configured: transactions over $10,000 require a second key confirmation.
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 reorg probability. Do not mark a payment as final until the required threshold is reached.
For stablecoins: additionally verify that the token contract is official. A user could send a fake token named "USDT". A contract address whitelist is mandatory.
UI/UX and Edge Cases
Widget UI Components
Minimal set for conversion:
┌─────────────────────────────────────┐ │ Pay: 47.50 USDT │ │ │ │ Network: [Ethereum ▼] [BNB Chain ▼] │ │ │ │ [QR code] 0x7f3a...b2c4 │ │ [Copy] │ │ │ │ ⏱ Awaiting payment: 14:32 │ │ ● Waiting for transaction... │ └─────────────────────────────────────┘ Critical: session timer (usually 15–30 minutes) after which the address is released and the exchange 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 a 1–2% buffer to the rate to account for volatility during the waiting period.
Handling Underpayment and Overpayment
Real users often pay an imprecise amount:
- Underpayment (sent less): either block the order pending a top-up, or accept with a "partial payment" flag—depends on business logic.
- Overpayment (sent more): credit the user or automatically return the difference.
- Network fee: for native coins (ETH, BNB) the user must have it in their wallet separately—this UX point must be explained.
What's Included and Project Estimation
- API documentation for integrating the widget with your site.
- A test environment in one of the networks (Goerli/Sepolia) for acceptance.
- Source code with deployment instructions (Docker, CI/CD).
- Integration with your CRM or ERP via webhook callbacks.
- Training your team on the admin panel and monitoring.
- Warranty support for 3 months (included in the price).
Order development of a payment widget for your business—we will evaluate the project in 1-2 days and propose the optimal architecture. Get a consultation: discuss requirements, timeline, and budget. Full control over crypto payments without intermediaries.







