Build with MCRTPay

Payment evidence.
Your order logic.

MCRTPay is a JavaScript widget and a Node.js transfer verifier. It is not a hosted merchant account, invoice database or fulfillment service.

Production boundary

The public endpoint checks transfers to its configured MCRTPay wallet only. Changing a widget’s receiving wallet does not change the hosted verifier’s wallet. Self-host the verifier for your wallet and connect it to an authenticated merchant backend.

Add the frontend widget

Download and review the source package, then copy public/js/mcrtpay.js to your own site at /vendor/mcrtpay.js. Serve the reviewed file from your own origin and pin your deployed version. The address-copy flow needs no third-party JavaScript. If you add QR rendering, self-host a reviewed, pinned QR library too. Your server creates an invoice for the signed-in customer before rendering checkout. Lock the exact MCRT amount and quote expiry on that invoice. Pass the same values to the widget:

<script src="/vendor/mcrtpay.js"></script>
<div id="mcrtpay-container"></div>
<script>
// invoice comes from YOUR authenticated server
new MCRTPay({
  walletAddress: invoice.walletAddress,
  paymentAmount: invoice.usdAmount,
  mcrtAmount: invoice.mcrtAmount,
  quoteExpiresAt: invoice.expiresAt, // epoch milliseconds
  planId: invoice.id,
  backendUrl: '/api/mcrtpay/verify',
  successCallback: () => refreshOrder()
});
</script>

The widget sends invoiceId and planId using the configured planId. It only fires the callback when your backend returns both success: true and fulfillmentCommitted: true. Never grant access from browser state.

For React or Next.js, mount the same widget in a client component after the container exists. Keep the widget instance and call widget.destroy() when the component unmounts. Creating a new widget in the same container retires the previous checkout, including pending requests and timers. A confirmed fulfillment removes payment instructions and calls the callback once for that instance. Your authentication, invoice database and server route are application-specific; they are not provided by this snippet.

Run the tested verifier

curl -fLO https://mcrtpay.com/downloads/mcrtpay-source.zip
unzip mcrtpay-source.zip
cd mcrtpay
npm ci
cp .env.example .env
# Configure your own receiving wallet, then:
npm test
npm start
MCRTPAY_WALLET_ADDRESS=0xYourReceivingWallet
MCRTPAY_MIN_CONFIRMATIONS=3
HOST=127.0.0.1
PORT=3000

Use Node.js 22 or newer. Put the server behind HTTPS. The default bind is loopback. The verifier needs no wallet private key and no BscScan API key. Do not place keys or seed phrases in the frontend or environment.

The maintained server implementation is the source of truth for canonical token filtering, 9-decimal integer amounts, bounded provider responses and confirmation checks. Use it instead of a copied, divergent verifier.

The merchant contract

Complete every requirement before inviting customers to pay. This is integration work in your application, not a feature switched on by the widget builder.

The public verifier never fulfills an invoice.

A response with transferVerified: true and fulfillmentCommitted: false is evidence only. It may be queried again; it is not a unique payment claim or authorization to unlock a product.

API reference

EndpointWhat it proves
GET /api/mcrtpay/configConfigured recipient, canonical token, decimals and confirmation threshold.
GET /api/crypto/pricesCached provider quote with source, timestamp and live/fallback state. Not an executable exchange price.
POST /api/mcrtpay/verifyTransfer evidence to the configured wallet. Never merchant fulfillment.
GET /healthApplication is responding. Does not prove RPC, pricing or merchant delivery health.

Verification request

{
  "txHash": "0x...64 hexadecimal characters...",
  "network": "bep20",
  "currency": "MCRT",
  "expectedAmount": "25000.000000001",
  "planId": "merchant-invoice-id"
}

Send JSON. Amounts are positive decimal MCRT values with at most 9 decimals. Requests are rate limited. Invalid input returns 400, pending confirmations return 202, request limits return 429 with a Retry-After header, unsupported request encodings return 415, and service failures return 503. A verified hosted response still returns success: false. Its verification object includes the normalized transaction hash, sender, recipient, token contract, chain ID, log index, amount, block number and confirmations. Sender evidence is not proof that the person submitting the hash controls that wallet.

Do not configure the public endpoint as a production fulfillment backend or treat client-supplied expectedAmount as an invoice price. The historical /api/jpay/verify and /verify-payment aliases have the same evidence-only boundary.

Key widget options

OptionPurpose
walletAddressRequired BNB Chain recipient. Must match the server invoice.
paymentAmountOptional USD reference for display only. It never sets the payable token amount.
mcrtAmountExact decimal token amount locked by the merchant invoice.
quoteExpiresAtInvoice quote expiry as epoch milliseconds.
planIdMerchant-issued invoice ID starting with a letter or number, followed by up to 99 letters, numbers, dots, underscores, colons or hyphens.
backendUrlYour authenticated verification and fulfillment route. Redirects are refused; use the final URL. Cross-origin HTTPS requires explicit allowCrossOriginBackend: true and does not send cookies cross-origin.
demoModeNon-payable preview. No real receiving address or verification.
validateOnBackendKeep true. Disabled mode cannot produce an automated success.

Canonical token reference

Network: BNB Chain mainnet, chain ID 56.
Decimals: 9.
Token contract, not a receiving wallet:

0x4b8285aB433D8f69CB48d5Ad62b415ed1a221e4f

Network gas is paid separately in BNB. Quote sources and public RPC providers can fail or disagree. Confirmation counts reduce risk but do not guarantee finality. Review the security and risk notice before accepting funds.

Validate the complete integration

Test wrong recipient, token and chain; underpayment; expired quotes; a reused hash; a different user’s transfer; simultaneous claims; service restart; failed RPC; and failed delivery. A funded acceptance test requires an authorized payment and a real merchant invoice. This website’s demo does not perform one.

Open widget builder →