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.
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:
curl -fsSL https://raw.githubusercontent.com/hamropatro/sample-store/main/install.sh | sh
cd sample-storeThe 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
git clone https://github.com/hamropatro/sample-store.git
cd sample-store
npm run setup2 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:
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-secretThat 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:
npm run preflightThis 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.
4 Pay with a test account
npm startOpen 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:
The OTP you enter at checkout decides the result, so you can test every outcome:
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.
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:
HAMRO_WEBHOOK_SECRET=your-merchant-webhook-signing-secretRestart 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:
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=25For 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 PlatformsMake 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.
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 workThe 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.
Company
Code of Conduct
Hamro Pay Support
Chat Support: (24x7)
Call support: (6am-10pm)
Grievance officer
Follow Us
© 2026 HamroPay. All Rights Reserved.