Integration of Himalayan Bank(HBL) Payment Gateway
In this post, I'll walk you through integrating the HBL payment gateway from scratch. Recently, I worked on a project built with React and Node.js, where I was tasked with this integration. If you've ever tried to get technical support from Nepali banks, you know how challenging it can be. That's why I decided to write this guide—so others in similar situations can find the help they need. Let's dive in!
Pre-requisite
- You as a merchant, need to ask Payment Gateway Id/ Merchant Id with the bank.
- You as a merchant, need to ask Merchant Secret Key with the bank.
- Ask bank to setup your frontend URL(URL where payer is redirected after payment is successful/failure.)
- Ask bank to setup your backend URL(Endpoint where you will receive the transaction response when payment is success/failure.)
Initiating request
For initiating the payment request, you need to integrate this form on your website:
<form method="post" action="https://hblpgw.2c2p.com/HBLPGW/Payment/Payment/Payment">
<input type="text" id="paymentGatewayID" name="paymentGatewayID" value="234" />
<input type="text" id="invoiceNo" name="invoiceNo" value="00000001234567890333" />
<input type="text" id="productDesc" name="productDesc" value="Test Product" />
<input type="text" id="amount" name="amount" value="000000010000" />
<input type="text" id="currencyCode" name="currencyCode" value="524" />
<input type="text" id="userDefined1" name="userDefined1" value="custom data" />
<input type="text" id="nonSecure" name="nonSecure" value="Y" />
<input type="text" id="hashValue" name="hashValue" value="94E8E91C29E73B9648011FADBAE19849B520B24B" />
</form>
Notes:
- Replace paymentGatewayID with your specific payment gateway ID.
- Invoice number must be of 20 digits. So, pad 0’s on left to if invoice number is less than 20 digits.
- Amount must be of 12 digits. So, pad 0’s on left if amount is less than 20 digits. Amount can’t be in decimal. If you need to make payment of Rs. 1.33, convert it into paisa i.e. 133 and pad 9 0’s on left to make amount as 000000000133.
- Currency can only be 524 if NPR or 840 if USD.
- Userdefined values are optional.
- nonSecure is either “N” for No or “Y” for Yes.
- hashValue is optional while making request. Refer below Generating Hash section to know how hash is generated.
Double check on these notes, a simple mistake might lead to errors that are not simply meaningful. A most common error is,
Upon successful form submission, it should redirect us to a page that asks for payment card details:
So the every requests after this are handled by HBL Payment server and user is redirected to the Frontend URL(which we need to ask bank to setup for us).
Capturing backend response
After the transaction is completed, the payer is redirected to the frontend URL, and simultaneously, we receive a response on the backend endpoint. This is where we handle all the post-payment processing.
Sample response from Payment gateway looks like this:
{
paymentGatewayID: '<Your payment gateway id>',
respCode: '00',
fraudCode: '00',
Pan: '123456******1234',
Amount: '000000000133',
invoiceNo: '00000000000000000089',
tranRef: '123456',
approvalCode: '123456',
Eci: '12',
dateTime: '20210805163332',
Status: 'RS',
failReason: 'Approved',
userDefined1: '',
userDefined2: '',
userDefined3: '',
userDefined4: '',
userDefined5: '',
noteToMerchant: '',
hashValue: '0E85FA8AE8F2FF60049D12C83023CDD3533EA817'
}
The first critical step is to verify the response hash to ensure the response is legitimate. This step can be tricky, especially if you overlook even the smallest details.
Generating Hash
In order to have data integrity and to identify the correct source of the request and response, the merchant needs to send hash value together in the request and HBL PGW returns the hash value in the response. The hash value is computed using the SHA1 algorithm with merchant secret key (provided by HBL to merchant).
The process for generating request hash(the hash value that we pass in initiating the payment request form) and generating response hash(the hash value that we generate from the response parameter to verify with incoming response hash value) is almost the same. The only difference is how we generate the signature string.
Type Signature String Payment Request merchantID + invoiceNumber +amount + currencyCode + nonSecure Payment Response paymentGatewayID + respCode + fraudCode + Pan + Amount + invoiceNo + tranRef + approvalCode + Eci + dateTime + Status
Type | Signature string |
---|---|
Payment Request | merchantID + invoiceNumber +amount + currencyCode + nonSecure |
Payment Response | paymentGatewayID + respCode + fraudCode + Pan + Amount + invoiceNo + tranRef + approvalCode + Eci + dateTime + Status |
Code snippet for generating response hash
import { createHmac } from "crypto";
function generateResponseHash(responseHashParams: HBLResponse) {
let signatureString = String(responseHashParams.paymentGatewayID).concat(
responseHashParams.respCode,
responseHashParams.fraudCode,
responseHashParams.Pan,
responseHashParams.Amount,
responseHashParams.invoiceNo,
responseHashParams.tranRef,
responseHashParams.approvalCode,
responseHashParams.Eci,
responseHashParams.dateTime,
responseHashParams.Status
);
let signedData = createHmac("sha1", process.env.MERCHANT_SECRET_KEY)
.update(signatureString)
.digest("hex")
.toUpperCase();
return signedData;
}
The hash returned by this method must match with the hash that is received from the response to verify that the transaction is not tampered.
Systems evolve over time, please refer to the documentation provided by HBL for more information.