# Hamro Pay Checkout — Developer Documentation (full text for LLMs) > Plain-Markdown copy of the Hamro Pay Checkout developer docs at https://hamropay.com.np/checkout/developer/ . > The web pages are the source of truth. This file restates them without changing API facts. > Sections marked "Notes for AI assistants" are additions that point out easy mistakes and > things the docs do not specify. Each note says where it comes from. Nothing here is guessed: > if a fact is not documented, it is listed as not documented. Pages: - How checkout works: https://hamropay.com.np/checkout/developer/how-it-works/ - Payments for Platforms: https://hamropay.com.np/checkout/developer/platforms/ - Checkout quickstart: https://hamropay.com.np/checkout/developer/quickstart/ - Node.js sample store: https://hamropay.com.np/checkout/developer/sample-store/ - API reference: https://hamropay.com.np/checkout/developer/reference/ - Sample store source: https://github.com/hamropatro/sample-store --- ## 1. Overview Hamro Pay Checkout is a hosted checkout. The customer starts on the merchant's website and pays on Hamro Pay's hosted payment page. The merchant's server creates the session and confirms the payment before fulfilling the order. Participants: - Your website (customer's browser): shows the order and submits the checkout form. - Your server (merchant backend): creates signed sessions, keeps credentials private, checks payments against saved orders. - Hamro Pay API (payment service): creates payment sessions, provides transaction status, sends configured webhook updates. - Hosted checkout (payment page): the customer chooses a payment method and completes the payment. Lifecycle: 1. Create the session. Your server reads the saved order, signs a Create Session request and sends it to Hamro Pay. The API returns `sessionId` and `merchantId`. Your server then generates the checkout `token` with its client secret and gives the browser only the checkout fields. 2. Open the payment page. The browser sends a `POST` form to the checkout gateway with the merchant ID, session ID, checkout token and the order's transaction ID. 3. Bring the customer back. Hamro Pay redirects to the `successRedirectionUrl` or `failedRedirectionUrl` supplied in Create Session, appending `?MerchantTxnId=...`. A return to the success page is not proof of payment. 4. Verify, then fulfill. Your server calls Get Transaction, checks for `COMPLETED`, and matches the transaction ID and amount to the saved order. Mark the order paid and fulfill it once. Keep pending, processing or failed orders unpaid. Webhooks arrive independently of the browser redirect, may arrive before or after the customer returns, and may repeat. Verify the signature, match the payment to the saved order, fulfill only once. --- ## 2. UAT environment setup All test credentials come from the self-service UAT Merchant Portal. You do not need to contact Hamro Pay for test credentials. 1. Create and verify a test merchant: sign up at https://pay-sandbox.hamropatro.com/signup (existing accounts log in at https://pay-sandbox.hamropatro.com/) - Registration verification OTP: `000000` 2. Get credentials: UAT Merchant Portal → Client Credentials — https://pay-sandbox.hamropatro.com/client-credentials - Client ID - Client Secret - Client API Key - Merchant ID 3. Configure the webhook: UAT Merchant Portal → Configuration → Webhook — https://pay-sandbox.hamropatro.com/configuration - Enter your Target Endpoint URL and save. - The webhook secret (`merchantWebHookSigningSecret`) is generated/displayed after saving. 4. UAT endpoints: | Variable | UAT value | |---|---| | `API_BASE_URL` | `https://uat-payclient.hamropatro.com/` | | `GATEWAY_URL` | `https://uat-checkout-pay.hamropatro.com/` | Full UAT URLs: - Create Session: `POST https://uat-payclient.hamropatro.com/v1/checkout/sessionId` - Get Transaction: `POST https://uat-payclient.hamropatro.com/v1/checkout/transaction` - Checkout gateway (browser form POST): `https://uat-checkout-pay.hamropatro.com/api/checkout` 5. Test customer credentials for completing a checkout: | Field | Value | |---|---| | Hamro Pay number | `9841414141` | | T-PIN | `0000` | | OTP | `000000` | The OTP entered at checkout decides the test transaction's result: | Checkout OTP | Resulting status | |---|---| | `000000` | `COMPLETED` (successful payment) | | `111111` | `PENDING` | | `222222` | `FAILED` | Going live: ask Hamro Pay to approve live onboarding and confirm your live credentials, endpoints, payment methods and transaction rate. Contact: https://hamropay.com.np/more/contactUs Example server environment: ```bash # Copy these from UAT Merchant Portal → Client Credentials HAMRO_MERCHANT_ID=REPLACE_ME HAMRO_CLIENT_ID=REPLACE_ME HAMRO_API_KEY=REPLACE_ME HAMRO_CLIENT_SECRET=REPLACE_ME # Generated when you save your webhook URL in UAT Merchant Portal → Configuration → Webhook HAMRO_WEBHOOK_SECRET=REPLACE_ME HAMRO_CREATE_SESSION_URL=https://uat-payclient.hamropatro.com/v1/checkout/sessionId HAMRO_GET_TRANSACTION_URL=https://uat-payclient.hamropatro.com/v1/checkout/transaction HAMRO_GATEWAY_URL=https://uat-checkout-pay.hamropatro.com/api/checkout ``` --- ## 3. API reference ### 3.1 Headers Every Hamro Pay API request must include these headers: | Header | Meaning | Dummy value | |---|---|---| | `Signature` | Base64 HMAC-SHA512 signature. Each API section defines the fields. | `base64stringrepresentation==` | | `Client-Id` | Unique id for your merchant account. From UAT Merchant Portal → Client Credentials. | `client@123` | | `Client-API-Key` | Key to access the checkout API. From UAT Merchant Portal → Client Credentials. | `merchant-api-key-test` | ### 3.2 Signature generation - Signature string = the values of the listed fields, in the listed order, joined with `,`. - Signature = `Base64( HMAC-SHA512( signature_string, client_secret ) )`. - The client secret is shown in UAT Merchant Portal → Client Credentials and is shared ONLY between the client and the Hamro Pay Checkout API. Keep it on your backend. ``` client_secret = 'abcdefg' signature_message_string = field1 + ',' + field2 + ',' + field3 + ... fieldn final_signature_string = toBase64( HmacSHA512Digest(signature_message_string, client_secret) ) ``` ```java public static String signHMAC(String message, String secret) throws Exception { Mac mac = Mac.getInstance("HmacSHA512"); mac.init(new SecretKeySpec(secret.getBytes(), "HmacSHA512")); return Base64.getEncoder().encodeToString(mac.doFinal(message.getBytes("UTF-8"))); } ``` ```javascript const crypto = require('crypto'); function signHMAC(message, secret) { return crypto.createHmac('sha512', secret).update(message, 'utf8').digest('base64'); } ``` ```php | Extra data; returned in the webhook. | | `clientCommissionConfig` | JSON [OPTIONAL] | Platform commission, see below. | `clientCommissionConfig` (provide only one of `commissionAmount` or `commissionPercentage`): | Field | Type | Description | |---|---|---| | `commissionMerchantId` | String | Commission-receiving merchant ID | | `commissionAmount` | Double | Commission amount | | `commissionPercentage` | Double | Commission percentage (`3` means 3%) | Product list item: ```json { "name": "shirt", "imageUrl": "https://testUrl.jpg", "description": "This is shirt", "price": 99.99, "quantity": 1 } ``` Response fields: | Field | Type | Description | |---|---|---| | `sessionId` | String | UUID | | `merchantId` | String | Client's Hamro Pay id | Success sample: ```json // Request { "merchantTxnId": "ORDER-1001", "merchantId": "PN_-Nd99TBnAlBjCgl8ef_b", "transactionAmount": "1000", "failedRedirectionUrl": "https://test.com/payment/", "successRedirectionUrl": "https://test.com/payment/", "productList": [ { "name": "shirt", "imageUrl": "https://testUrl.jpg", "description": "This is shirt", "price": 10, "quantity": 1 } ] } // Response 200 OK { "sessionId": "ca8f7b70-b9c9-11ee-8611-0a73743c8233", "merchantId": "PN_-Nd99TBnAlBjCgl8ef_b" } ``` Error samples (response body shape is `{ "code", "message", "details" }`): | Case | Response | |---|---| | Empty `merchantTxnId` | `{"code": 3, "message": "Merchant Txn Id is required", "details": []}` | | Unknown `merchantId` | `{"code": 5, "message": "Merchant doesn't exist", "details": []}` | | Amount below Rs.10 | `{"code": 3, "message": "You can only transfer amount more than or equals to Rs. 10", "details": []}` | ### 3.4 Checkout Proceed (browser form to the gateway) - `POST {{GATEWAY_URL}}/api/checkout`, `enctype="application/x-www-form-urlencoded"` - Intended API user: merchant frontend (browser form). The response is a redirect to the Hamro Pay checkout page. - Build the params on your backend, because the token needs the client secret. Send only the params to the browser. Form params: ``` merchant_id Your merchant id session_id sessionId from Create Session token see below merchant_transaction_id Your transaction ID (≤ 25 chars), same as merchantTxnId remarks Remarks (up to 250 chars) phone_number Hamro Pay user's phone number if available [OPTIONAL] ``` Token = signature (same algorithm and same client secret) over these fields, in order: 1. `merchant_id` 2. `merchant_transaction_id` 3. `session_id` 4. `transaction_amount` 5. `client_id` 6. `client_api_key` ```html
``` ```php $request['merchantId'], 'session_id' => $session['sessionId'], 'token' => base64_encode(hash_hmac('sha512', $tokenMessage, $clientSecret, true)), 'merchant_transaction_id' => $request['merchantTxnId'], ]; } ``` ### 3.5 Get Transaction API - `POST {{API_BASE_URL}}/v1/checkout/transaction` - Intended API user: merchant backend - Headers: as in 3.1 Signature fields, in order: 1. `merchantTxnId` 2. `merchantId` 3. `client_id` 4. `clientApiKey` Request: | Field | Type | Description | |---|---|---| | `merchantId` * | String | Merchant id | | `merchantTxnId` * | String | Merchant transaction ID from previous requests | Response: | Field | Type | Description | |---|---|---| | `merchantTransactionId` | String | Merchant transaction ID | | `status` | String | PENDING, PROCESSING, FAILED, COMPLETED | | `amount` | Double | Amount in RUPEES | | `remarks` | String | Remarks of the transaction | | `message` | String | Message about the transaction | Samples: ```json {"merchantTransactionId": "erftycnmiim", "trackingId": "", "status": "NOT_INITIATED", "amount": 0, "remarks": "", "message": "TRANSACTION NOT INITIATED YET"} {"merchantTransactionId": "v23o1lj5q4g", "trackingId": "ed72b710-ba8c-11ee-af91-aa6bf67f81d3", "status": "FAILED", "amount": 23.77, "remarks": "This is remarks", "message": "SUCCESS"} {"merchantTransactionId": "bdg68smvsyg", "trackingId": "9d7ebc60-ba76-11ee-a642-ba34db130c51", "status": "COMPLETED", "amount": 14.5, "remarks": "This is remarks", "message": "SUCCESS"} {"merchantTransactionId": "bdg68asdgghfgh", "trackingId": "9d7ebc60-ba76-11ee-a642-ba34db130c51", "status": "PENDING", "amount": 145, "remarks": "This is remarks", "message": "PENDING"} ``` ### 3.6 Success / failed redirection After the transaction Hamro Pay redirects to the URL given in Create Session, appending `MerchantTxnId`: ``` https://something.com/success?MerchantTxnId=123213 https://something.com/failure?MerchantTxnId=123213 ``` Use `MerchantTxnId` to look up the order, then confirm with Get Transaction from your server. ### 3.7 Webhook (optional) Set the webhook URL in UAT Merchant Portal → Configuration → Webhook. Hamro Pay sends a POST with a JSON body to that URL when a checkout transaction succeeds or fails. Saving the URL generates `merchantWebHookSigningSecret`, which is used only to validate webhook requests. Body: | Field | Type | Description | |---|---|---| | `merchantTxnId` | String | Your transaction ID; can be used with `merchantId` to fetch the transaction | | `merchantId` | String | For reconciliation | | `amount` | double | Transaction amount in RUPEES | | `status` | String | PENDING, PROCESSING, FAILED, COMPLETED | | `metadata` | map