Recurring API

PayHere Recurring API lets you accept recurring payments from your customers so that the customer has to enter the card credentials only once & then his/her card will be automatically charged as per a time period you set & authorized by the customer.

It's a simple HTML Form based POST API (similar to PayHere Checkout API) which initiate a recurring payment request and redirect your customers to PayHere Payment Gateway to securely process & authorize the recurring payment. Once the first payment is processed & recurring payment is authorized, it notifies your given URL (notify_url) about the payment status with a checksum to verify, everytime your customer's card is charged. You can use those response params & checksum to verify and update your system, based on the payment status.

1. Redirecting Customer to PayHere Payment Gateway

Regardless of your scripting language, you can simply use an 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 / eZCash No / PIN) & securely process the payment there.

Action URL
Live    -
Sandbox -

Required POST Parameters
  • merchant_id - PayHere Merchant ID
  • return_url - URL to redirect users when success
  • cancel_url - URL to redirect users when cancelled
  • notify_url - URL to callback the status of the payment
  • first_name - Customer’s First Name
  • last_name - Customer’s Last Name
  • email - Customer’s Email
  • phone - Customer’s Phone No
  • address - Customer’s Address Line1 + Line2
  • city - Customer’s City
  • country - Customer’s Country
  • order_id - Order ID generated by the merchant
  • items - Item title or Order/Invoice number
  • currency - Currency Code (LKR/USD)
  • recurrence - Recurring Period (A number & a word separated by a space such as 2 Week, 1 Month, 6 Month, 1 Year, etc. Word can be ‘Week’, ‘Month’ or ‘Year’ in singular. Number can be any to define recurrent period with word.)
  • duration - Duration to charge ('Forever' if there's no time limitation. Otherwise a Number & a word separated by a space as 1 Month, 1 Year, 3 Year, ect. Word can be ‘Week’, ‘Month’, ‘Year’. Number should be compatible with the word in recurrence.)
  • amount - Total Payment Amount (eg. 1000.00)

Optional POST Parameters

  • delivery_address - Delivery Address Line1 + Line2
  • delivery_city - Delivery City
  • delivery_country - Delivery Country
  • item_name_1 - Name of Item 1
  • item_number_1 - Model number of Item 1
  • amount_1 - Unit amount of Item 1
  • quantity_1 - Quantity of Item 1
  • item_name_2 - Name of Item 2
  • item_number_2 - Model number of Item 2
  • amount_2 - Unit amount of Item 2
  • quantity_2 - Quantity of Item 2
    (You can list rest of the items also like this)
  • platform - Referring Platform
  • custom_1 - Custom param 1 set by merchant
  • custom_2 - Custom param 2 set by merchant
  • startup_fee - Additional fee or discount in 1st payment occurance
  • hash - Generated hash value to ensure extra security

If you need to add extra security when initializing the payment you can use hash parameter. Please note that this parameter should not be generated in client-side since it will expose your payhere_secret
The hash value can be generated in following manner

hash = to_upper_case( md5( merchant_id + order_id + payhere_amount + payhere_currency + to_upper_case( md5(payhere_secret) ) ) )

PHP Code sample for generating hash

md5sig = strtoupper (md5 ( merchant_id + order_id + payhere_amount + payhere_currency + strtoupper(md5(payhere_secret)) ) )

Code Sample
<form method="post" action="">   
    <input type="hidden" name="merchant_id" value="121XXXX">    <!-- Replace your Merchant ID -->
    <input type="hidden" name="return_url" value="">
    <input type="hidden" name="cancel_url" value="">
    <input type="hidden" name="notify_url" value="">  
    <br><br>Item Details<br>
    <input type="text" name="order_id" value="ItemNo12345">
    <input type="text" name="items" value="Door bell wireless"><br>
    <input type="text" name="currency" value="LKR">
    <input type="text" name="recurrence" value="1 Month">
    <input type="text" name="duration" value="Forever">
    <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"><br>
    <input type="text" name="email" value="">
    <input type="text" name="phone" value="0771234567"><br>
    <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"><br><br> 
    <input type="submit" value="Buy Now">   

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 merchant
  • order_id - Order ID sent by Merchant to Checkout page
  • payment_id - Unique Payment ID generated by PayHere for the processed payment
  • subscription_id - Unique Subscription ID generated by PayHere for the authorized subscription
  • payhere_amount - Total Amount of the payment
  • payhere_currency - Currency code of the payment (LKR/USD)
  • status_code - Payment status code (2, 0, -1, -2, -3)
  • md5sig - Encrypted signature to verify the payment
  • custom_1 - Custom param 1 sent by merchant to Checkout page
  • custom_2 - Custom param 2 sent by merchant to Checkout page
  • method - Payment method selected by the customer. (VISA, MASTER)
  • status_message - Message received from payment gateway which the customer tried to pay
  • recurring - Whether payment is a recurring payment (1:recurring, 0: not-recurring)
  • item_recurrence - How often it charges. eg. 1 Month
  • item_duration - How long it charges. eg. 1 Year
  • item_rec_status - Status of recurring subscription. (0: active, -1: cancelled, 1: completed)
  • item_rec_date_next - Date of next recurring installment (YYYY-MM-DD)
  • item_rec_install_paid - Number of successful recurring installments charged

    If the customer made the payment by VISA or MASTER credit/debit card, following parameters will also be available.
  • card_holder_name - Card Holder Name
  • card_no - Masked card number (Ex: ************4564)
  • card_expiry - Card expiry in format MMYY (Ex: 0122)

Payment Status Codes

  • 2 - success
  • 0 - pending
  • -1 - canceled
  • -2 - failed
  • -3 - chargedback

Please note that;

  • 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 on notify_url & then show the payment status to your customer in the page on return_url by fetching the status from your database.

3. Verifying the Payment Status

It is important 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(payhere_secret)) ) )

Once you receive the payment status params 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 payhere_secret you have locally (You can find your Merchant Secret in your PayHere Account's Settings page). Your locally generated checksum should equals to the md5sig sent by PayHere if the payment notification is valid.

Code Sample (PHP)

You can host this script at your notify_url.


$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 (Can be found on your PayHere account's Settings page)

$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


Recurring API - PayHere Knowledge Base

Still need help? Get in touch!
Last updated on 9th May 2019