Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
Integration & Development11 min read

Cryptocurrency Payment Systems: Architecture, Integration, and Verification

A technical guide to designing, integrating, and verifying cryptocurrency payment systems, from invoice creation and chain monitoring to settlement and reconciliation.

TL;DR

A cryptocurrency payment system is a set of services that turns a blockchain transfer into a verifiable, reconciled business transaction. This article explains the components, the invoice and confirmation lifecycle, and how to integrate chain monitoring without trusting a single signal. It includes runnable diagnostic procedures for checking a payment transaction over JSON-RPC and a reconciliation workflow you can reproduce against your own nodes. It separates documented protocol behavior from design recommendations and from measurements you must run in your own environment.

Scope and the direct answer

Cryptocurrency payment systems are not a single product. They are an integration pattern: a merchant or platform creates an invoice, a customer broadcasts a transfer on a blockchain, and backend services detect, confirm, and reconcile that transfer before goods or balances are released. The blockchain is the settlement rail; everything else — pricing, address assignment, confirmation policy, accounting — is application logic you own or delegate to a gateway.

This guide is for engineers and operators building or auditing that logic. It covers the mechanism, a runnable verification procedure, expected results, failure modes, and the tradeoffs between self-custodial and gateway-mediated designs. It does not rank providers. When you need a concrete RPC endpoint or provider recommendation, use the OnFinality RPC Assistant rather than treating this page as a provider list.

  • Documented behavior: what a blockchain transfer and its receipt actually prove.
  • Recommendations: confirmation depth, idempotency, and reconciliation design choices.
  • Measurements: latency, reorg frequency, and finality timing you must observe on your own networks.

Assumptions and prerequisites

The procedures below assume an EVM-compatible chain and a JSON-RPC endpoint you control or trust, such as a dedicated node or a managed endpoint. You need the ability to run curl or a short script, a database or ledger table for invoices, and a job scheduler for polling or a websocket subscription for push events.

You also need a clear policy decision before writing code: which assets you accept, how many confirmations you require, and whether you settle in the asset itself or convert to fiat or stablecoins. Those decisions drive the rest of the architecture. For endpoint selection across networks, see the OnFinality networks directory and the RPC endpoint guide.

  • A JSON-RPC URL for each chain you accept, stored as an environment variable such as RPC_URL.
  • An invoice table with unique IDs, expected amount, asset, and an assigned deposit address or memo.
  • A confirmation policy per chain, reviewed against that chain's documented finality behavior.
  • A reconciliation job that compares on-chain state with your internal ledger.

Mental model: the invoice lifecycle

Every crypto payment moves through a small state machine. Modeling it explicitly prevents the most common class of bugs: releasing value on a transaction that is later reorged out or that paid the wrong amount.

The lifecycle is: created → awaiting payment → detected (seen in mempool or in a block) → confirmed (reached your depth policy) → settled (credited in your ledger) → reconciled. A separate expired or underpaid branch handles timeouts and partial payments. Each transition should be idempotent and driven by a unique key such as the transaction hash plus the invoice ID.

  • Created: invoice persisted with a unique deposit address and an expiry timestamp.
  • Detected: a matching transfer appears in a block; do not credit yet.
  • Confirmed: the transfer has reached your required confirmation depth.
  • Settled: your ledger records the credit and any conversion.
  • Reconciled: a periodic job re-checks settled transactions against chain state.

Components of a cryptocurrency payment system

A production system typically separates concerns into a checkout service, a chain watcher, a confirmation engine, a ledger, and a settlement or payout service. The checkout service prices the invoice and assigns an address. The chain watcher subscribes to blocks or polls for transfers to your addresses. The confirmation engine applies depth and value rules. The ledger is the source of truth for accounting, and the settlement service handles conversion or payout.

If you use a hosted gateway, several of these components are outsourced, but the ledger and reconciliation remain yours. That boundary matters: a gateway's webhook is a notification, not a proof. Your system should still be able to verify the underlying transfer independently. For teams running their own infrastructure, a dedicated node reduces dependence on third-party rate limits and gives you consistent access to historical logs.

Runnable check: verifying a payment transaction over JSON-RPC

The first diagnostic for any disputed or delayed payment is to read the transaction and its receipt directly. The following curl calls use placeholders; replace RPC_URL with your endpoint and TX_HASH with the transaction hash. The first call returns the transaction, including the recipient and value. The second returns the receipt, including status and block number.

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["TX_HASH"]}'

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"eth_getTransactionReceipt","params":["TX_HASH"]}'

