Quickstart · Test environment

Accept your first payment.

Add Hamro Pay’s hosted checkout to your website or app. Your server creates the payment, your customer chooses how to pay, and your server confirms the result.

New to hosted payments?

Before you start

You’ll need a backend that can make HTTPS requests, a test merchant account, and pages to return customers to after checkout. Create a test merchant account.

Get your connection details first
Ask Hamro Pay for test credentials, the full Create Session and Get Transaction URLs and HTTP methods, and the checkout gateway URL. Full endpoint paths and backend HTTP methods are not specified in the integration reference. The examples below mark the configuration values you need to replace.

1 Set up your test account

Follow these steps to create and verify your test merchant, get your credentials, and reach the checkout endpoints.

Merchant Onboarding

1.1. Create and Verify Your Test Merchant Account

Register your merchant account through the UAT Merchant Portal to start your checkout integration.

Use verification OTP 000000
Step 2: Credentials & Webhook

1.2. Get Credentials and Configure Webhook

Once your merchant account is verified, navigate to:

You will find:

  • Client ID
  • Client Secret
  • Client API Key
  • Merchant ID
Hamro Pay Merchant Portal - Client Credentials

Configure your Webhook:

  1. Enter your Target Endpoint URL.
  2. Save the configuration.
  3. The Webhook Secret (merchantWebHookSigningSecret) will be generated/displayed after saving.
  4. Use this secret to verify webhook requests from Hamro Pay.
Hamro Pay Merchant Portal - Webhook Configuration
Security Warning: Keep your credentials and webhook secret secure. Do not expose them in frontend client-side code or public repositories.
Step 3: API Integration

1.3. Integrate Hamro Pay Checkout

Use the credentials obtained from the Merchant Portal and the following UAT endpoints to connect your backend and frontend:

Environment Variable UAT Value Action
BASE_URL https://uat-payclient.hamropatro.com/
GATEWAY_URL https://uat-checkout-pay.hamropatro.com/
Follow the Checkout API documentation to implement session creation, proceed forms, and signature validation.

Keep secret values on your server. Collect the credentials and UAT endpoints from the steps above into your backend’s environment configuration.

.env · server configuration
# .env — your server only; never commit this file
# Replace every REPLACE_ME value with your test configuration.
HAMRO_MERCHANT_ID=REPLACE_ME
HAMRO_CLIENT_ID=REPLACE_ME
HAMRO_API_KEY=REPLACE_ME
HAMRO_CLIENT_SECRET=REPLACE_ME
HAMRO_USER_SECRET=REPLACE_ME

# Obtain full URLs from Hamro Pay during test onboarding.
HAMRO_CREATE_SESSION_URL=REPLACE_ME
HAMRO_GET_TRANSACTION_URL=REPLACE_ME
HAMRO_GATEWAY_URL=REPLACE_ME

# Set these to pages in your application.
CHECKOUT_SUCCESS_URL=https://your-domain.example/payment/success
CHECKOUT_FAILURE_URL=https://your-domain.example/payment/failure
Ready when:
Your test merchant is verified and your server has its test credentials.

2 Create a payment session

Build a request from the order saved on your server. Set the amount in paisa, and give each order a unique merchantTxnId of no more than 25 characters. This example charges NPR 125.50 (12550 paisa).

Create Session · request body
{
  "merchantTxnId": "ORDER-1001",
  "merchantId": "YOUR_TEST_MERCHANT_ID",
  "transactionAmount": "12550",
  "failedRedirectionUrl": "https://your-domain.example/payment/failure",
  "successRedirectionUrl": "https://your-domain.example/payment/success",
  "remarks": "Order ORDER-1001"
}

Building a platform that hosts other merchants? Use the selling merchant’s ID and explore Payments for Platforms to allocate your platform’s share automatically.

Sign the request

A signature lets Hamro Pay verify your request. Join the five fields in the order shown below, sign them with your client secret using HMAC-SHA512, and encode the result as Base64.

signature
import { createHmac } from 'node:crypto';

export function signSession(request, clientId, clientApiKey, clientSecret) {
  const message = [
    request.merchantTxnId,
    request.transactionAmount,
    request.merchantId,
    clientId,
    clientApiKey,
  ].join(',');

  return createHmac('sha512', clientSecret)
    .update(message, 'utf8')
    .digest('base64');
}

// request is the exact JSON object you send to Create Session.
// Read the client id, api key and secret from your server environment.

Send the JSON body to your confirmed Create Session endpoint, using its confirmed HTTP method and these headers. Sign the values you actually send; don’t change the amount or field values after signing.

Create Session · request headers
Signature: YOUR_GENERATED_BASE64_SIGNATURE
Client-Id: YOUR_TEST_CLIENT_ID
Client-API-Key: YOUR_TEST_API_KEY
Content-Type: application/json
Keep payment creation on your server
Read prices from your own order records. Don’t trust an amount submitted by the browser, and don’t send your API key, client secret, or user secret to the browser.
Ready when:
You have a successful session response containing sessionId and merchantId. Save the order’s transaction ID for step 4.
See all request fields and the full response example

3 Send your customer to checkout

Use sessionId from the response in step 2, and compute the checkout token as a form signature. Pass only the checkout fields to your page, never the full session response.

checkout-fields.mjs · server only
import { createHmac } from 'node:crypto';

