# JLA Payway API > AI-readable reference for creating ABA Payway payment transactions, opening checkout, checking payment status, and receiving webhook notifications. Base URL: https://payway.jlastore.com Human documentation: https://payway.jlastore.com/ AI documentation: https://payway.jlastore.com/llms.txt Interactive API tester: https://payway.jlastore.com/#api-tester Privacy Policy: https://payway.jlastore.com/privacy-policy Terms of Use: https://payway.jlastore.com/terms The interactive tester uses https://link.payway.com.kh/ABAPAYhj455002v as its default aba_data URL. Submitting the tester creates a live payment request. Response format: application/json ## Get an ABA Payway Link The default aba_data value is an ABA Payway Payment Link. To create your own: 1. Download the free ABA Merchant App from https://www.payway.com.kh/aba-merchant-app/. 2. If you are a new merchant, activate with your ABA account for free. Existing merchants can sign in with the ABA account connected to their business. 3. Create a Payment Link in the ABA merchant tools and copy the generated https://link.payway.com.kh/... URL. 4. Send that URL as aba_data in POST /api/create-tran or paste it into the interactive API tester. Merchant self-registration: https://merchant.payway.com.kh/self-register/ Official Payment Link information: https://www.payway.com.kh/payment-link/ ## Public API Use these endpoints for public integrations: - POST /api/create-tran - GET /checkout/:tran_id - POST /api/check-payment-status ## POST /api/create-tran Creates a Payway transaction, saves a local transaction reference, and returns an absolute checkout URL. Request content type: application/json Request body: ```json { "amount": "0.1", "aba_data": "https://link.payway.com.kh/ABAPAYhj455002v", "continue_url": "https://your-site.com/payment/success", "cancel_url": "https://your-site.com/payment/cancel", "webhook": "https://your-site.com/api/payway-webhook", "tran_id": "jl002" } ``` Fields: - amount: Required. String or number. Minimum value is 0.01. - aba_data: Required. Either encrypted ABA Payway data or a Payway link URL. If a URL is sent, the server inspects the Payway page once, extracts the encrypted aba_data value, and reuses its internal cache on later requests. - tran_id: Optional. Your own transaction reference id. If provided, this is used for checkout and status checks. - continue_url: Optional. URL where the customer is redirected after approval. - cancel_url: Optional. URL where the customer is redirected after cancel or expiry. - webhook: Optional. Your endpoint that receives an approved payment notification. Important behavior: - If tran_id already exists, the API returns the saved response and does not create another Payway transaction. - checkout_url is always absolute and uses the public base URL. - deeplink opens ABA Mobile and contains the URL-encoded qr_string. - The Payway transaction id is returned as payway_tran_id. Example response: ```json { "success": true, "message": "Transaction created", "tran_id": "jl002", "payway_tran_id": "178392699651531", "checkout_url": "https://payway.jlastore.com/checkout/jl002", "deeplink": "abamobilebank://ababank.com?type=payway&qrcode=000201...", "reference_saved": true, "reused": false, "aba_data_url": "https://link.payway.com.kh/ABAPAYhj455002v", "aba_data_cached": false, "data": { "status": { "code": "00", "tran_id": "178392699651531" }, "client_id": "CLIENT_ID", "qr_string": "..." }, "webhook_registered": true } ``` Duplicate tran_id response: ```json { "success": true, "message": "Transaction already exists", "tran_id": "jl002", "payway_tran_id": "178392699651531", "checkout_url": "https://payway.jlastore.com/checkout/jl002", "deeplink": "abamobilebank://ababank.com?type=payway&qrcode=000201...", "reference_saved": true, "reused": true, "data": { "status": { "code": "00", "tran_id": "178392699651531" } } } ``` Validation errors: ```json { "error": "Amount >= 0.01 required" } ``` ```json { "error": "aba_data is required" } ``` ## GET /checkout/:tran_id Displays the customer checkout page for a saved transaction. Example: ```text https://payway.jlastore.com/checkout/jl002 ``` Behavior: - Shows a locally generated SVG QR code. - Attempts to open ABA mobile. - Counts down using the saved Payway expiry. - Redirects to cancel_url when expired. - Redirects to continue_url when payment is approved. ## POST /api/check-payment-status Checks payment status for a saved transaction. Request content type: application/json Request body: ```json { "tran_id": "jl002" } ``` Fields: - tran_id: Required. The transaction reference id returned by /api/create-tran, or your own tran_id if you supplied one. Behavior: - The client only sends tran_id. - The server uses the saved transaction reference to build the Payway status request. - The API returns the upstream Payway status response. ## Status Polling & Expiration Recommendations When polling payment status programmatically or via background loop: - **Loop Interval (5-Second Sleep)**: Recommended loop sleep time is **5 seconds** (`sleep 5s` or `setTimeout(..., 5000)`). Do NOT poll faster than 5 seconds to avoid IP rate-limiting (`RATE_LIMIT_STATUS_MAX: 120/min`). - **Transaction Expiry (3 Minutes)**: Payway QR checkout sessions expire after **3 minutes** (180 seconds). Stop polling after 3 minutes (maximum 36 check cycles). If not approved within 3 minutes, treat the transaction as expired and generate a new payment link. Example Polling Loop (JavaScript): ```javascript async function waitForPayment(tranId, maxMinutes = 3) { const timeoutMs = maxMinutes * 60 * 1000; const startTime = Date.now(); while (Date.now() - startTime < timeoutMs) { const res = await fetch("https://payway.jlastore.com/api/check-payment-status", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ tran_id: tranId }) }); const data = await res.json(); if (data.status?.message === "approved" || data.data?.action === "approved") { return { status: "approved", data }; } // Sleep 5 seconds before next poll await new Promise(resolve => setTimeout(resolve, 5000)); } return { status: "expired", message: "Transaction expired after 3 minutes" }; } ``` ## Webhook If webhook is supplied in /api/create-tran, the server polls Payway and sends a POST request to your webhook URL after approval. Webhook payload: ```json { "status": "approved", "tran_id": "jl002", "payway_tran_id": "178392699651531", "real_tran_id": "PAYWAY_TRANSACTION_ID", "download_receipt": "https://...", "amount": "0.10", "date": "20260713083022", "full_response": {} } ``` ## Recommended Integration Flow 1. Call POST /api/create-tran with amount, aba_data, URLs, webhook, and optional tran_id. 2. Open checkout_url in a browser or deeplink in ABA Mobile. 3. If polling status on client or backend, sleep 5 seconds between checks and timeout after 3 minutes (180s expiration). 4. Receive webhook when the payment is approved. 5. If webhook delivery is not enough, call POST /api/check-payment-status with only tran_id.