Expected verification result

A valid payment transaction returns a non-null transaction object whose to field matches your assigned deposit address and whose value matches the invoice amount in the asset's smallest unit. The receipt returns status 0x1 for success and a blockNumber. If the receipt is null, the transaction is pending or unknown; if status is 0x0, the transfer reverted and did not move value.

Record the block number and compare it with the current head from eth_blockNumber. The difference is your observed confirmation count. Do not treat a mempool sighting as payment. The table below is a template for logging what you observe; fill it with values from your own runs rather than assuming any numbers.

  • | Field | Source | Expected |
  • | tx.to | eth_getTransactionByHash | matches assigned address |
  • | tx.value | eth_getTransactionByHash | equals invoice amount |
  • | receipt.status | eth_getTransactionReceipt | 0x1 |
  • | confirmations | head minus receipt.blockNumber | at or above policy |

Implementation: a confirmation and reconciliation loop

The following Python sketch polls the head, checks pending invoices, and only settles when the confirmation policy is met. It is intentionally small; production code needs retries, backoff, and persistent state. The key design point is that settlement is gated on chain-derived confirmations, not on a webhook alone.

import os, time, requests

RPC_URL = os.environ["RPC_URL"]
REQUIRED_CONFIRMATIONS = int(os.environ.get("REQUIRED_CONFIRMATIONS", "12"))

def rpc(method, params):
    r = requests.post(RPC_URL, json={"jsonrpc":"2.0","id":1,"method":method,"params":params}, timeout=10)
    r.raise_for_status()
    return r.json()["result"]

def confirmations(tx_hash):
    receipt = rpc("eth_getTransactionReceipt", [tx_hash])
    if not receipt or receipt.get("status") != "0x1":
        return 0
    head = int(rpc("eth_blockNumber", []), 16)
    return head - int(receipt["blockNumber"], 16) + 1

# Example loop over invoice rows from your database
for invoice in load_pending_invoices():
    depth = confirmations(invoice["tx_hash"])
    if depth >= REQUIRED_CONFIRMATIONS:
        mark_settled(invoice["id"], depth)

Troubleshooting common payment failures

Most payment incidents fall into a few categories: the transaction is pending because the fee was too low, the transfer went to the wrong address or memo, the amount was underpaid due to price movement, or the receipt reverted. Each has a distinct diagnostic path.

For pending transactions, check the current base fee and compare it with the transaction's fee fields. For wrong-address transfers, there is usually no recovery without the recipient's cooperation; this is why address assignment must be unique and displayed clearly. For underpayment, compare the received value with the invoice amount at the quoted rate and decide whether to accept, top up, or expire. For reverted receipts, the value did not move and the invoice remains unpaid.

  • Pending: inspect fee fields and mempool status; consider replacement only if your policy allows it.
  • Underpaid: reconcile against the quoted rate and define a tolerance before launch.
  • Reverted: status 0x0 means no value transferred; do not credit.
  • Duplicate webhooks: deduplicate on transaction hash plus invoice ID.

Limitations and tradeoffs

Self-custodial systems give you control and reduce counterparty risk, but you own key management, reorg handling, and compliance. Gateway-mediated systems reduce operational burden and can offer fiat conversion, but they introduce a trusted intermediary and webhook dependencies. Neither removes the need for reconciliation.

Confirmation depth is a tradeoff between speed and safety. Stablecoins and fast-finality chains may need fewer confirmations than probabilistic-finality chains, but you should measure reorg behavior on your chosen network rather than assuming. Throughput and latency also depend on your RPC provider; measure them under your own load. For performance-sensitive deployments, review the dedicated node options and the pricing model before committing.

Next steps

Start by writing down your invoice state machine and confirmation policy, then implement the verification procedure above against a testnet. Once it passes, run a reconciliation job on a schedule and log every state transition. If you need help choosing an endpoint or network, the RPC Assistant can give a direct recommendation, and the Learn library covers related infrastructure topics such as node hosting and multi-chain endpoints.

  • Read the blockchain node hosting guide for infrastructure planning.
  • Review the multi-chain RPC endpoints guide if you accept assets on several networks.
  • Compare dedicated node options for consistent payment monitoring throughput.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started