// Run on your server after a successful Create Session call.
// session is the parsed response from Hamro Pay.
export function checkoutFields(session, clientId, clientApiKey, clientSecret) {
  const tokenMessage = [
    session.merchantId,
    session.merchantTxnId,
    session.sessionId,
    session.transactionAmount,
    clientId,
    clientApiKey,
  ].join(',');

  const token = createHmac('sha512', clientSecret)
    .update(tokenMessage, 'utf8')
    .digest('base64');

  const fields = {
    merchant_id: session.merchantId,
    session_id: session.sessionId,
    token,
    merchant_transaction_id: session.merchantTxnId,
  };
  for (const [name, value] of Object.entries(fields)) {
    if (typeof value !== 'string' || value.length === 0) {
      throw new Error('Missing checkout field: ' + name);
    }
  }
  return fields;
}

// Render only these fields in the checkout form.
// Never serialize the full session response into the page.

The token is the form signature generated from merchant_id, merchant_transaction_id, session_id, transaction_amount, client_id, client_api_key using your client secret.

Render these fields in your checkout form. When the customer clicks the button, the browser submits the form to Hamro Pay’s checkout gateway.

checkout.html · server-rendered template
<!-- Template: replace these values on your server.
     HTML-escape every value before inserting it.
     Use only the checkout URL confirmed by Hamro Pay. -->
<form method="POST"
      action="{{ HAMRO_GATEWAY_URL }}"
      enctype="application/x-www-form-urlencoded">
  <input type="hidden" name="merchant_id"
         value="{{ merchant_id }}">
  <input type="hidden" name="session_id"
         value="{{ session_id }}">
  <input type="hidden" name="token"
         value="{{ token }}">
  <input type="hidden" name="merchant_transaction_id"
         value="{{ merchant_transaction_id }}">
  <button type="submit">Pay with Hamro Pay</button>
</form>

The double braces are template variables. Replace them using your backend’s HTML template engine and its HTML escaping. Keep merchant_transaction_id identical to the merchantTxnId used to create the session.

Ready when:
Clicking “Pay with Hamro Pay” opens the test checkout for the correct order and amount.

4 Confirm payment before fulfilling the order

The return URL includes MerchantTxnId (capital M and T). Use it to look up your saved order. A success-page visit alone is not proof of payment.

Call your confirmed Get Transaction endpoint from your server with the following body. Generate a new signature in this order: merchantTxnId,merchantId,client_id,clientApiKey. Use the same HMAC-SHA512 and Base64 process, and your client secret.

Get Transaction · request body
{
  "merchantId": "YOUR_TEST_MERCHANT_ID",
  "merchantTxnId": "ORDER-1001"
}

Fulfill only when the server response reports COMPLETED and its transaction ID and amount match your saved order. Use merchantTransactionId from the response—the name differs from the request field.

verify-payment.mjs · server only
// Run on your server after calling Get Transaction.
// payment = Hamro Pay's response, not the browser's data.
// order = your saved order, loaded using its transaction ID.
export function isPaid(payment, order) {
  if (!payment || !order || typeof order.merchantTxnId !== 'string'
      || !order.merchantTxnId) return false;
  if (!['number', 'string'].includes(typeof payment.amount)
      || !['number', 'string'].includes(typeof order.amount)) return false;
  const amount = Number(payment.amount);
  const expected = Number(order.amount);
  return payment.status === 'COMPLETED'
    && payment.merchantTransactionId === order.merchantTxnId
    && Number.isFinite(amount)
    && amount > 0
    && Number.isFinite(expected)
    && amount === expected;
}

// Fulfill only after isPaid returns true, and save the paid state
// atomically so repeated checks or webhooks cannot fulfill twice.

Keep PENDING or PROCESSING orders unpaid while awaiting confirmation. Show a retry option for FAILED. Return-page checks work when the customer returns; add verified webhooks to handle customers who close the page.

Ready when:
A verified test payment marks the correct order as paid exactly once.

Test the whole flow

Create a test user, complete the checkout with the test credentials below, then run through these cases before switching to live credentials.

Step 4: End-to-End Testing

Test Your Checkout Integration

Perform end-to-end Checkout transactions to ensure your backend and webhooks respond correctly:

Use these test credentials to complete the checkout:
Hamro Pay number 9841414141
T-PIN 0000
OTP 000000
Test the complete lifecycle scenarios:
  • Successful Payment Flow Verify browser redirect and webhook payload with status: COMPLETED.
  • Failed / Cancelled Flow Verify error handling when transaction is aborted by user.
  • Pending / Timeout Flow Verify polling with Get Transaction API or asynchronous webhook delivery.

Run through these cases

  • Successful payment: the correct amount is shown and your server confirms the order as paid.
  • Failed or canceled payment: the customer can try again and the order stays unpaid.
  • Pending payment: the order stays unpaid until a later server check confirms completion.
  • Repeated return or notification: the order is fulfilled only once.
  • Changed transaction ID or amount: your server rejects the mismatch.
  • Customer closes checkout: verified webhooks or server reconciliation still update the order.

Ready for real payments?

Ask Hamro Pay to approve live onboarding and confirm your live credentials, endpoints, payment methods, and transaction rate. Replace test settings, verify your production return URLs and webhook, and confirm a live payment with your team.

Contact the integration team

Need field details?

They’re all in the API reference.

Next: API reference

Hamro Pay Support

Grievance officer

Follow Us

© 2026 HamroPay. All Rights Reserved.