Herepay Payment Gateway
Use this skill for Herepay payment gateway integration work.
Source
Read references/herepay-api.md before giving factual API guidance or writing integration code. It contains environments, auth headers, the payment channel and initiate flow, request fields, checksum algorithm, callback and redirect fields, status codes, requery, payment links, sandbox test banks, and documented inconsistencies.
Read references/herepay-codes.md for bank codes (B2C and B2B), UAT test banks, status and callback enums, and HTTP codes.
Read references/account-setup.md when the user asks how to register, which credentials are needed, where keys come from, UAT setup, callback/redirect URL setup, payment methods, pricing, or settlement timing.
Read references/source-map.md when choosing which Herepay docs page or official repo file applies.
Core Workflow
- Identify environment: UAT (
https://uat.herepay.org) or production (https://app.herepay.org). - Identify surface: direct API (merchant builds bank picker), payment link (Herepay pay page), or WooCommerce plugin.
- Confirm credentials for that environment:
SecretKey,XApiKey, and the Private Key used for checksums, plus the callback and redirect URLs set in the Herepay dashboard. - Create a local pending payment with a unique
payment_codebefore calling Herepay. - Fetch channels server-side with
GET /api/v1/herepay/payment/channels; show onlyActivechannels and keepprefixandpayment_method. - Build the initiate payload, compute
checksumover every field you send (excludingchecksum), andPOST /api/v1/herepay/initiatefrom the server withSecretKeyandXApiKeyheaders. - Return the HTML body from Herepay to the browser; it form-POSTs the customer to the bank.
- Treat the redirect URL POST as browser UX only; do not fulfil from it.
- On the server-to-server callback, verify
checksumwith the Private Key using a constant-time compare, then settle idempotently onpayment_code, amount, currency, and status. - Requery
GET /api/v1/herepay/transactions/{reference_code}when a callback is missing, pending, or ambiguous.
Core Facts
- UAT base:
https://uat.herepay.org. Production base:https://app.herepay.org. Keys are not interchangeable. - Auth headers on every V1 call:
SecretKeyandXApiKey. Payment links useSecretKeyonly. - Payment channels:
GET /api/v1/herepay/payment/channels. - Create payment:
POST /api/v1/herepay/initiatewithpayment_code,created_at(YYYY-MM-DD hh:mm:ss),amount(ringgit, not sen),name,email,phone,description,bank_prefix,payment_method,checksum; official samples also send optionalredirect_url. - Status requery:
GET /api/v1/herepay/transactions/{reference_code}. List:GET /api/v1/herepay/transactions. - Payment link (official samples only):
POST /api/integration/create-payment-link, then redirect todata.pay_url. - Checksum: sort fields by key, JSON-encode nested values, join values with
,, HMAC-SHA256 with the Private Key, lowercase hex. - Callback is a
POST(form data) withreference_code,payment_code,transaction_id,status,status_code,message,amount,currency,payment_method,fpx_type,bank_name,checksum. - Status codes: Status Codes page and official samples use
00success,29pending,30failed,41unauthorized. The Callback reference page lists1completed,2pending,0failed. Handle both. - A malformed initiate request only shows "Checksum verification failed"; there is no detailed error in the browser.
- Test banks (UAT):
TEST0021,TEST0022,TEST0023(SBI Bank A/B/C),ABB0234,LOAD001. Test bank login1234/1234. - Payment methods in API:
Online Banking(B2C) andCorporate Banking(B2B). B2B can stay pending until an authorizer approves. - Refunds, recurring billing, and tokenisation have no API in the official docs (checked 2026-10-21).
- Support: WhatsApp
+60 11-5140 4297(from Getting Started page).
Critical Rules
- Keep
SecretKey,XApiKey, and the Private Key server-side only; never call Herepay from the browser. - Sign the exact values you send, in the exact string form you send (for example
"10.50"vs10.5changes the hash). - If you add
redirect_urlor any other field, it must be inside the checksum input. - Verify callback checksum over all posted fields except
checksum, before trusting any field. - Use constant-time comparison (
hash_equals,crypto.timingSafeEqual,hmac.compare_digest). - Do not mark paid from the redirect POST, the bank page, or a frontend message alone.
- Confirm
payment_code, amount, currencyMYR, and a success status before marking paid. - Make callback processing idempotent; repeated callbacks must not double-fulfil.
- Store
reference_codefrom the callback; requery needs it. - Keep UAT and production keys, URLs, and callback endpoints separate.
- Do not use the published PHP SDK
generateChecksumas-is; it passes the key throughopenssl_pkey_get_private, unlike every other official sample. - Do not copy fee numbers into code or docs; link to the pricing page.
Completion Criteria
A Herepay integration is done only when:
- Channel fetch and initiate run server-side with
SecretKeyandXApiKeyfor the right environment. - Initiate checksum matches the official algorithm and covers every sent field.
- Callback URL is registered in the dashboard for the right environment and is publicly reachable.
- Callback handler verifies
checksumwith the Private Key in constant time. - Settlement checks
payment_code, amount, currency, and status, accepting both00and1style success codes only after checksum passes. - Pending (
29/2) and B2B authorizer-pending payments stay pending and are requeried later. - Tests cover bad checksum, duplicate callback, wrong amount, failed status, pending status, and success.
- Deployment docs list
HEREPAY_SECRET_KEY,HEREPAY_API_KEY,HEREPAY_PRIVATE_KEY,HEREPAY_SANDBOX, callback URL, and redirect URL.
Loophole Review Loop
When asked whether a Herepay strategy is "100% confident", run this loop until no factual gaps remain:
- List trust boundaries: browser checkout form, merchant initiate route, Herepay API, bank page, redirect handler, callback receiver, database, fulfilment job, dashboard URL settings.
- Check bypasses: forged callback, checksum computed over different field set, number formatting drift, unsigned
redirect_url, fake redirect POST, UAT/production key mix, wrong amount, reusedpayment_code, duplicate callback, B2B pending treated as failed, status code1vs00confusion, inactive bank selected. - Add fixes: server-only initiate, local pending row first, unique
payment_code, constant-time checksum check, strict amount/currency/status checks, idempotent settlement, requery byreference_code, environment-scoped config. - Re-read
references/herepay-api.mdsections relevant to any gap. - State remaining uncertainty: which status code set your account's callback sends, callback retry policy, rate limits, card/e-wallet
payment_methodvalues, refund process, andcreated_attimezone are not documented; confirm with Herepay support.


