PayHere
Use this skill to implement or diagnose PayHere integrations without rediscovering PayHere's product model, API flows, hash rules, callback behavior, and sandbox details.
First Steps
- Identify the PayHere path:
- One-time web payment: Checkout API or JavaScript SDK.
- Onsite web popup: JavaScript SDK.
- Native app: Android, iOS, React Native, or Flutter SDK.
- Subscription: Recurring API plus Subscription Manager API.
- Tokenized/on-demand payment: Preapproval API plus Charging API.
- Hold now, capture later: Authorize API plus Capture API.
- Operations: Retrieval API, Refund API, PayHere portal, Links, Buttons, or plugins.
- Ask for or locate environment values: sandbox/live, merchant ID, domain/app-specific merchant secret, allowed domain/app package, callback URL, order ID, currency, amount, and relevant tokens.
- Protect secrets. Never put merchant secrets, app secrets, authorization codes, access tokens, customer tokens, or authorization tokens in client-side code, logs, fixtures, or public examples.
- Treat
return_url as user navigation only. Rely on notify_url server callbacks and signature verification before updating orders, subscriptions, tokens, or captures.
- Check the relevant reference:
- PayHere product, account, limits, and operational behavior:
references/system-overview.md
- API endpoints, parameters, statuses, hash/OAuth rules:
references/api-reference.md
- Web/mobile SDKs and shopping-cart plugins:
references/sdk-and-plugin-reference.md
- Crawled knowledge-base URL map and source freshness notes:
references/source-map.md
Implementation Rules
- Generate the checkout/request
hash on the server:
HASH = UPPER(MD5(merchant_id + order_id + amount_with_two_decimals + currency + UPPER(MD5(merchant_secret))))
- Verify callback
md5sig before marking anything paid, approved, tokenized, captured, refunded, or canceled:
MD5SIG = UPPER(MD5(merchant_id + order_id + payhere_amount + payhere_currency + status_code + UPPER(MD5(merchant_secret))))
- Format amounts with exactly two decimal places and no thousands separators before hashing.
- Use a public
notify_url; localhost cannot receive PayHere callbacks. For local testing, use a tunnel or deploy a temporary callback endpoint.
- Parse callbacks as
application/x-www-form-urlencoded, not JSON, for redirect-style APIs and SDK notifications.
- Store merchant-side order/payment state before redirecting or opening a popup. Callback delivery and browser return are separate events.
- Make payment updates idempotent by
order_id plus PayHere payment_id or subscription/preapproval token.
- For live merchant REST APIs, expect both allowed-domain/app restrictions and IP whitelisting. Guide the merchant to request PayHere support whitelisting for the server IP when needed.
- Keep sandbox and live credentials completely separate. Sandbox accounts cannot be converted into live accounts.
Helper Script
Use scripts/payhere_crypto.py to calculate hashes, callback signatures, and OAuth Basic authorization strings while implementing or debugging:
python scripts/payhere_crypto.py request-hash \
--merchant-id 121XXXX \
--order-id Order123 \
--amount 1000 \
--currency LKR \
--merchant-secret "$PAYHERE_MERCHANT_SECRET"
python scripts/payhere_crypto.py notification-sig \
--merchant-id 121XXXX \
--order-id Order123 \
--payhere-amount 1000.00 \
--payhere-currency LKR \
--status-code 2 \
--merchant-secret "$PAYHERE_MERCHANT_SECRET"
Use examples with fake credentials only. If a user provides real secrets, avoid echoing them back.
Source Freshness
The PayHere support knowledge base changes. If the user asks for the latest pricing, limits, SDK versions, approval rules, or live operational requirements, verify against the current PayHere documentation before answering or changing code.
1---2name: payhere3description: Build, review, and troubleshoot PayHere Sri Lanka payment integrations. Use when working with PayHere Checkout API, JavaScript SDK, Android/iOS/React Native/Flutter SDKs, Recurring API, Preapproval and Charging API, Authorize and Capture API, Refund or Retrieval APIs, sandbox testing, PayHere Links/Buttons, shopping-cart plugins, merchant onboarding, callbacks, hashes, OAuth tokens, or PayHere-specific payment status handling.4---56# PayHere78Use this skill to implement or diagnose PayHere integrations without rediscovering PayHere's product model, API flows, hash rules, callback behavior, and sandbox details.910## First Steps11121. Identify the PayHere path:13 - One-time web payment: Checkout API or JavaScript SDK.14 - Onsite web popup: JavaScript SDK.15 - Native app: Android, iOS, React Native, or Flutter SDK.16 - Subscription: Recurring API plus Subscription Manager API.17 - Tokenized/on-demand payment: Preapproval API plus Charging API.18 - Hold now, capture later: Authorize API plus Capture API.19 - Operations: Retrieval API, Refund API, PayHere portal, Links, Buttons, or plugins.202. Ask for or locate environment values: sandbox/live, merchant ID, domain/app-specific merchant secret, allowed domain/app package, callback URL, order ID, currency, amount, and relevant tokens.213. Protect secrets. Never put merchant secrets, app secrets, authorization codes, access tokens, customer tokens, or authorization tokens in client-side code, logs, fixtures, or public examples.224. Treat `return_url` as user navigation only. Rely on `notify_url` server callbacks and signature verification before updating orders, subscriptions, tokens, or captures.235. Check the relevant reference:24 - PayHere product, account, limits, and operational behavior: `references/system-overview.md`25 - API endpoints, parameters, statuses, hash/OAuth rules: `references/api-reference.md`26 - Web/mobile SDKs and shopping-cart plugins: `references/sdk-and-plugin-reference.md`27 - Crawled knowledge-base URL map and source freshness notes: `references/source-map.md`2829## Implementation Rules3031- Generate the checkout/request `hash` on the server:3233```text34HASH = UPPER(MD5(merchant_id + order_id + amount_with_two_decimals + currency + UPPER(MD5(merchant_secret))))35```3637- Verify callback `md5sig` before marking anything paid, approved, tokenized, captured, refunded, or canceled:3839```text40MD5SIG = UPPER(MD5(merchant_id + order_id + payhere_amount + payhere_currency + status_code + UPPER(MD5(merchant_secret))))41```4243- Format amounts with exactly two decimal places and no thousands separators before hashing.44- Use a public `notify_url`; localhost cannot receive PayHere callbacks. For local testing, use a tunnel or deploy a temporary callback endpoint.45- Parse callbacks as `application/x-www-form-urlencoded`, not JSON, for redirect-style APIs and SDK notifications.46- Store merchant-side order/payment state before redirecting or opening a popup. Callback delivery and browser return are separate events.47- Make payment updates idempotent by `order_id` plus PayHere `payment_id` or subscription/preapproval token.48- For live merchant REST APIs, expect both allowed-domain/app restrictions and IP whitelisting. Guide the merchant to request PayHere support whitelisting for the server IP when needed.49- Keep sandbox and live credentials completely separate. Sandbox accounts cannot be converted into live accounts.5051## Helper Script5253Use `scripts/payhere_crypto.py` to calculate hashes, callback signatures, and OAuth Basic authorization strings while implementing or debugging:5455```bash56python scripts/payhere_crypto.py request-hash \57 --merchant-id 121XXXX \58 --order-id Order123 \59 --amount 1000 \60 --currency LKR \61 --merchant-secret "$PAYHERE_MERCHANT_SECRET"6263python scripts/payhere_crypto.py notification-sig \64 --merchant-id 121XXXX \65 --order-id Order123 \66 --payhere-amount 1000.00 \67 --payhere-currency LKR \68 --status-code 2 \69 --merchant-secret "$PAYHERE_MERCHANT_SECRET"70```7172Use examples with fake credentials only. If a user provides real secrets, avoid echoing them back.7374## Source Freshness7576The PayHere support knowledge base changes. If the user asks for the latest pricing, limits, SDK versions, approval rules, or live operational requirements, verify against the current PayHere documentation before answering or changing code.