Juk Gateway API
Juk Gateway ជា middleware ដែលបំប្លែង ABA PayWay Payment Link របស់អ្នក ទៅជា API សាមញ្ញមួយ សម្រាប់បង្កើត KHQR, ទទួល ABA Mobile Deeplink ដោយស្វ័យប្រវត្តិ និងតាមដានស្ថានភាពទូទាត់ជាមួយ endpoint តែពីរប៉ុណ្ណោះ។
🔑 Authentication
រាល់ Store ដែលអ្នកភ្ជាប់ក្នុង Dashboard នឹងទទួលបាន
API Key មួយចាប់ផ្តើមដោយ sk_live_...។ ដាក់វាក្នុង header
Authorization សម្រាប់ endpoint ដែលត្រូវការបង្កើតការទូទាត់។
⚠️ កុំដាក់ API Key ក្នុងកូដ front-end (browser) ដោយផ្ទាល់ — ត្រូវហៅ endpoint /v1/payment ពី server របស់អ្នកជានិច្ច។
💵 រូបិយប័ណ្ណ (USD / KHR)
រូបិយប័ណ្ណត្រូវបានកំណត់ត្រឹម Store level ក្នុង Dashboard (មិនមែនផ្ញើមកជាមួយ request ម្តងៗទេ) — ត្រូវជ្រើសរើសឲ្យត្រូវនឹងអ្វីដែល PayWay Link ត្រូវបានបង្កើតជាមួយលើគណនី ABA ផ្ទាល់របស់អ្នក (ប្រព័ន្ធនេះមិនបម្លែងរូបិយប័ណ្ណទេ គ្រាន់តែបង្ហាញឲ្យត្រឹមត្រូវប៉ុណ្ណោះ)។
| Currency | ទម្រង់ Amount | ឧទាហរណ៍ |
|---|---|---|
| USD | ២ ខ្ទង់ទសភាគ | "amount": "5.00" |
| KHR | លេខគត់ (គ្មានទសភាគ) | "amount": "20000" |
field currency នៅក្នុង response នៃ /v1/payment និង /v1/payment/status ប្រាប់អ្នកថាត្រូវបង្ហាញ "$" ឬ "៛" ដល់អតិថិជន។
/v1/payment
បង្កើត QR ទូទាត់ (Generate KHQR + Deeplink)
ហៅ endpoint នេះម្តងគត់ ដើម្បីទទួលបានទាំង KHQR image, QR string ដើម្បីបង្កើត QR ដោយខ្លួនឯង
និង ABA Mobile Deeplink នៅក្នុង response តែមួយ — មិនចាំបាច់ហៅ API ២ដងទេ។
ភ្លាមៗពេល QR លេចឡើងលើអេក្រង់ អ្នកអាចបង្ហាញប៊ូតុង "បើកក្នុង ABA Mobile" ភ្លាមៗ ព្រោះ field
deeplink ភ្ជាប់មកជាមួយស្រាប់។
Request Body
| Field | ប្រភេទ | ការពិពណ៌នា |
|---|---|---|
| amount | number (required) | ចំនួនទឹកប្រាក់ជា USD ឧ. 5.00 |
| tranId | string (required) | Transaction ID តែមួយគត់ក្នុង order នីមួយៗ។ បើ retry ដោយប្រើ tranId ដដែលពេល QR នៅមានសុពលភាព នឹងទទួលបាន payment ដដែល ប៉ុន្តែបើផុតកំណត់ហើយ នឹងទទួល 409 (ត្រូវប្រើ tranId ថ្មី) |
ឧទាហរណ៍កូដ (Sample Code)
curl -X POST https://aba-api.annoymous.com/v1/payment \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 5.00,
"tranId": "ORDER-1029"
}'
const res = await fetch("https://aba-api.annoymous.com/v1/payment", {
method: "POST",
headers: {
"Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json"
},
body: JSON.stringify({
amount: 5.00,
tranId: "ORDER-1029"
})
});
const payment = await res.json();
console.log(payment.qr_image); // QR ដើម្បីបង្ហាញលើអេក្រង់
console.log(payment.deeplink); // ABA Mobile deeplink (មានស្រាប់ភ្លាមៗ)
console.log(payment.checkout_url); // ទំព័រទូទាត់ដែលរួចរាល់ ប្រើប្រាស់បានភ្លាមៗ
<?php
$ch = curl_init("https://aba-api.annoymous.com/v1/payment");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"amount" => 5.00,
"tranId" => "ORDER-1029"
])
]);
$response = curl_exec($ch);
curl_close($ch);
$payment = json_decode($response, true);
echo $payment['qr_image']; // QR ដើម្បីបង្ហាញលើអេក្រង់
echo $payment['deeplink']; // ABA Mobile deeplink
echo $payment['checkout_url']; // ទំព័រទូទាត់ដែលរួចរាល់
import requests
res = requests.post(
"https://aba-api.annoymous.com/v1/payment",
headers={
"Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json"
},
json={
"amount": 5.00,
"tranId": "ORDER-1029"
}
)
payment = res.json()
print(payment["qr_image"]) # QR ដើម្បីបង្ហាញលើអេក្រង់
print(payment["deeplink"]) # ABA Mobile deeplink
print(payment["checkout_url"]) # ទំព័រទូទាត់ដែលរួចរាល់
Response (201 Created)
{
"id": "pay_9f2a7c1b3e4d5a6f",
"storeId": "store_a1b2c3d4e5f6",
"paywayLink": "https://payway.ababank.com/plc/...",
"tranId": "ORDER-1029",
"amount": "5.00",
"currency": "USD",
"status": "PENDING",
"qr_string": "00020101021229180014...6304A1B2",
"qr_image": "https://aba-api.annoymous.com/qr/pay_9f2a7c1b3e4d5a6f.png",
"deeplink": "abamobilebank://ababank.com?type=payway&qrcode=00020101021229180014...",
"checkout_url": "https://aba-api.annoymous.com/checkout.html?paymentId=pay_9f2a7c1b3e4d5a6f",
"createdAt": "2026-09-07T10:12:03.000Z"
}
💡 currency កំណត់ត្រឹម Store level (ជ្រើសរើសពេលភ្ជាប់ PayWay Link ក្នុង Dashboard) មិនមែនផ្ញើមកជាមួយ request នេះទេ —
value ដែលអាចមានគឺ USD ឬ KHR។ KHR បង្ហាញជាលេខគត់ (គ្មានទសភាគ) ខណៈ USD បង្ហាញ ២ ខ្ទង់ទសភាគ។
💡 វិធីលឿនបំផុត៖ redirect អតិថិជនទៅ checkout_url ដោយផ្ទាល់ — ទំព័រនោះបង្ហាញ QR, ប៊ូតុង Deeplink,
និង poll ស្ថានភាពដោយស្វ័យប្រវត្តិឲ្យរួចរាល់ស្រាប់ (មិនចាំបាច់សង់ UI ដោយខ្លួនឯងក៏បាន)។
/v1/payment/status
ពិនិត្យស្ថានភាពទូទាត់
Endpoint នេះមិនត្រូវការ API Key ទេ (ប្រើ paymentId ជា reference) —
ស័ក្តិសមសម្រាប់ front-end ធ្វើ polling ផ្ទាល់ ដើម្បីដឹងថាអតិថិជនបានស្កេន QR ហើយបានបង់ប្រាក់ពិតៗឬនៅ។
ស្ថានភាពប្រែទៅ COMPLETED តែនៅពេលប្រព័ន្ធបានឃើញការទូទាត់ពិតៗពី PayWay ប៉ុណ្ណោះ។
ឧទាហរណ៍កូដ (Polling រៀងរាល់ 2.5 វិនាទី)
curl -X POST https://aba-api.annoymous.com/v1/payment/status \
-H "Content-Type: application/json" \
-d '{ "paymentId": "pay_9f2a7c1b3e4d5a6f" }'
async function pollStatus(paymentId) {
const interval = setInterval(async () => {
const res = await fetch("https://aba-api.annoymous.com/v1/payment/status", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ paymentId })
});
const data = await res.json();
if (data.status === "COMPLETED") {
clearInterval(interval);
console.log("បង់ប្រាក់ជោគជ័យ!", data);
// TODO: ដំណើរការ order នៅត្រង់នេះ
}
}, 2500);
}
<?php
$ch = curl_init("https://aba-api.annoymous.com/v1/payment/status");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["paymentId" => "pay_9f2a7c1b3e4d5a6f"])
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($response['status'] === 'COMPLETED') {
// ដំណើរការ order នៅត្រង់នេះ
}
import requests, time
def poll_status(payment_id):
while True:
res = requests.post(
"https://aba-api.annoymous.com/v1/payment/status",
json={"paymentId": payment_id}
)
data = res.json()
if data["status"] == "COMPLETED":
print("បង់ប្រាក់ជោគជ័យ!", data)
break
time.sleep(2.5)
QR មានសុពលភាពប្រហែល 4 នាទី។ សូមដំណើរការ order តែនៅពេល
fulfillment_ready ជា true (status COMPLETED) ប៉ុណ្ណោះ។
បើ status ជា EXPIRED ហើយ reconciliation_required ជា true មានន័យថាប្រព័ន្ធមិនអាចបញ្ជាក់ដោយស្វ័យប្រវត្តិទេ —
សូមកុំដំណើរការ order ហើយទាក់ទង support ដើម្បីពិនិត្យដោយដៃ។ Record ទូទាត់ត្រូវបានរក្សាទុក 30 ថ្ងៃ។
Response
{
"id": "pay_9f2a7c1b3e4d5a6f",
"tranId": "ORDER-1029",
"status": "PENDING", // ឬ "COMPLETED" / "EXPIRED"
"amount": "5.00",
"currency": "USD"
}
/v1/payment/:id
ព័ត៌មានពេញលេញនៃការទូទាត់
ត្រឡប់ record ពេញលេញ (រួមទាំង qr_image និង deeplink) —
នេះជា endpoint ដែលទំព័រ checkout.html ខ្លួនឯងហៅ ដើម្បីបង្ហាញ QR ដល់អតិថិជន។
curl https://aba-api.annoymous.com/v1/payment/pay_9f2a7c1b3e4d5a6f
📱 របៀបប្រើ ABA Deeplink ត្រឹមត្រូវ
field deeplink ត្រូវបានបង្កើតជាទម្រង់
abamobilebank://ababank.com?type=payway&qrcode=<qr_string>
ដូចឯកសារផ្លូវការរបស់ PayWay។ ប៉ុន្តែ Android Chrome មិនបើក custom scheme ដោយផ្ទាល់ទេ
ត្រូវរុំវាជា intent:// URL សិន ចំណែក iOS Safari អាចប្រើ deeplink ដើមបានតែម្តង។
function buildAbaOpenUrl(deeplink) {
// iOS: Safari បង្ហាញ prompt "Open in ABA Mobile?" ដោយស្វ័យប្រវត្តិ
if (!/Android/i.test(navigator.userAgent)) {
return deeplink;
}
// Android: ត្រូវរុំជា intent:// URL ជាមួយ fallback ទៅ Play Store
const qrcode = deeplink.match(/qrcode=([^&]+)/)?.[1] || '';
return `intent://ababank.com?type=payway&qrcode=${qrcode}#Intent;` +
`scheme=abamobilebank;package=com.paygo24.ibank;` +
`S.browser_fallback_url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.paygo24.ibank;end;`;
}
// ពេល QR លេចឡើង (response ពី /v1/payment) — បង្ហាញប៊ូតុងភ្លាមៗ
document.getElementById('aba-btn').href = buildAbaOpenUrl(payment.deeplink);
// ជម្រើស: បើកកម្មវិធីដោយស្វ័យប្រវត្តិលើទូរស័ព្ទ ភ្លាមៗពេល QR រួចរាល់
if (/Android|iPhone|iPad/i.test(navigator.userAgent)) {
window.location.href = buildAbaOpenUrl(payment.deeplink);
}
កូដពិតដែលអនុវត្តតក្កវិជ្ជានេះស្រាប់ អាចមើលឧទាហរណ៍ពេញលេញនៅឯកសារ checkout.html ក្នុងគម្រោងផ្ទាល់របស់អ្នក។
🔄 Full Integration Flow
-
1
Server របស់អ្នក ហៅ
POST /v1/paymentជាមួយ amount → ទទួលid,qr_image,deeplink,checkout_url -
2
Redirect អតិថិជនទៅ
checkout_url(ងាយបំផុត) ឬ embedqr_imageនិងប៊ូតុង deeplink ក្នុង UI ផ្ទាល់ខ្លួន -
3
អតិថិជនស្កេន QR ក្នុងកម្មវិធីធនាគារណាមួយ ឬចុចប៊ូតុងបើក ABA Mobile ដោយផ្ទាល់
-
4
Front-end poll
POST /v1/payment/statusរៀងរាល់ 2-3 វិនាទី រហូតទទួលstatus: "COMPLETED" -
5
ដំណើរការ order របស់អ្នក (ផ្ញើ email, ដកស្តុក, ។ល។)
⚠️ Error Codes
| HTTP Status | អត្ថន័យ |
|---|---|
| 401 | API Key គ្មាន ឬខុស |
| 403 | Store/Merchant ត្រូវបានផ្អាកដំណើរការ (Banned) |
| 429 | លើសកម្រិត Quota ប្រចាំថ្ងៃរបស់ Plan ឬមាន payment មិនទាន់បង់ច្រើនពេក (អតិបរមា 5 ក្នុងមួយពេល) |
| 400 | Amount ឬ Body មិនត្រឹមត្រូវ |
| 409 | tranId ត្រូវបានប្រើរួចហើយ ហើយ payment នោះផុតកំណត់ ឬបានបញ្ចប់ (ត្រូវប្រើ tranId ថ្មី) |
| 500 | មិនអាចទាញយក QR ពី PayWay Link បានទេ (សូម retry) |