Skip to content

Demo Shop ​

HashNut provides fully working demo merchant applications that demonstrate the complete payment integration flow. Use them as a reference for your own implementation.

ComponentLanguageRepository
Demo backend (Go)Go + Ginhashnut-demo-go
Demo backend (Java)Java + Spring Boothashnut-demo
Demo frontendReact + TypeScripthashnut-demo-web

Both backends implement the same API; the frontend works with either.

TIP

To actually run it (clone the code, start the database, fill in the API key, start the backend and frontend, complete a payment), see 2.5 Verify the API Key — that page is written as an ordered walkthrough.

This page is reference material: architecture, database schema, and the details that matter when you write your own implementation.

Architecture ​

Browser (localhost:5173)           Demo Backend (localhost:1800)          HashNut API
        |                                   |                                |
        |  GET /api/products                |                                |
        |---------------------------------->|                                |
        |  GET /api/chains                  |                                |
        |---------------------------------->|  (reads from DB)               |
        |                                   |                                |
        |  POST /api/orders                 |                                |
        |  {productId, blockChain, tokenSymbol} |                            |
        |---------------------------------->|  SDK.createOrder()             |
        |                                   |------------------------------->|
        |                                   |  payOrderId + receiptAddress   |
        |  payUrl (redirect to HashNut)     |<-------------------------------|
        |<----------------------------------|                                |
        |                                   |                                |
        |  (user pays on HashNut page)      |                                |
        |                                   |  POST /api/notify (webhook)    |
        |                                   |<-------------------------------|
        |                                   |  update order status           |
        |                                   |                                |
        |  redirect to /payment-result      |                                |
        |  (frontend shows success)         |                                |

API list ​

What the backend exposes to the frontend. Identical in both language versions:

MethodPathDescription
GET/api/productsList products
GET/api/chainsList supported chains and tokens (read from the database)
POST/api/ordersCreate an order {productId, blockChain, tokenSymbol}
GET/api/orders/:idQuery order status
POST/api/orders/:id/confirmSubmit the payment transaction hash {payTxId}
POST/api/notifyHashNut payment notification callback

Database schema ​

The demo uses PostgreSQL with the following tables:

TablePurpose
t_coin_infoSupported chains and tokens (decides what the frontend offers)
t_hashnut_api_keyPer-chain splitter address + API credentials
productsProducts (price only, not bound to a chain/token)
ordersOrders (records the chain and token the user chose)

t_coin_info decides which chains and tokens appear on the payment page. Configure it for the chains you actually accept:

sql
INSERT INTO t_coin_info (block_chain, token_symbol, chain_label, coin_label, contract_address, decimals) VALUES
    ('ETH', 'usdt', 'Ethereum', 'USDT', '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6),
    ('TRON', 'usdt', 'Tron',     'USDT', 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',         6);

t_hashnut_api_key holds one row per chain, with values taken from the one-key setup export — see 2.5.4 Put the account info into migrate.sql.

Key implementation details ​

Before copying the demo, these are the parts most likely to cause trouble in your own code.

Multi-chain support ​

Products are not bound to a specific chain. The frontend lets users choose which chain and token to pay with, and passes blockChain + tokenSymbol in the order request. The backend looks up the corresponding splitter and API credentials from the database.

Webhook handling ​

The /api/notify endpoint receives payment notifications from HashNut. Your handler must:

  1. Parse the JSON payload (payOrderId, state, payTxId)
  2. Update the order status in your database
  3. Return the string "success" (HTTP 200) to acknowledge receipt

If you don't return "success", HashNut will retry the notification.

The full notification payload and signature scheme are documented in Notifications.

Payment page redirect ​

When an order is created, the backend returns a payUrl pointing to the HashNut payment page. The frontend redirects the user there. After payment, the user is redirected back to your callbackUrl with query parameters including state and merchantOrderId.

notifyUrl and callbackUrl point in opposite directions ​

This is the most commonly confused pair of parameters:

FieldWho calls whomMust be publicly reachable
notifyUrlHashNut server → your serverYes
callbackUrlUser's browser → your siteNo

In the demo the corresponding paths are /api/notify and /payment-result. During local development notifyUrl needs a tunnel to be publicly reachable — see Appendix: Making notifyUrl publicly reachable.

See also ​