# PayHere.lk — LLM Context File
> **Created by:** Theepan Kaja — https://theepankaja.website
> **Disclaimer:** This is NOT an official PayHere document. This file is an independently created community resource compiled from publicly available PayHere documentation for use by AI coding agents. PayHere™ is a trademark of PayHere (Pvt) Ltd. All product names, logos, and brands are property of their respective owners. For official documentation, visit https://support.payhere.lk
> PayHere is Sri Lanka's first Central Bank approved Aggregated Internet Payment Gateway.
> It enables businesses to accept online payments locally and globally from customers worldwide.
> This file provides comprehensive context for AI agents (Claude Code, Cursor, Copilot, Windsurf, Cline, etc.) to understand and assist with PayHere integrations.
---
## Table of Contents
- [Overview](#overview)
- [Key Concepts & Terminology](#key-concepts--terminology)
- [Authentication & Credentials](#authentication--credentials)
- [API Endpoints Reference](#api-endpoints-reference)
- [Checkout API](#checkout-api)
- [Recurring API](#recurring-api)
- [Preapproval API](#preapproval-api)
- [Charging API (Tokenization)](#charging-api-tokenization)
- [Retrieval API](#retrieval-api)
- [Subscription Manager API](#subscription-manager-api)
- [Refund API](#refund-api)
- [Authorize API](#authorize-api)
- [Capture API](#capture-api)
- [JavaScript SDK (payhere.js)](#javascript-sdk-payherejs)
- [Mobile SDKs](#mobile-sdks)
- [Shopping Cart Plugins](#shopping-cart-plugins)
- [PayHere Links & Buttons](#payhere-links--buttons)
- [Payment Notification (notify_url)](#payment-notification-notify_url)
- [Hash Generation](#hash-generation)
- [OAuth Authentication (Merchant APIs)](#oauth-authentication-merchant-apis)
- [Sandbox & Testing](#sandbox--testing)
- [Payment Limits, Fees & Plans](#payment-limits-fees--plans)
- [Supported Payment Methods & Currencies](#supported-payment-methods--currencies)
- [Application Process](#application-process)
- [Policy Requirements](#policy-requirements)
- [Onsite Checkout](#onsite-checkout)
- [Common Pitfalls & FAQs](#common-pitfalls--faqs)
- [Documentation Links](#documentation-links)
---
## Overview
PayHere provides multiple integration methods for accepting online payments:
1. **PayHere Links** — Accept payments without a website (shareable payment links)
2. **PayHere Buttons** — Embeddable payment buttons for websites
3. **Checkout API** — HTML form-based redirect to PayHere payment gateway
4. **Recurring API** — Subscription/recurring billing via HTML form redirect
5. **Preapproval API** — Tokenize customer cards for future automated charges
6. **Charging API** — Programmatically charge preapproved customers on demand
7. **Authorize API** — Hold on Card (authorize amount without capturing)
8. **Capture API** — Capture previously authorized payments
9. **Retrieval API** — Retrieve payment details programmatically
10. **Subscription Manager API** — View, retry, cancel subscriptions programmatically
11. **Refund API** — Programmatic refunds
12. **JavaScript SDK** — Onsite checkout popup (no redirect, iframe-based)
13. **Mobile SDKs** — Android, iOS, React Native, Flutter (in-app payments)
14. **Shopping Cart Plugins** — OpenCart, WooCommerce, Magento, Prestashop, Shopify, WHMCS, CS-Cart, Moodle, ShopHere
**Website:** https://www.payhere.lk
**Support/Docs:** https://support.payhere.lk
**Sandbox Portal:** https://sandbox.payhere.lk
**GitHub:** https://github.com/PayHereLK
**Support Email:** support@payhere.lk / techsupport@payhere.lk
---
## Key Concepts & Terminology
- **Merchant ID** — Unique identifier for your PayHere business account. Found at Side Menu > Integrations.
- **Merchant Secret** — Secret key tied to a specific domain/app. Generated per domain at Side Menu > Integrations > Add Domain/App.
- **notify_url** — Server-to-server callback URL where PayHere sends payment status. Must be publicly accessible (not localhost).
- **return_url** — URL where the customer is redirected after payment. No payment params are sent here.
- **cancel_url** — URL where the customer is redirected if they cancel.
- **order_id** — Merchant-defined unique reference for each transaction. PayHere does NOT validate uniqueness.
- **customer_token** — Encrypted token from Preapproval API, used to charge customers later via Charging API.
- **authorization_token** — Token from Authorize API, used to capture payment later via Capture API.
- **status_code** — Payment result: `2` = success, `0` = pending, `-1` = canceled, `-2` = failed/chargebacked, `-3` = charged back.
- **md5sig** — Checksum sent with payment notifications to verify authenticity.
- **Sandbox** — Test environment at sandbox.payhere.lk. No real payments processed.
- **Onsite Checkout** — Payment popup within your site (iframe-based, no redirect). Requires HTTPS.
- **Recurring Billing** — Automatic periodic charges (subscriptions) at fixed intervals.
- **Automated Charging (Tokenization)** — Preapprove customer cards, then charge on-demand any amount any time.
- **Hold on Card (Auth & Capture)** — Authorize (hold) an amount, then capture later (full or partial).
---
## Authentication & Credentials
### Merchant ID & Secret (for Checkout/Recurring/Preapproval/Authorize APIs + JS SDK + Mobile SDKs)
1. Find Merchant ID: PayHere Account > Side Menu > Integrations
2. Generate Merchant Secret:
- Go to Side Menu > Integrations
- Click "Add Domain/App"
- Enter your top-level domain or app package name
- Click "Request to Allow"
- Wait for approval (up to 24 hours)
- Copy the Merchant Secret shown for your domain/app
### OAuth (for Charging, Retrieval, Subscription Manager, Refund, Capture APIs)
These server-side APIs use OAuth Bearer tokens. See [OAuth Authentication](#oauth-authentication-merchant-apis) section below.
---
## API Endpoints Reference
### Base URLs
| Environment | Base URL |
|---|---|
| Live | `https://www.payhere.lk` |
| Sandbox | `https://sandbox.payhere.lk` |
### Endpoint Summary
| API | Method | Live Endpoint | Purpose |
|---|---|---|---|
| Checkout | POST | `/pay/checkout` | One-time payment redirect |
| Recurring | POST | `/pay/checkout` | Subscription payment redirect |
| Preapproval | POST | `/pay/preapprove` | Tokenize card for future charges |
| Authorize | POST | `/pay/authorize` | Hold on Card authorization |
| OAuth Token | POST | `/merchant/v1/oauth/token` | Get access token |
| Charging | POST | `/merchant/v1/payment/charge` | Charge preapproved customer |
| Retrieval | GET | `/merchant/v1/payment/search?order_id=XXX` | Get payment details |
| Subscription | GET | `/merchant/v1/subscription` | List subscriptions |
| Subscription Payments | GET | `/merchant/v1/subscription/{id}/payments` | List subscription payments |
| Subscription Retry | POST | `/merchant/v1/subscription/retry` | Retry failed subscription |
| Subscription Cancel | POST | `/merchant/v1/subscription/cancel` | Cancel subscription |
| Refund | POST | `/merchant/v1/payment/refund` | Refund a payment |
| Capture | POST | `/merchant/v1/payment/capture` | Capture authorized payment |
---
## Checkout API
**Purpose:** One-time payment via HTML form redirect.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/checkout-api
### Integration Steps
1. Submit HTML form with POST params to PayHere
2. Listen for payment notification at notify_url (server callback)
3. Verify the md5sig checksum and update your database
### Form Action URLs
- Live: `https://www.payhere.lk/pay/checkout`
- Sandbox: `https://sandbox.payhere.lk/pay/checkout`
### Required Parameters
| Parameter | Type | Description |
|---|---|---|
| `merchant_id` | string | Your Merchant ID |
| `return_url` | string | URL to redirect after payment |
| `cancel_url` | string | URL to redirect on cancel |
| `notify_url` | string | Server callback URL (public IP/domain required) |
| `order_id` | string | Unique order reference |
| `items` | string | Item description |
| `currency` | string | `LKR`, `USD`, `EUR`, `GBP`, `AUD` |
| `amount` | decimal | Payment amount (format: `1000.00`) |
| `first_name` | string | Customer first name |
| `last_name` | string | Customer last name |
| `email` | string | Customer email |
| `phone` | string | Customer phone |
| `address` | string | Customer address |
| `city` | string | Customer city |
| `country` | string | Customer country |
| `hash` | string | MD5 hash for verification (generated server-side) |
### Optional Parameters
| Parameter | Type | Description |
|---|---|---|
| `delivery_address` | string | Delivery address |
| `delivery_city` | string | Delivery city |
| `delivery_country` | string | Delivery country |
| `custom_1` | string | Custom field 1 |
| `custom_2` | string | Custom field 2 |
| `platform` | string | Platform identifier |
| `item_number_X` | string | Item number for item X (1-indexed) |
| `item_name_X` | string | Item name for item X |
| `quantity_X` | int | Quantity for item X |
| `amount_X` | decimal | Unit amount for item X |
### Example HTML Form
```html
```
---
## Recurring API
**Purpose:** Accept recurring/subscription payments. Customer enters card once, auto-charged at set intervals.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/recurring-api
### Form Action URLs
Same as Checkout API:
- Live: `https://www.payhere.lk/pay/checkout`
- Sandbox: `https://sandbox.payhere.lk/pay/checkout`
### Additional Required Parameters (on top of Checkout params)
| Parameter | Type | Description |
|---|---|---|
| `recurrence` | string | Charging frequency: `1 Month`, `2 Week`, `6 Month`, `1 Year`, etc. Word must be singular (`Week`, `Month`, `Year`). |
| `duration` | string | How long to charge: `Forever`, `1 Year`, `3 Month`, etc. Must be compatible with recurrence. |
### Optional Recurring Parameters
| Parameter | Type | Description |
|---|---|---|
| `startup_fee` | decimal | Extra amount added/subtracted from first charge (can be negative for discount) |
### Additional Notification Parameters for Recurring
| Parameter | Description |
|---|---|
| `recurring` | `1` if recurring payment, `0` if one-time |
| `item_rec_status` | Recurring status: `0`=active, `1`=completed, `-1`=cancelled, `-2`=failed, `-3`=pending retry |
| `item_rec_date_next` | Next scheduled charge date |
| `item_rec_install_paid` | Number of successful recurring installments charged |
---
## Preapproval API
**Purpose:** Tokenize customer's card for future on-demand charges via Charging API.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/preapproval-api
### Form Action URLs
- Live: `https://www.payhere.lk/pay/preapprove`
- Sandbox: `https://sandbox.payhere.lk/pay/preapprove`
### Key Differences from Checkout
- The `amount` field can be set to `0` (or minimum `10.00` LKR / `1.01` for other currencies) — this is just for card validation, not an actual charge (unless you want to charge as part of preapproval).
- The notification callback includes a `customer_token` — an encrypted token to store securely for future charges.
### Notification Response Includes
| Parameter | Description |
|---|---|
| `customer_token` | Encrypted token for the customer's card. Store this securely for use with Charging API. |
---
## Charging API (Tokenization)
**Purpose:** Programmatically charge preapproved customers on demand using their stored customer_token.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/charging-api
**Auth:** OAuth Bearer Token
### Endpoint
- Live: `POST https://www.payhere.lk/merchant/v1/payment/charge`
- Sandbox: `POST https://sandbox.payhere.lk/merchant/v1/payment/charge`
### Headers
```
Authorization: Bearer
Content-Type: application/json
```
### Request Body
```json
{
"type": "PAYMENT",
"order_id": "Order12345",
"items": "Taxi Hire 123",
"currency": "LKR",
"amount": 345.67,
"customer_token": "59AFEE022CC69CA39D325E1B59130862",
"custom_1": "custom parameter 1",
"custom_2": null,
"notify_url": "http://www.abc.com/notify",
"itemList": [
{
"name": "Item Name",
"number": "ITEM_001",
"quantity": 1,
"unit_amount": 345.67
}
]
}
```
### Type Field Values
- `PAYMENT` — Capture payment immediately (default)
- `AUTHORIZE` — Authorize (hold) amount, returns `authorization_token` for later capture
### Response
```json
{
"status": 1,
"msg": "Automatic payment charged successfully",
"data": {
"order_id": "Order12345",
"items": "Taxi Hire 123",
"currency": "LKR",
"amount": 345.67,
"custom_1": null,
"custom_2": null,
"payment_id": 320025021815,
"status_code": 2,
"status_message": "Successfully completed the payment.",
"md5sig": "A098FEBCC06293734641770555B4D569",
"authorization_token": null
}
}
```
### Status Codes
- `2` = Success
- `0` = Pending
- `-1` = Canceled
- `-2` = Failed/Chargebacked
### Live Environment Security
In live environment, this API can only be consumed from whitelisted domains/IPs. To enable access, email `support@payhere.lk` with your server IP address for whitelisting.
---
## Retrieval API
**Purpose:** Retrieve details of successful payments processed through your PayHere account.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/retrieval-api
**Auth:** OAuth Bearer Token
### Endpoint
- Live: `GET https://www.payhere.lk/merchant/v1/payment/search?order_id=`
- Sandbox: `GET https://sandbox.payhere.lk/merchant/v1/payment/search?order_id=`
### Headers
```
Authorization: Bearer
Content-Type: application/json
```
### Response
```json
{
"status": 1,
"msg": "Found 1 payments",
"data": [
{
"payment_id": 320025023469,
"order_id": "LP8006126139",
"date": "2018-10-04 20:24:52",
"description": "LP8006126139 - Outstanding Payment",
"status": "RECEIVED",
"currency": "LKR",
"amount": 50,
"customer": {
"fist_name": "Saman",
"last_name": "Perera",
"email": "samanperera@gmail.com",
"phone": "+94771234567",
"delivery_details": {
"address": "N0.1, Galle Road",
"city": "Colombo",
"country": "Sri Lanka"
}
},
"amount_detail": {
"currency": "LKR",
"gross": 500,
"fee": 14.50,
"net": 485.50,
"exchange_rate": 1,
"exchange_from": "LKR",
"exchange_to": "LKR"
},
"payment_method": {
"method": "VISA",
"card_customer_name": "S Perera",
"card_no": "************1234"
},
"items": null
}
]
}
```
### Payment Status Values
- `RECEIVED` — Payment received
- `REFUNDED` — Payment has been refunded
- `CHARGEBACKED` — Payment has been chargebacked
- `REFUND REQUESTED` — Refund request received, waiting processing
- `HOLD` — Payment is on hold
**Note:** PayHere does NOT validate order_id uniqueness. Multiple payments may be returned for the same order_id.
---
## Subscription Manager API
**Purpose:** View, retry, and cancel subscriptions created via Recurring API.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/subscription-manager-api
**Auth:** OAuth Bearer Token
### Endpoints
**View Subscriptions:**
- Live: `GET https://www.payhere.lk/merchant/v1/subscription`
- Sandbox: `GET https://sandbox.payhere.lk/merchant/v1/subscription`
**View Subscription Payments:**
- Live: `GET https://www.payhere.lk/merchant/v1/subscription/{subscription_id}/payments`
- Sandbox: `GET https://sandbox.payhere.lk/merchant/v1/subscription/{subscription_id}/payments`
**Retry Failed Subscription:**
- Live: `POST https://www.payhere.lk/merchant/v1/subscription/retry`
- Sandbox: `POST https://sandbox.payhere.lk/merchant/v1/subscription/retry`
**Cancel Subscription:**
- Live: `POST https://www.payhere.lk/merchant/v1/subscription/cancel`
- Sandbox: `POST https://sandbox.payhere.lk/merchant/v1/subscription/cancel`
### Subscription Statuses
- `ACTIVE` — Currently active and charging
- `COMPLETED` — All recurring payments finished
- `CANCELLED` — Cancelled by merchant
- `FAILED` — Payment failed
---
## Refund API
**Purpose:** Programmatically refund payments or authorized holds.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/refund-api
**Auth:** OAuth Bearer Token
### Endpoint
- Live: `POST https://www.payhere.lk/merchant/v1/payment/refund`
- Sandbox: `POST https://sandbox.payhere.lk/merchant/v1/payment/refund`
### Request Body
To refund a **payment**:
```json
{
"payment_id": "320027150501",
"description": "Item is out of stock"
}
```
To refund an **authorization** (hold):
```json
{
"authorization_token": "74d7f304-7f9d-481d-b47f-6c9cad32d3d5",
"description": "Customer cancelled order"
}
```
**Note:** Set either `payment_id` OR `authorization_token`, not both.
---
## Authorize API
**Purpose:** Hold on Card — authorize (hold) an amount on the customer's card for later capture.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/authorize-api
### Form Action URLs
- Live: `https://www.payhere.lk/pay/authorize`
- Sandbox: `https://sandbox.payhere.lk/pay/authorize`
### Parameters
Same as Checkout API parameters. The form submit redirects the customer to authorize the hold.
### Notification Response Includes
| Parameter | Description |
|---|---|
| `authorization_token` | Token to use with Capture API to capture the authorized amount |
---
## Capture API
**Purpose:** Capture a previously authorized Hold on Card payment.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/capture-api
**Auth:** OAuth Bearer Token
### Endpoint
- Live: `POST https://www.payhere.lk/merchant/v1/payment/capture`
- Sandbox: `POST https://sandbox.payhere.lk/merchant/v1/payment/capture`
### Request Body
```json
{
"authorization_token": "74d7f304-7f9d-481d-b47f-6c9cad32d3d5",
"amount": 80.00,
"deduction_details": "Partial capture - item was discounted"
}
```
**Note:** You can capture the full authorized amount or a lesser amount (partial capture).
### Response
```json
{
"status": 1,
"msg": "Successfully captured payment",
"data": {
"status_code": 2,
"status_message": "Successfully received the VISA payment",
"payment_id": 320025527952,
"currency": "LKR",
"amount": 100.00,
"captured_amount": 80.00,
"items": "Toy Car",
"order_id": "Order12345",
"md5sig": "27EE69A66E761D20429984A0CB0AFC27",
"custom_1": "ABCD",
"custom_2": null
}
}
```
---
## JavaScript SDK (payhere.js)
**Purpose:** Onsite checkout popup — payment processes inside an iframe on your page, no redirect needed.
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/javascript-sdk
**Requires:** HTTPS on your website
### Include the SDK
```html
```
### One-Time Payment Example
```javascript
// Event handlers
payhere.onCompleted = function onCompleted(orderId) {
console.log("Payment completed. OrderID:" + orderId);
// Validate payment and show success/failure page
};
payhere.onDismissed = function onDismissed() {
console.log("Payment dismissed");
// Prompt user to pay again or show error
};
payhere.onError = function onError(error) {
console.log("Error:" + error);
// Show error page
};
var payment = {
"sandbox": true,
"merchant_id": "121XXXX",
"return_url": undefined, // Important: set to undefined for JS SDK
"cancel_url": undefined, // Important: set to undefined for JS SDK
"notify_url": "http://sample.com/notify",
"order_id": "ItemNo12345",
"items": "Door bell wireless",
"amount": "1000.00",
"currency": "LKR",
"hash": "GENERATED_HASH_FROM_BACKEND", // Must be generated server-side!
"first_name": "Saman",
"last_name": "Perera",
"email": "samanp@gmail.com",
"phone": "0771234567",
"address": "No.1, Galle Road",
"city": "Colombo",
"country": "Sri Lanka"
};
payhere.startPayment(payment);
```
### Recurring Payment via JS SDK
Add these fields to the payment object:
```javascript
"recurrence": "1 Month", // Frequency
"duration": "1 Year", // Duration
"startup_fee": "10.00" // Optional: extra amount for first payment
```
### Preapproval via JS SDK
Add this field:
```javascript
"preapprove": true
```
### Authorize (Hold on Card) via JS SDK
Add this field:
```javascript
"authorize": true
```
### CRITICAL: return_url and cancel_url must be `undefined` when using JS SDK
**SECURITY WARNING:** The `hash` parameter must NEVER be generated on the client-side as it would expose your `merchant_secret`. Always generate the hash on your server and retrieve it to the client.
---
## Mobile SDKs
### Android SDK
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/android-sdk
**GitHub:** https://github.com/PayHereLK/payhere-mobilesdk-android
**Min API Level:** 17
#### Gradle Dependency
```groovy
implementation 'lk.payhere:android-sdk:4.0.18'
```
#### One-Time Payment
```java
InitRequest req = new InitRequest();
req.setMerchantId("1210XXX");
req.setCurrency("LKR");
req.setAmount(1000.00);
req.setOrderId("230000123");
req.setItemsDescription("Door bell wireless");
req.setCustom1("Custom message 1");
req.setCustom2("Custom message 2");
req.getCustomer().setFirstName("Saman");
req.getCustomer().setLastName("Perera");
req.getCustomer().setEmail("samanp@gmail.com");
req.getCustomer().setPhone("+94771234567");
req.getCustomer().getAddress().setAddress("No.1, Galle Road");
req.getCustomer().getAddress().setCity("Colombo");
req.getCustomer().getAddress().setCountry("Sri Lanka");
req.setNotifyUrl("https://yourserver.com/notify");
Intent intent = new Intent(this, PHMainActivity.class);
intent.putExtra(PHConstants.INTENT_EXTRA_DATA, req);
launcher.launch(intent);
```
#### Recurring Payment (add to InitRequest)
```java
req.setRecurrence("1 Month");
req.setDuration("Forever");
req.setStartupFee(0);
```
### iOS SDK
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/payhere-ios
**GitHub:** https://github.com/PayHereLK/payhere-mobilesdk-ios
**Min iOS:** 13.0
#### CocoaPods
```ruby
pod 'payHereSDK'
```
#### One-Time Payment (Swift)
```swift
let item = Item(id: "item_1", name: "Item 1", quantity: 1, amount: 50.0)
let initRequest = PHInitialRequest(
merchantID: merchantID,
notifyURL: "https://yourserver.com/notify",
firstName: "Saman",
lastName: "Perera",
email: "samanp@gmail.com",
phone: "+9477123456",
address: "No.1, Galle Road",
city: "Colombo",
country: "Sri Lanka",
orderID: "001",
itemsDescription: "Greeting Card",
itemsMap: [item],
currency: .LKR,
amount: 50.00,
deliveryAddress: "",
deliveryCity: "",
deliveryCountry: "",
custom1: "",
custom2: ""
)
PHPrecentController.precent(
from: self,
isSandBoxEnabled: true,
withInitRequest: initRequest!,
delegate: self
)
```
#### Delegate Response
```swift
extension ViewController: PHViewControllerDelegate {
func onResponseReceived(response: PHResponse?) {
if response?.isSuccess() == true {
guard let resp = response?.getData() as? StatusResponse else { return }
// Payment success
} else {
// Payment failed: response?.getMessage()
}
}
}
```
### React Native SDK
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/react-native-sdk
**GitHub:** https://github.com/PayHereLK/payhere-mobilesdk-reactnative
**NPM:** `@payhere/payhere-mobilesdk-reactnative`
```bash
npm install @payhere/payhere-mobilesdk-reactnative
```
```javascript
import PayHere from '@payhere/payhere-mobilesdk-reactnative';
const paymentObject = {
"sandbox": true,
"merchant_id": "1211149",
"notify_url": "http://sample.com/notify",
"order_id": "ItemNo12345",
"items": "Hello from React Native!",
"amount": "50.00",
"currency": "LKR",
"first_name": "Saman",
"last_name": "Perera",
"email": "samanp@gmail.com",
"phone": "0771234567",
"address": "No.1, Galle Road",
"city": "Colombo",
"country": "Sri Lanka"
};
PayHere.startPayment(
paymentObject,
(paymentId) => { console.log("Payment Completed", paymentId); },
(errorData) => { console.log("Payment Failed", errorData); },
() => { console.log("Payment Dismissed"); }
);
```
### Flutter SDK
**Docs:** https://support.payhere.lk/api-&-mobile-sdk/flutter-sdk
**GitHub:** https://github.com/PayHereLK/payhere-mobilesdk-flutter
**Pub.dev:** `payhere_mobilesdk_flutter`
```yaml
dependencies:
payhere_mobilesdk_flutter: ^4.0.5
```
```dart
import 'package:payhere_mobilesdk_flutter/payhere_mobilesdk_flutter.dart';
Map paymentObject = {
"sandbox": true,
"merchant_id": "1211149",
"merchant_secret": "xyz", // Required for Flutter SDK
"notify_url": "http://sample.com/notify",
"order_id": "ItemNo12345",
"items": "Hello from Flutter!",
"amount": 50.00,
"currency": "LKR",
"first_name": "Saman",
"last_name": "Perera",
"email": "samanp@gmail.com",
"phone": "0771234567",
"address": "No.1, Galle Road",
"city": "Colombo",
"country": "Sri Lanka",
};
PayHere.startPayment(
paymentObject,
(paymentId) { print("One Time Payment Success. Payment Id: $paymentId"); },
(error) { print("One Time Payment Failed. Error: $error"); },
() { print("One Time Payment Dismissed"); },
);
```
#### Flutter Recurring Payment
Add to paymentObject:
```dart
"recurrence": "1 Month",
"duration": "1 Year",
"startup_fee": "10.00",
```
#### Flutter Preapproval (Tokenization)
```dart
"preapprove": true,
```
#### Flutter Authorize (Hold on Card)
```dart
"authorize": true,
```
#### Flutter ProGuard Rules (Android release builds)
```proguard
-keep class lk.payhere.** { *; }
-keep interface lk.payhere.androidsdk.PayhereSDK { *; }
-keep class lk.payhere.androidsdk.models.** { *; }
-keep class okhttp3.** { *; }
-keep class okio.** { *; }
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes *Annotation*
```
#### Flutter iOS Setup
Run `pod install` in your iOS project directory after adding the dependency.
---
## Shopping Cart Plugins
| Platform | Docs |
|---|---|
| OpenCart | https://support.payhere.lk/shopping-cart-plugins/plugin-for-opencart |
| WooCommerce | https://support.payhere.lk/shopping-cart-plugins/plugin-for-woocommerce |
| Magento | https://support.payhere.lk/shopping-cart-plugins/plugin-for-magento |
| Prestashop | https://support.payhere.lk/shopping-cart-plugins/plugin-for-prestashop |
| ShopHere | https://support.payhere.lk/shopping-cart-plugins/plugin-for-shophere |
| Shopify | https://support.payhere.lk/shopping-cart-plugins/plugin-for-shopify-oneclick |
| WHMCS | https://support.payhere.lk/shopping-cart-plugins/plugin-for-whmcs |
| CS-Cart | https://support.payhere.lk/shopping-cart-plugins/plugin-for-cs-cart |
| Moodle | https://support.payhere.lk/shopping-cart-plugins/plugin-for-moodle |
**GitHub repos:**
- WooCommerce: https://github.com/PayHereLK/payhere-woocommerce
- OpenCart: https://github.com/PayHereLK/payhere-opencart
- Moodle: https://github.com/PayHereLK/moodleplugin
### Shopify Plugin Setup
1. Go to PayHere Payment App installation page on Shopify
2. Click "Add App" > Choose your Shopify account > Click "Install app"
3. Enter Merchant ID and Merchant Secret
4. Untick "Sandbox Mode" for live payments
5. Click "Save" then "Activate PayHere Payment Gateway"
---
## PayHere Links & Buttons
**Links:** Accept payments without a website. Create shareable payment links from your PayHere dashboard.
**Buttons:** Embed a payment button on your website with minimal code (no API integration needed).
---
## Payment Notification (notify_url)
This is the most critical part of the integration. PayHere sends a server-to-server POST callback to your `notify_url` after each payment.
### Notification POST Parameters
| Parameter | Description |
|---|---|
| `merchant_id` | Your Merchant ID |
| `order_id` | Your order reference |
| `payment_id` | PayHere payment reference number |
| `payhere_amount` | Amount paid |
| `payhere_currency` | Currency of payment |
| `status_code` | `2`=success, `0`=pending, `-1`=canceled, `-2`=failed, `-3`=chargebacked |
| `md5sig` | Verification checksum |
| `method` | Payment method: `VISA`, `MASTER`, `AMEX`, `EZCASH`, `MCASH`, `GENIE`, `VISHWA`, `PAYAPP`, `HNB`, `FRIMI` |
| `status_message` | Gateway message |
| `custom_1` | Custom field 1 |
| `custom_2` | Custom field 2 |
### VISA/MASTER Card Additional Parameters
| Parameter | Description |
|---|---|
| `card_holder_name` | Name on card |
| `card_no` | Masked card number |
| `card_expiry` | Card expiry date |
### CRITICAL: Verifying md5sig
Always verify the md5sig checksum before trusting the notification:
```
md5sig = UPPER(MD5(
merchant_id +
order_id +
payhere_amount +
payhere_currency +
status_code +
UPPER(MD5(merchant_secret))
))
```
Compare your locally generated md5sig with the one received. If they don't match, the notification may be tampered with — do NOT process the payment.
### Important Notes About notify_url
- Notification is sent as `application/x-www-form-urlencoded`, NOT `application/json`
- `notify_url` must be a publicly accessible URL (no localhost)
- Cannot test with `print`/`echo` — it's a server callback, not a browser request
- No payment params are sent to `return_url` — update your DB from `notify_url`, then read from DB on `return_url`
---
## Hash Generation
The hash is used to verify the integrity of payment request parameters. It MUST be generated server-side to protect your merchant_secret.
### Formula
```
hash = UPPER(MD5(
merchant_id +
order_id +
amount_formatted +
currency +
UPPER(MD5(merchant_secret))
))
```
**Where `amount_formatted`** is the amount with exactly 2 decimal places (e.g., `1000.00`).
### PHP Example
```php
$hash = strtoupper(
md5(
$merchant_id .
$order_id .
number_format($amount, 2, '.', '') .
$currency .
strtoupper(md5($merchant_secret))
)
);
```
### Node.js Example
```javascript
const crypto = require('crypto');
function generateHash(merchantId, orderId, amount, currency, merchantSecret) {
const hashedSecret = crypto.createHash('md5')
.update(merchantSecret)
.digest('hex')
.toUpperCase();
const amountFormatted = parseFloat(amount).toFixed(2);
const hash = crypto.createHash('md5')
.update(merchantId + orderId + amountFormatted + currency + hashedSecret)
.digest('hex')
.toUpperCase();
return hash;
}
```
### Python Example
```python
import hashlib
def generate_hash(merchant_id, order_id, amount, currency, merchant_secret):
hashed_secret = hashlib.md5(merchant_secret.encode()).hexdigest().upper()
amount_formatted = f"{float(amount):.2f}"
raw = merchant_id + order_id + amount_formatted + currency + hashed_secret
return hashlib.md5(raw.encode()).hexdigest().upper()
```
### Java Example
```java
import java.math.BigInteger;
import java.security.MessageDigest;
import java.text.DecimalFormat;
public static String generateHash(String merchantId, String orderId, double amount, String currency, String merchantSecret) {
DecimalFormat df = new DecimalFormat("0.00");
String amountFormatted = df.format(amount);
String hash = getMd5(merchantId + orderId + amountFormatted + currency + getMd5(merchantSecret));
return 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 (Exception e) { throw new RuntimeException(e); }
}
```
### C# Example
```csharp
using System.Security.Cryptography;
using System.Text;
static string GenerateHash(string merchantId, string merchantSecret, string orderId, double amount, string currency) {
string hashedSecret = ComputeMD5(merchantSecret);
string amountFormatted = amount.ToString("####0.00");
return ComputeMD5(merchantId + orderId + amountFormatted + currency + hashedSecret);
}
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();
}
```
---
## OAuth Authentication (Merchant APIs)
The Charging, Retrieval, Subscription Manager, Refund, and Capture APIs all use OAuth Bearer tokens.
### Step 1: Create API Key
1. Sign in to PayHere > Settings > API Keys
2. Click "Create API Key"
3. Enter app name and comma-separated domains to whitelist
4. Copy the **App ID** and **App Secret**
### Step 2: Generate Authorization Code
Base64-encode your `App_ID:App_Secret`:
```
Base64Encode("4OVx33RVOPg4DzdZUzq4A94D2:8n4VCj25MXp4JLDFyvsE9h4a8qgbPaZUI4JEWK4FCvop")
```
### Step 3: Get Access Token
```
POST https://www.payhere.lk/merchant/v1/oauth/token (Live)
POST https://sandbox.payhere.lk/merchant/v1/oauth/token (Sandbox)
Headers:
Authorization: Basic
Content-Type: application/x-www-form-urlencoded
Body:
grant_type=client_credentials
```
Response:
```json
{
"access_token": "cb5c47fd-741c-489a-b69e-fd73155ca34e",
"token_type": "bearer",
"expires_in": 599,
"scope": "SANDBOX"
}
```
### Step 4: Use Access Token
Include in all subsequent API requests:
```
Authorization: Bearer cb5c47fd-741c-489a-b69e-fd73155ca34e
```
**Note:** Access tokens expire (default ~10 minutes). Retrieve a new one when expired.
### Live Environment IP Whitelisting
For live Merchant APIs, PayHere enforces IP-based whitelisting. Email `support@payhere.lk` with your server IP address to get whitelisted.
---
## Sandbox & Testing
**Docs:** https://support.payhere.lk/sandbox-and-testing
### Sandbox Portal
- URL: https://sandbox.payhere.lk
- Create a separate sandbox account (not linked to live account)
- No real payments processed — all transactions are simulated
### Test Card Numbers (Successful Payments)
| Card Number | Type |
|---|---|
| `4916217501611292` | Visa |
| `5307732125531191` | Mastercard |
| `346781005510225` | Amex |
For "Name on Card", "CVV" & "Expiry date" — enter any valid data.
### Test Cards for Decline Scenarios
Any card number NOT in the list above will result in a failed payment in sandbox.
### Switching to Sandbox in Code
- Change API endpoint from `www.payhere.lk` to `sandbox.payhere.lk`
- Set `sandbox: true` in JS SDK / Mobile SDK payment objects
- For plugins: enable "Sandbox Mode" checkbox in plugin settings
---
## Payment Limits, Fees & Plans
**Docs:** https://support.payhere.lk/limits-and-fees
### Service Plans
| Plan | Monthly Fee | Processing Fee | Per Payment Limit | Monthly Limit | Features |
|---|---|---|---|---|---|
| **LITE** | Free | 3.99% | Rs.50,000 | Rs.200,000 | LKR & USD one-time payments only |
| **PLUS** | Rs.3,990 | 2.99% | Rs.250,000 | Rs.3,000,000 | One-time + Recurring. LKR/USD/EUR/GBP/AUD |
| **PREMIUM** | Rs.9,990 | 2.69% | Rs.1,000,000 | Unlimited | All features + Automatic Payments (Tokenization) |
| **EDU** | Rs.9,990 | 2.49% | Rs.1,000,000 | Unlimited | Education-only payments |
| **GOV** | Free | 1.99% | Rs.1,000,000 | Unlimited | Government-only. LKR via Visa/Master/HelaPay |
### Limit Types
- **Per Payment Limit** — Max amount per single transaction
- **Monthly Payment Limit** — Max total accepted within a billing month
- **Over Limit** — Customer sees error on payment page when limits exceeded
---
## Supported Payment Methods & Currencies
### Payment Methods
- Visa (credit/debit)
- Mastercard (credit/debit)
- American Express (AMEX)
- eZ Cash (mobile wallet)
- mCash (mobile wallet)
- Genie (mobile wallet)
- Vishwa (mobile wallet)
- PayApp
- HNB (bank)
- FriMi (mobile wallet)
- HelaPay
### Supported Currencies
- `LKR` — Sri Lankan Rupee
- `USD` — US Dollar
- `EUR` — Euro
- `GBP` — British Pound
- `AUD` — Australian Dollar
### USD Payouts
PayHere supports USD payouts for merchants who accept payments in USD. See: https://support.payhere.lk/usd-payouts
---
## Application Process
**Docs:** https://support.payhere.lk/application-process
### Who Can Apply
Any registered business entity in Sri Lanka:
- Private Limited Companies
- Sole Proprietorships
- Partnerships
- Home-based businesses (social media)
- Freelancers
- Clubs/Associations
- Government Organizations
### Prerequisites
- **No application fees or setup fees** — completely free to apply
- Website/app must be complete and ready to go live (not under construction)
- Must display: Terms & Conditions, Return/Refund Policy, Privacy Policy
- Must display: Business name, phone, email, postal address
### Required Signatories
- Private Limited Company: Two directors + company secretary
- Other types: Varies by business type
### Important Notes
- PayHere is strictly for business payments (goods/services exchanged)
- Mock products/services or incomplete content will be rejected
- Applications typically processed within a few business days
---
## Policy Requirements
**Docs:** https://support.payhere.lk/policy-samples
Your website/app MUST display these policy documents (activation will be rejected without them):
1. **Refund Policy** — Conditions for refunds, timeframes, process
2. **Privacy Policy** — Data collection, usage, protection practices
3. **Terms & Conditions** — Usage terms, purchase terms, liability
PayHere provides sample policy templates at the docs link above. Customize them for your business.
---
## Onsite Checkout
**Docs:** https://support.payhere.lk/faq/onsite-checkout
Onsite Checkout displays the payment form as a popup within your website (via iframe), instead of redirecting to PayHere's site.
### Requirements
- Website must be served over HTTPS (SSL certificate required)
- Use the JavaScript SDK (payhere.js) for web integration
- Use Mobile SDKs for in-app payment experience
### Security
Payment credentials are captured inside a PCI DSS certified secure iframe served directly by PayHere's servers. Security is not compromised.
### Benefits
- Better conversion rates (no redirect)
- Seamless customer experience
- Customer stays on your website throughout
---
## Common Pitfalls & FAQs
### Integration Pitfalls
1. **notify_url cannot be localhost** — Must be publicly accessible IP/domain
2. **Hash must be generated server-side** — Never expose merchant_secret in client code
3. **Notification is URL-encoded, not JSON** — Parse as `application/x-www-form-urlencoded`
4. **No payment data in return_url** — Update DB from notify_url, read from DB on return_url
5. **Always verify md5sig** — Never trust notification data without checksum verification
6. **Amount must have exactly 2 decimal places** in hash calculation (e.g., `1000.00`)
7. **order_id uniqueness not enforced** — PayHere doesn't validate; you must ensure uniqueness
8. **JS SDK: set return_url and cancel_url to undefined** — Not empty string, must be `undefined`
9. **Access tokens expire** — Re-fetch OAuth token when expired (~10 min)
10. **Live Merchant APIs require IP whitelisting** — Email support@payhere.lk with server IP
### FAQ
**Q: Can I test on localhost?**
A: The payment gateway itself can be tested on localhost, but the `notify_url` callback cannot reach localhost. Use a tunneling service (ngrok) or a public server for testing notifications.
**Q: What happens when monthly limit is exceeded?**
A: Customer sees an "Over Limit" error on the payment page. Upgrade your plan for higher limits.
**Q: Can I accept payments without a website?**
A: Yes! Use PayHere Links to create shareable payment URLs. No website needed.
**Q: How long does domain/app approval take?**
A: Up to 24 hours for domain/app approval for Merchant Secret generation. Live account app package names may require manual review (up to 1 business day).
**Q: What are the supported recurrence values?**
A: Format is `{number} {unit}` where unit is `Week`, `Month`, or `Year` (singular). Examples: `1 Month`, `2 Week`, `6 Month`, `1 Year`.
**Q: What are the supported duration values?**
A: Same format as recurrence, or `Forever` for unlimited. Duration must be compatible with recurrence unit.
---
## Documentation Links
### Main Docs
| Page | URL |
|---|---|
| Knowledge Base Home | https://support.payhere.lk/ |
| General Questions | https://support.payhere.lk/general-questions |
| Application Process | https://support.payhere.lk/application-process |
| Payment Limits & Fees | https://support.payhere.lk/limits-and-fees |
| Sandbox & Testing | https://support.payhere.lk/sandbox-and-testing |
| Policy Samples | https://support.payhere.lk/policy-samples |
| Onsite Checkout | https://support.payhere.lk/faq/onsite-checkout |
### APIs
| API | URL |
|---|---|
| Checkout API | https://support.payhere.lk/api-&-mobile-sdk/checkout-api |
| Recurring API | https://support.payhere.lk/api-&-mobile-sdk/recurring-api |
| Preapproval API | https://support.payhere.lk/api-&-mobile-sdk/preapproval-api |
| Charging API | https://support.payhere.lk/api-&-mobile-sdk/charging-api |
| Retrieval API | https://support.payhere.lk/api-&-mobile-sdk/retrieval-api |
| Subscription Manager API | https://support.payhere.lk/api-&-mobile-sdk/subscription-manager-api |
| Refund API | https://support.payhere.lk/api-&-mobile-sdk/refund-api |
| Authorize API | https://support.payhere.lk/api-&-mobile-sdk/authorize-api |
| Capture API | https://support.payhere.lk/api-&-mobile-sdk/capture-api |
### SDKs
| SDK | URL |
|---|---|
| JavaScript SDK | https://support.payhere.lk/api-&-mobile-sdk/javascript-sdk |
| Android SDK | https://support.payhere.lk/api-&-mobile-sdk/android-sdk |
| iOS SDK | https://support.payhere.lk/api-&-mobile-sdk/payhere-ios |
| React Native SDK | https://support.payhere.lk/api-&-mobile-sdk/react-native-sdk |
| Flutter SDK | https://support.payhere.lk/api-&-mobile-sdk/flutter-sdk |
### Plugins
| Plugin | URL |
|---|---|
| OpenCart | https://support.payhere.lk/shopping-cart-plugins/plugin-for-opencart |
| WooCommerce | https://support.payhere.lk/shopping-cart-plugins/plugin-for-woocommerce |
| Magento | https://support.payhere.lk/shopping-cart-plugins/plugin-for-magento |
| Prestashop | https://support.payhere.lk/shopping-cart-plugins/plugin-for-prestashop |
| Shopify | https://support.payhere.lk/shopping-cart-plugins/plugin-for-shopify-oneclick |
| WHMCS | https://support.payhere.lk/shopping-cart-plugins/plugin-for-whmcs |
| CS-Cart | https://support.payhere.lk/shopping-cart-plugins/plugin-for-cs-cart |
| Moodle | https://support.payhere.lk/shopping-cart-plugins/plugin-for-moodle |
| ShopHere | https://support.payhere.lk/shopping-cart-plugins/plugin-for-shophere |
### GitHub Repositories
| Repo | URL |
|---|---|
| PayHere Org | https://github.com/PayHereLK |
| Android SDK | https://github.com/PayHereLK/payhere-mobilesdk-android |
| iOS SDK | https://github.com/PayHereLK/payhere-mobilesdk-ios |
| React Native SDK | https://github.com/PayHereLK/payhere-mobilesdk-reactnative |
| Flutter SDK | https://github.com/PayHereLK/payhere-mobilesdk-flutter |
| WooCommerce Plugin | https://github.com/PayHereLK/payhere-woocommerce |
| OpenCart Plugin | https://github.com/PayHereLK/payhere-opencart |
| Demo (PHP) | https://github.com/PayHereLK/payhere-demo-beta |
| Laravel Package (Community) | https://github.com/Visanduma/laravel-payhere |
| JS SDK (Community) | https://github.com/pavinduLakshan/payhere-js-sdk |
### Community Packages
| Package | Platform | URL |
|---|---|---|
| `@payhere-js-sdk/client` | NPM (Browser) | https://github.com/pavinduLakshan/payhere-js-sdk |
| `@payhere-js-sdk/server` | NPM (Node.js) | https://github.com/pavinduLakshan/payhere-js-sdk |
| `lahirulhr/laravel-payhere` | Composer (Laravel) | https://github.com/Visanduma/laravel-payhere |
| `payhere_mobilesdk_flutter` | pub.dev (Flutter) | https://pub.dev/packages/payhere_mobilesdk_flutter |
| `@payhere/payhere-mobilesdk-reactnative` | NPM (React Native) | https://www.npmjs.com/package/@payhere/payhere-mobilesdk-reactnative |
---
## Quick Reference: Integration Decision Tree
```
Need to accept payments?
├── No website? → Use PayHere Links
├── Website, no coding? → Use PayHere Buttons or Shopping Cart Plugins
├── Website, with coding?
│ ├── Want redirect flow? → Checkout API (one-time) or Recurring API (subscription)
│ ├── Want popup/onsite? → JavaScript SDK (payhere.js)
│ └── Need server-to-server?
│ ├── Charge on demand? → Preapproval API + Charging API
│ ├── Hold then capture? → Authorize API + Capture API
│ ├── Get payment details? → Retrieval API
│ ├── Manage subscriptions? → Subscription Manager API
│ └── Process refunds? → Refund API
└── Mobile App?
├── Android? → Android SDK
├── iOS? → iOS SDK
├── React Native? → React Native SDK
└── Flutter? → Flutter SDK
```
---
## Quick Reference: Status Codes
| Code | Meaning | Action |
|---|---|---|
| `2` | Payment success | Fulfill order |
| `0` | Payment pending | Wait for final status |
| `-1` | Payment canceled | Show cancellation to user |
| `-2` | Payment failed/chargebacked | Do not fulfill, contact customer |
| `-3` | Chargebacked | Payment reversed by bank |
---
*This file was created by Theepan Kaja (https://theepankaja.website) as a community resource for AI coding assistants and agents. This is NOT an official PayHere product or document. For the most up-to-date and authoritative information, always refer to the official documentation at https://support.payhere.lk*