Checkout API
PayHere Checkout API lets you integrate PayHere with your website, web application or any other application in code level. It offers a simple HTML Form based POST API to initiate a payment request and redirect your customer to PayHere Payment Gateway to securely process the payment. Once the payment is processed it notifies your given URL (notify_url
) about the payment status by a server callback with a checksum to verify the response params. You can use those response params & checksum to verify and update your system, based on the payment status.
Prerequisites
You need the following things ready to integrate your website with PayHere Checkout API.
- Merchant ID
- You can find your Merchant ID from Side Menu > Integrations of your PayHere Account.
- Merchant Secret
- You can generate a Merchant Secret for your domain/app by following below steps.
- Go to Side Menu > Integrations section of your PayHere Account
- Click 'Add Domain/App' > Enter your top level domain or App package name > Click 'Request to Allow'
- Wait for the approval for your domain/app (This will take up to 24 hours)
- Copy the Merchant Secret shown in front of your domain/app
- You can generate a Merchant Secret for your domain/app by following below steps.
Attention: Please note that Merchant ID is unique to your PayHere account, but Merchant Secret is specific to your integrating domain/app. Therefore, you need to add your new domains/apps & get a new Merchant Secret every time you're integrating PayHere on a new domain/app.
Integration
You need to complete the following 3 steps in order to fully integrate your website with PayHere Checkout API.
1. Redirecting Customer to PayHere Payment Gateway
You can a simple HTML Form to submit the below POST params to PayHere Payment Gateway. When the form is submitted, your customer will be securely redirected to the PayHere Payment Gateway & the customer can then enter the credentials (Card No/CVV) & securely process the payment there.
Action URL
Live - https://www.payhere.lk/pay/checkout
Sandbox - https://sandbox.payhere.lk/pay/checkout
Required POST Parameters
merchant_id
- PayHere Merchant IDreturn_url
- URL to redirect users when payment is approvedcancel_url
- URL to redirect users when user cancel the paymentnotify_url
- URL to callback the status of the payment (Needs to be a URL accessible on a public IP/domain)first_name
- Customer’s First Namelast_name
- Customer’s Last Nameemail
- Customer’s Emailphone
- Customer’s Phone Noaddress
- Customer’s Address Line1 + Line2city
- Customer’s Citycountry
- Customer’s Countryorder_id
- Order ID generated by the merchantitems
- Item title or Order/Invoice numbercurrency
- Currency Code (LKR/USD)amount
- Total Payment Amounthash
- Generated hash value as mentioned below (*Required from 2023-01-16)
Generating 'hash' Value
You can generate the hash
value using the merchant_id
, order_id
, amount
, currency
and the merchant_secret
.
hash = to_upper_case(md5(merchant_id + order_id + amount + currency + to_upper_case(md5(merchant_secret))))
PHP Code sample for generating hash
value:
$hash = strtoupper(
md5(
$merchant_id .
$order_id .
number_format($amount, 2, '.', '') .
$currency .
strtoupper(md5($merchant_secret))
)
);
JavaScript Code sample for generating hash
value:
npm install crypto-js
import md5 from 'crypto-js/md5';
let merchantSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
let merchantId = '2xxxxx';
let orderId = '12345';
let amount = 1000;
let hashedSecret = md5(merchantSecret).toString().toUpperCase();
let amountFormated = parseFloat( amount ).toLocaleString( 'en-us', { minimumFractionDigits : 2 } ).replaceAll(',', '');
let currency = 'LKR';
let hash = md5(merchantId + orderId + amountFormated + currency + hashedSecret).toString().toUpperCase();
.NET Code sample for generating hash
value:
public class Program
{
public static void Main()
{
string merchantId = "2xxxxx";
string merchantSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string orderId = "12345";
double amount = 1000;
string hashedSecret = ComputeMD5(merchantSecret);
string amountFormated = amount.ToString("####0.00");
string currency = "LKR";
string hash = ComputeMD5(merchantId + orderId + amountFormated + currency + hashedSecret);
Console.WriteLine(hash);
}
static string ComputeMD5(string s)
{
StringBuilder sb = new StringBuilder();
using (MD5 md5 = MD5.Create())
{
byte[] hashValue = md5.ComputeHash(Encoding.UTF8.GetBytes(s));
foreach (byte b in hashValue)
{
sb.Append($"{b:X2}");
}
}
return sb.ToString();
}
}
Java Code sample for generating hash
value:
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
public static void main(String[] args) {
String merahantID = "2xxxxx";
String merchantSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String orderID = "12345";
double amount = 1000;
String currency = "LKR";
DecimalFormat df = new DecimalFormat("0.00");
String amountFormatted = df.format(amount);
String hash = getMd5(merahantID + orderID + amountFormatted + currency + getMd5(merchantSecret));
System.out.println("Generated Hash: " + hash);
}
public static String getMd5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
BigInteger no = new BigInteger(1, messageDigest);
String hashtext = no.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext.toUpperCase();
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
Attention:
Please note that the hash
parameter should not be generated in client-side since it will expose your merchant_secret
.
Optional POST Parameters
delivery_address
- Delivery Address Line1 + Line2delivery_city
- Delivery Citydelivery_country
- Delivery Countryitem_name_1
- Name of Item 1item_number_1
- Model number of Item 1amount_1
- Unit amount of Item 1quantity_1
- Quantity of Item 1item_name_2
- Name of Item 2item_number_2
- Model number of Item 2amount_2
- Unit amount of Item 2quantity_2
- Quantity of Item 2 (You can list rest of the items also like this)platform
- Referring Platformcustom_1
- Custom param 1 set by merchantcustom_2
- Custom param 2 set by merchant
HTML Form Code Sample
<html>
<body>
<form method="post" action="https://sandbox.payhere.lk/pay/checkout">
<input type="hidden" name="merchant_id" value="121XXXX"> <!-- Replace your Merchant ID -->
<input type="hidden" name="return_url" value="http://sample.com/return">
<input type="hidden" name="cancel_url" value="http://sample.com/cancel">
<input type="hidden" name="notify_url" value="http://sample.com/notify">
</br></br>Item Details</br>
<input type="text" name="order_id" value="ItemNo12345">
<input type="text" name="items" value="Door bell wireless">
<input type="text" name="currency" value="LKR">
<input type="text" name="amount" value="1000">
</br></br>Customer Details</br>
<input type="text" name="first_name" value="Saman">
<input type="text" name="last_name" value="Perera">
<input type="text" name="email" value="[email protected]">
<input type="text" name="phone" value="0771234567">
<input type="text" name="address" value="No.1, Galle Road">
<input type="text" name="city" value="Colombo">
<input type="hidden" name="country" value="Sri Lanka">
<input type="hidden" name="hash" value="098F6BCD4621D373CADE4E832627B4F6"> <!-- Replace with generated hash -->
<input type="submit" value="Buy Now">
</form>
</body>
</html>
2. Listening to Payment Notification
As soon as the payment is processed, PayHere notifies the payment status to the notify_url
you posted to the Checkout API as a server callback & redirects the customer back to your website to the return_url
. Payment notification will contain the following data as POST params, so you need to host a script on your notify_url
to fetch the following POST params & update your database accordingly.
POST params
merchant_id
- PayHere Merchant ID of the merchantorder_id
- Order ID sent by Merchant to Checkout pagepayment_id
- Unique Payment ID generated by PayHere for the processed paymentpayhere_amount
- Total Amount of the paymentpayhere_currency
- Currency code of the payment (LKR/USD/GBP/EUR/AUD)status_code
- Payment status code (2
,0
,-1
,-2
,-3
)md5sig
- Encrypted signature to verify the paymentcustom_1
- Custom param 1 sent by merchant to Checkout pagecustom_2
- Custom param 2 sent by merchant to Checkout pagemethod
- Payment method selected by the customer. (VISA
,MASTER
,AMEX
,EZCASH
,MCASH
,GENIE
,VISHWA
,PAYAPP
,HNB
,FRIMI
)status_message
- Message received from payment gateway which the customer tried to pay
If the customer made the payment by VISA
or MASTER
credit/debit card, following parameters will also be available.
card_holder_name
- Card Holder Namecard_no
- Masked card number (Ex:************4564
)card_expiry
- Card expiry in format MMYY (Ex:0122
)
Payment Status Codes
2
- success0
- pending-1
- canceled-2
- failed-3
- chargedback
Attention:
- You cannot test the payment notification by print/echo methods since
notify_url
never loads to the browser as it's a server callback. You can only test it by updating your database upon fetching the notification. - You cannot test the payment notification on localhost. You need to submit a publically accessible IP or domain based URL as your
notify_url
for PayHere to directly notify your server. - No payment status parameters are passed to the
return_url
when redirecting the customer back to your website. You need to update your database upon fetching payment status by your script onnotify_url
& then show the payment status to your customer in the page onreturn_url
by fetching the status from your database. - The request parameters are encoded in the
'application/x-www-form-urlencoded'
format, not'application/json'
.
3. Verifying the Payment Status
It is critical to verify the Payment Notification before taking any actions on the payment response. You can do the verification using the md5sig
checksum parameter that is generated & sent by PayHere along with the payment status params according to following logic.
md5sig = strtoupper(
md5 (
merchant_id +
order_id +
payhere_amount +
payhere_currency +
status_code +
strtoupper(md5(merchant_secret))
)
)
Once you receive the payment status parameters from PayHere, you can locally generate this checksum using the merchant_id
, order_id
, payhere_amount
, payhere_currency
& status_code
sent by the payment notification and the merchant_secret
you have locally. Your locally generated checksum should be equal to the md5sig
sent by PayHere if the payment notification is valid.
Code Sample (PHP)
You can host this script at your notify_url
.
<?php
$merchant_id = $_POST['merchant_id'];
$order_id = $_POST['order_id'];
$payhere_amount = $_POST['payhere_amount'];
$payhere_currency = $_POST['payhere_currency'];
$status_code = $_POST['status_code'];
$md5sig = $_POST['md5sig'];
$merchant_secret = 'XXXXXXXXXXXXX'; // Replace with your Merchant Secret
$local_md5sig = strtoupper(
md5(
$merchant_id .
$order_id .
$payhere_amount .
$payhere_currency .
$status_code .
strtoupper(md5($merchant_secret))
)
);
if (($local_md5sig === $md5sig) AND ($status_code == 2) ){
//TODO: Update your database as payment success
}
?>
Attention:
- Please make sure to consider the payment as successful only after the verfification, as it ensures that the payment notification received to your
notify_url
was genuinely initiated by PayHere, not by any other party. - If you do not implement this payment verification properly, there's a security risk of a third party sending a manipulated payment notification to your
notify_url
, falsly notifing that the payment is successful.