Node.js sample · UAT

A real checkout flow. A shop you can run.

Start with a small T-shirt store. Add an item to your bag, pay on Hamro Pay's real hosted checkout page with a test account, and follow the code from session to confirmation. It runs against the UAT environment, so no money moves.

UAT credentials are required
This sample exercises the real checkout protocol end to end, so it will not start without test credentials. Installing takes about two minutes; getting your UAT merchant credentials takes a little longer. There is no offline demo mode and no live-payment mode.

1 Install the store

Install Node.js 22.13 or newer, which includes npm. On macOS, Linux, or Windows with WSL, paste these commands into your terminal:

Terminal · install
curl -fsSL https://raw.githubusercontent.com/hamropatro/sample-store/main/install.sh | sh
cd sample-store
Nothing to provision
No database and no third-party runtime packages. The store runs on Node's standard library and keeps its orders in a local JSON file.

The installer downloads release v1.0.0 into a new sample-store directory and creates your local .env. It refuses to overwrite an existing directory, and it needs curl and tar.

Install with Git, including Windows PowerShell

Terminal · clone the repository
git clone https://github.com/hamropatro/sample-store.git
cd sample-store
npm run setup

2 Connect your test merchant

Create a test merchant in the UAT Merchant Portal and complete its business verification; the registration OTP is 000000. Copy Merchant ID, Client ID, Client API Key, and Client Secret from the Client Credentials page into the .env that setup created:

.env · the four required values
HOST=127.0.0.1
PORT=3000
APP_URL=http://localhost:3000

HAMRO_MERCHANT_ID=your-test-selling-merchant-id
HAMRO_CLIENT_ID=your-test-client-id
HAMRO_API_KEY=your-test-api-key
HAMRO_CLIENT_SECRET=your-test-client-secret

That is everything required. Endpoint paths are fixed by the API, so the sample only needs base URLs, and it already defaults to UAT:

Setting Default Used for
HAMRO_API_BASE_URL https://uat-payclient.hamropatro.com/ Create Session and Get Transaction
HAMRO_GATEWAY_BASE_URL https://uat-checkout-pay.hamropatro.com/ The hosted checkout page your form posts to

3 Prove the credentials work

Before opening the store, check the whole signed path in one command:

Terminal · credential preflight
npm run preflight

This creates one NPR 10 UAT session and prints the exact form your browser would post. It moves no money and opens no page. A sessionId in the output means your credentials, signature, and endpoints are all correct.

UAT resets connections under bursts
Rapid repeated calls have the TCP connection closed rather than returning an HTTP error. The adapter reports this as “Could not reach Hamro Pay … UND_ERR_SOCKET”. Wait a moment and retry before assuming your credentials are wrong.

4 Pay with a test account

Terminal · start the store
npm start

Open your APP_URL, choose a T-shirt size, add it to your bag, and check out. Continue to Hamro Pay posts a signed form to the hosted checkout page and your browser lands on the real gateway, exactly as in production. Pay with the UAT test account:

Hamro Pay number
9841414141
T-PIN
0000
OTP
000000

The OTP you enter at checkout decides the result, so you can test every outcome:

OTP 000000
COMPLETED
OTP 111111
PENDING
OTP 222222
FAILED

Hamro Pay redirects back to APP_URL/payment/success or /payment/failure with ?MerchantTxnId=…. Both pages are informational only: the server calls Get Transaction and decides for itself.

  • Paid (OTP 000000): Get Transaction returns COMPLETED and the transaction ID and rupee amount match the saved order.
  • Pending (OTP 111111): the order stays unpaid. An unfinished transaction reports amount 0, which is treated as pending rather than a mismatch.
  • Failed (OTP 222222) or cancelled: the order stays unpaid, and the return page offers Check payment status again.
  • Repeated confirmation: a webhook for an already-paid order leaves the paid timestamp unchanged.

Landing on the success URL, or editing the query string, cannot confirm payment. The server prices the order from its own catalog, so changing an amount in the browser cannot change the total.

Use a public HTTPS origin for a realistic run
http://localhost:3000 is fine for a first look, but Hamro Pay needs to reach APP_URL for the redirect to work in every case, and for product images to render on its page. Run a development tunnel to port 3000, set APP_URL to its HTTPS origin, restart, and always open the shop at that exact origin — the one holding the session cookie.

5 Receive payment updates by webhook

A customer may close the checkout tab before the return redirect fires, so keep both paths. Expose the store through a public HTTPS development tunnel, set APP_URL to that origin, and register https://your-tunnel.example/api/webhooks/hamropay on the portal's Webhook Config page. Saving generates the signing secret:

.env · enable the webhook endpoint
HAMRO_WEBHOOK_SECRET=your-merchant-webhook-signing-secret

Restart afterwards. Without the secret the endpoint stays disabled. It verifies the Signature header in constant time, then checks that the merchant, transaction ID, and amount match the saved order before anything is marked paid.

Read the webhook reference for the payload and signing format.

Try Payments for Platforms

Keep the selling merchant in HAMRO_MERCHANT_ID. Add your platform merchant plus exactly one of the two commission amounts:

.env · optional commission
HAMRO_PLATFORM_MERCHANT_ID=your-test-platform-merchant-id
HAMRO_COMMISSION_PERCENTAGE=3
# or, instead of a percentage, a flat amount in rupees:
# HAMRO_COMMISSION_AMOUNT=25

For a NPR 1,200 shirt, 3% allocates NPR 36 to the platform and NPR 1,164 to the seller, before applicable processing fees or adjustments. Hamro Pay handles the allocation; the sample transfers nothing itself. Ask Hamro Pay to enable the arrangement for both test merchants, and leave all three settings empty for ordinary merchant checkout.

Explore Payments for Platforms

Make it your own

Each layer has one job, so you can read the part you need and ignore the rest.

  • src/hamropay/ — The provider adapter — the only code that talks to Hamro Pay. Signing, the signed POST, Create Session, Get Transaction, and webhook verification.
  • src/services/ — Payment decisions, independent of HTTP. Only payment-service.mjs may mark an order PAID, and only from an answer Hamro Pay gave it.
  • src/web/ — The HTTP layer — route table, session cookie, CSRF, rate limiting, and the server-rendered hand-off page. No payment logic lives here.
  • src/config.mjs — The only reader of process.env. Turns environment variables into one validated config object, so a credential has a single source.
  • src/catalog.mjs — Products and trusted prices. Changing an amount in the browser cannot change the order total.
  • public/ — Storefront markup, styles, and the return-page script. Safe to restyle without touching payment code.
Terminal · development and checks
npm run dev        # restart on file changes
npm test           # full payment journey, signatures, webhooks, persistence
npm run check      # syntax check every source file
npm run preflight  # prove your sandbox credentials still work

The test suite walks a full payment — checkout, hand-off form, gateway, redirect, verification, webhook — against a stand-in gateway that rejects tampered tokens, expired sessions, and replays. UAT HTTP calls are mocked, so the tests never charge money. Logs are structured and leveled (LOG_LEVEL, LOG_FORMAT=json), with signatures, tokens, and secrets redacted by key name before formatting.

Orders are saved in the local .data directory. This is a single-process learning sample with no inventory, shipping, taxes, refunds, or fulfillment, and no live-payment mode. For a real shop, replace the JSON store with a transactional database, add reconciliation and monitoring, and validate the complete flow with Hamro Pay. Keep .env and .data/ private; never commit them.

Need a different port, a custom installation directory, or help with configuration? Read the full README and troubleshooting guide.

Hamro Pay Support

Grievance officer

Follow Us

© 2026 HamroPay. All Rights Reserved.