รายการ Endpoint
รายละเอียดทุก endpoint ของ Payment API ทั้งการสร้างรายการรับเงิน จ่ายเงินออก ตรวจยอดคงเหลือ ยกเลิกรายการ และแนบสลิป
สร้างจาก public-api.md โดยอัตโนมัติเวอร์ชัน 1.2.0ปรับปรุงล่าสุด 2026-09-20
#สรุป Endpoint
| Method | Path | วัตถุประสงค์ |
|---|---|---|
| POST | /v1/payments/deposit | สร้างรายการรับเงิน (PromptPay QR) |
| POST | /v1/payments/withdraw | สร้างรายการจ่ายเงินออกเข้าบัญชีธนาคาร |
| GET | /v1/payments/get-balance | สรุปยอดคงเหลือปัจจุบัน |
| GET | /v1/payments/{id} | ดึงข้อมูลรายการเดียว |
| POST | /v1/payments/{id}/cancel | ยกเลิกรายการที่ยังรอชำระ |
| POST | /v1/payments/{id}/upload-slip | กู้รายการรับเงินที่ หมดอายุ ด้วยสลิปโอนเงิน |
| GET | /v1/merchant-reports/* | รายงานสำหรับ ERP — ดู merchant-reports-api.md |
| GET | /health, /health/detailed | ตรวจสถานะเกตเวย์ (ไม่ต้องยืนยันตัวตน) |
| GET | /sandbox/test, /sandbox/credentials, /sandbox/test-amounts | ตัวช่วยของ sandbox (เฉพาะโฮสต์ sandbox ไม่ต้องยืนยันตัวตน) |
API รับ-จ่ายเงินไม่มี endpoint สำหรับค้นหาหรือแสดงรายการธุรกรรม และไม่มี endpoint สำหรับคืนเงิน
หากต้องการดูประวัติแบบอ่านอย่างเดียว ให้ใช้ /v1/merchant-reports/transactions และ
/v1/merchant-reports/refunds
#สร้างรายการรับเงิน (Create Deposit)
สร้างคำขอรับเงินรายการใหม่ ระบบจะคืน PromptPay QR สำหรับให้ลูกค้าชำระเงิน
POST /v1/payments/deposit → 201 Created
#Request Body
| ฟิลด์ | ชนิด | จำเป็น | การตรวจสอบ / คำอธิบาย |
|---|---|---|---|
amount | number | ใช่ | ต้อง > 0 ที่เกตเวย์ ดูหัวข้อ ขีดจำกัดจำนวนเงิน ด้านล่าง |
currency | string | ใช่ | ความยาว 3 ตัวอักษรพอดี ระบบประมวลผลเฉพาะ THB |
reference_id | string | ใช่ | เลขอ้างอิงคำสั่งซื้อของคุณ ยาว 1–64 ตัวอักษร ไม่ มีการตัดรายการซ้ำ ดูหมายเหตุ |
bank_code | string | ใช่ | รหัสธนาคาร ของผู้ชำระเงิน ความยาว 3 ตัวอักษรพอดี ดูหัวข้อรหัสธนาคาร |
bank_account_no | string | ใช่ | เลขบัญชีธนาคาร ของผู้ชำระเงิน ยาว 10–20 ตัวอักษร |
bank_account_name | string | ใช่ | ชื่อเจ้าของบัญชี ของผู้ชำระเงิน ยาว 1–100 ตัวอักษร |
customer_email | string | ไม่ | ต้องอยู่ในรูปแบบอีเมลที่ถูกต้อง |
customer_phone | string | ไม่ | ยาวไม่เกิน 20 ตัวอักษร |
description | string | ไม่ | ยาวไม่เกิน 255 ตัวอักษร |
webhook_url | string | ไม่ | ต้องอยู่ในรูปแบบ URL ที่ถูกต้อง ระบบจะส่ง webhook ก็ต่อเมื่อมีฟิลด์นี้ |
การเปลี่ยนแปลงที่กระทบของเดิม — 2026-05-13:
bank_code,bank_account_noและbank_account_nameเป็นฟิลด์ จำเป็น ให้ส่งข้อมูลธนาคารของ ผู้ฝากเงิน (ลูกค้า) มาด้วย เพื่อให้ระบบจับคู่การแจ้งเตือนจากธนาคารเข้ากับรายการที่ถูกต้อง คำขอที่ขาดฟิลด์ใดฟิลด์หนึ่ง ในสามฟิลด์นี้จะถูกปฏิเสธด้วยMISSING_PAYER_INFO(400) ดู Migration: payer info required
reference_idไม่ใช่กุญแจกันรายการซ้ำ การส่งreference_idเดิมซ้ำจะสร้าง รายการที่สองแยกอีกรายการหนึ่ง ระบบไม่มีการตรวจจับรายการซ้ำและไม่ตอบ409เมื่อส่งซ้ำ ดังนั้นอย่าสั่งรับเงินซ้ำเมื่อเกิด timeout ก่อนตรวจสอบว่ารายการแรกสำเร็จไปแล้วหรือยัง
#ขีดจำกัดจำนวนเงิน
เกตเวย์ตรวจเพียงว่า amount > 0 จากนั้นระบบชำระเงินจะบังคับเงื่อนไขเพิ่ม:
- ขั้นต่ำเด็ดขาดที่ 50.00 บาท สำหรับการรับเงิน ใช้กับทุกบัญชีไม่ว่าตั้งค่าไว้อย่างไร
- ขั้นต่ำและขั้นสูงของการรับเงินที่ตั้งไว้ในบัญชีร้านค้าของคุณ (ค่าเริ่มต้น 1 ถึง 1,000,000 บาท โดยขั้นต่ำเด็ดขาดด้านบนยังมีผลเหนือกว่าในฝั่งต่ำ)
หากผิดเงื่อนไขจะได้ 400 INVALID_AMOUNT พร้อมช่วงที่ใช้ได้จริงในข้อความ เช่น
Amount must be between 50.00 and 1000000.00 THB
#ตัวอย่างคำขอ
{
"amount": 1000.00,
"currency": "THB",
"reference_id": "ORD888888888",
"bank_code": "004",
"bank_account_no": "1234567890",
"bank_account_name": "นาย ทดสอบ ตัวอย่าง",
"webhook_url": "https://example.com/path/to/your/webhook"
}#ข้อผิดพลาด: ข้อมูลผู้ชำระเงินไม่ครบ
{
"code": "MISSING_PAYER_INFO",
"message": "กรุณาส่งข้อมูลผู้ฝาก (bank_code, bank_account_no, bank_account_name) ครบทั้ง 3 ฟิลด์ — จำเป็นสำหรับการตรวจสอบรายการกับ SMS ของธนาคาร",
"details": {
"bank_code": "ต้องระบุ — รหัสธนาคารผู้ฝาก 3 หลัก เช่น 004 (KBANK), 014 (SCB), 030 (TTB)",
"bank_account_no": "ต้องระบุ — เลขบัญชีผู้ฝาก 10-20 หลัก (ผู้ที่จะโอนเงินเข้ามา)",
"bank_account_name": "ต้องระบุ — ชื่อบัญชีผู้ฝาก 1-100 ตัวอักษร"
}
}ค่าใน details ใช้ชื่อฟิลด์ JSON เป็นคีย์และเขียนคำอธิบายเป็นภาษาไทย หากฟิลด์อื่นนอกเหนือจาก
สามฟิลด์ของผู้ชำระเงินไม่ผ่านการตรวจสอบ ค่า code ระดับบนสุดจะเป็น INVALID_REQUEST แทน
#Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"reference_id": "ORD888888888",
"type": "deposit",
"status": "pending",
"amount": 1000.00,
"paid_amount": 1000.37,
"currency": "THB",
"qr_code": "00020101021129370016A000000677010111011300668123456785802TH5303764...",
"qr_code_image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"payment_url": "https://pay.paymenow.asia/p/THMTrerxgEc08n-tgadZ5a8FeIoIuwDHFo8OqmGsO-4",
"created_at": "2026-09-20T17:30:00+07:00",
"expires_at": "2026-09-20T17:40:00+07:00"
}#ฟิลด์ใน Response
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
id | string | รหัสรายการที่ไม่ซ้ำ (UUID) |
reference_id | string | เลขอ้างอิงคำสั่งซื้อของคุณ |
type | string | deposit |
status | string | เป็น pending เมื่อสร้าง (ใน sandbox อาจคืนสถานะสุดท้ายมาทันที) |
amount | number | จำนวนเงินที่คุณขอมา |
paid_amount | number | จำนวนเงินที่ลูกค้าต้องโอนจริง ดูคำอธิบายด้านล่าง |
currency | string | รหัสสกุลเงิน |
qr_code | string | ข้อความ payload ของ PromptPay QR |
qr_code_image | string | รูป QR แบบ data:image/png;base64,… (เฉพาะ production ส่วน sandbox เป็นค่าว่าง) |
payment_url | string | หน้าชำระเงินที่โฮสต์ให้สำหรับรายการนี้ — ดูด้านล่าง ได้ "" เมื่อไม่ได้ตั้งค่า |
created_at | string | เวลาที่สร้างรายการ (RFC 3339 เวลาไทย) |
expires_at | string | เวลาที่หมดอายุ (RFC 3339 เวลาไทย ค่าเริ่มต้น 10 นาที) |
paid_amountคือจำนวนเงินที่ต้องโอนจริง ระบบจับคู่รายการรับเงินกับการแจ้งเตือนของธนาคาร ด้วยบัญชีผู้โอนร่วมกับจำนวนเงินระดับ สตางค์ที่ไม่ซ้ำกัน ตัว QR จึงเข้ารหัสยอดamountบวกเศษสตางค์สุ่มเล็กน้อย ให้แสดงpaid_amount(หรือ QR) แก่ลูกค้าเสมอ อย่าแสดงamountมิฉะนั้นการโอนอาจจับคู่ไม่ได้ ส่วนใน sandbox ค่าpaid_amountจะเท่ากับamount
#
payment_url— หน้าชำระเงินที่แพลตฟอร์มโฮสต์ให้แทนที่จะเรนเดอร์ QR เอง ส่งลิงก์นี้ให้ลูกค้าได้เลย หน้านี้แพลตฟอร์มเป็นผู้ให้บริการ มีทั้งภาษาไทยและอังกฤษ และจัดการส่วนที่พลาดกันบ่อยให้:
- แสดงถูกตามบัญชีที่ได้รับ แพลตฟอร์มหมุนบัญชีรับเงินให้แต่ละรายการ ถ้าบัญชีนั้นมีเลข PromptPay หน้าจะแสดง QR ถ้าไม่มีจะแสดงเลขบัญชีพร้อมปุ่มคัดลอก คุณไม่ต้องเขียนเงื่อนไขเอง และกรณีหลัง
qr_codeอย่างเดียวบอกไม่ได้- แสดงยอดที่ต้องโอนแบบตรงทุกสตางค์ ปุ่มคัดลอกจะคัดลอก
1000.37ไม่ใช่1,000.37ที่แอปธนาคารไม่รับ- บอกว่าต้องโอนจากบัญชีไหน การจับคู่ใช้บัญชีต้นทางและเศษสตางค์ร่วมกัน หน้านี้จึงย้ำ ธนาคารและเลข 4 ตัวท้ายของบัญชีที่ลูกค้าแจ้งไว้ เงินที่โอนจากบัญชีอื่นจะเข้าแต่จับคู่ไม่ได้
- บันทึกรูป QR ได้ ลิงก์มักถูกเปิดบนมือถือเครื่องเดียวกับแอปธนาคาร ซึ่งสแกนหน้าจอตัวเองไม่ได้ บันทึกรูปแล้วเลือกจากคลังภาพในแอปได้เลย
- อัปเดตตัวเอง หน้าจะเปลี่ยนเป็น "ชำระเงินสำเร็จ" เองโดยไม่ต้องรีเฟรช และมีนับถอยหลังถึง
expires_at- ให้ลูกค้ายืนยันการโอนเองได้ ทั้งระหว่างที่ QR ยังไม่หมดเวลาและหลังหมดเวลาแล้ว ลูกค้าอัปโหลด สลิปได้ ระบบตรวจยอด บัญชีปลายทาง ธนาคารต้นทาง และอายุสลิป (ไม่เกิน 24 ชม.) แล้วปิดรายการให้ทันที ตรงนี้คือความต่างระหว่างการโอนช้าที่ได้รับเครดิต กับการโอนช้าที่กลายเป็นเรื่องร้องเรียน
ให้ถือว่าลิงก์นี้เป็นความลับ กุญแจเดียวของมันคือโทเคนสุ่มขนาด 256 บิตที่สร้างเฉพาะรายการนั้น ไม่ใช่รหัสรายการ และไม่ปรากฏในฟิลด์อื่นใด ใครถือลิงก์ก็เห็นยอดเงิน บัญชีรับเงิน และสถานะ จึงควรส่งให้ลูกค้าผ่านช่องทางเดียวกับที่คุณส่งใบแจ้งหนี้ และอย่าใส่ไว้ใน log ที่แชร์ออกไป ในระบบวิเคราะห์ข้อมูล หรือหน้าที่ search engine เข้าถึงได้
สิ่งที่หน้านั้นไม่เปิดเผย: ชื่อร้านค้า ค่าธรรมเนียม และเลขบัญชีเต็มของผู้โอน (ปิดบังเหลือ 4 ตัวท้าย) ข้อมูลที่หน้านั้นได้รับแคบกว่าที่ API นี้คืนให้โดยตั้งใจ
รูปแบบการแสดงผล เป็นไปตามที่ร้านค้าตั้งไว้ในแดชบอร์ดร้านค้า (ตั้งค่า › ทั่วไป › หน้าชำระเงินของลูกค้า) — สว่าง มืด หรือตามเครื่องของลูกค้า ไม่ต้องส่งค่าใดมาที่นี่
ร้านค้าปิดการใช้งานได้ ที่แดชบอร์ดร้านค้า ตั้งค่า › ทั่วไป สวิตช์นี้เปลี่ยนสองอย่างพร้อมกัน และแยกจากกันไม่ได้:
เปิด (ค่าเริ่มต้น) ปิด payment_urlลิงก์หน้าชำระเงิน ""บัญชีรับเงินที่ระบบเลือกใช้ ทุกบัญชีที่ตั้งไว้ว่ารับฝาก เฉพาะบัญชีที่มีพร้อมเพย์ qr_code/qr_code_imageคืนให้ คืนให้ กติกาเรื่องบัญชีเป็นผลจากฟิลด์นั้นโดยตรง เมื่อเปิดหน้าชำระเงิน บัญชีที่ไม่มีเลขพร้อมเพย์ยังใช้ได้ เพราะหน้านั้นจะแสดงเลขบัญชีให้โอนแทน QR แต่เมื่อปิด คุณต้องนำ
qr_codeไปแสดงเอง ซึ่งบัญชีแบบนั้น สร้าง QR ไม่ได้ การส่งลูกค้าไปที่บัญชีนั้นจึงเท่ากับส่งไปที่หน้าจอว่าง ระบบจึงจำกัดการหมุนบัญชี ให้เหลือเฉพาะบัญชีที่มีพร้อมเพย์ตลอดเวลาที่ปิดอยู่สิ่งที่ระบบของคุณต้องรองรับ: ถ้าคุณเรนเดอร์ QR เอง ให้คาดหวังว่า
payment_urlเป็น""แล้วข้ามไป ถ้าคุณใช้ลิงก์ อย่าบังคับว่าqr_codeต้องไม่ว่าง เพราะเมื่อเปิดหน้าชำระเงิน รายการหนึ่งอาจไม่มี QR เลย โดยถูกต้อง และลิงก์คือทางเดียวที่จ่ายได้ — อ่านทั้งสองฟิลด์แล้วเลือกอันที่มีค่า ใช้ได้ทุกกรณีและจะได้
""เช่นกันเมื่อการติดตั้งนั้นไม่มีหน้านี้เลย
#สร้างรายการจ่ายเงินออก (Create Withdraw)
สร้างคำขอถอน/จ่ายเงินออกไปยังบัญชีธนาคาร
POST /v1/payments/withdraw → 201 Created
การจ่ายเงินออกใช้เงินจากยอดคงเหลือที่ใช้ได้ของคุณ ระบบจะกันยอด (จำนวนเงิน + ค่าธรรมเนียม) ไว้ล่วงหน้า หากยอดคงเหลือไม่พอ คำขอจะถูกปฏิเสธทันที
#Request Body
| ฟิลด์ | ชนิด | จำเป็น | การตรวจสอบ / คำอธิบาย |
|---|---|---|---|
amount | number | ใช่ | ต้อง > 0 ที่เกตเวย์ ขั้นต่ำเด็ดขาด 100.00 บาท และต้องอยู่ในช่วงขั้นต่ำ/ขั้นสูงที่ตั้งไว้ในบัญชีของคุณ |
currency | string | ใช่ | ความยาว 3 ตัวอักษรพอดี |
reference_id | string | ใช่ | เลขอ้างอิงของคุณ ยาว 1–64 ตัวอักษร ไม่มีการตัดรายการซ้ำ |
bank_code | string | ใช่ | ความยาว 3 ตัวอักษรพอดี ดูหัวข้อรหัสธนาคาร |
account_number | string | ใช่ | เลขบัญชีปลายทาง ยาว 10–20 ตัวอักษร |
account_holder_name | string | ใช่ | ชื่อเจ้าของบัญชีปลายทาง ยาว 1–100 ตัวอักษร |
webhook_url | string | ไม่ | ต้องอยู่ในรูปแบบ URL ที่ถูกต้อง ระบบส่ง webhook ก็ต่อเมื่อมีฟิลด์นี้ |
การจ่ายเงินออกไม่มีฟิลด์ description — ตัวถอดรหัส JSON รับค่านี้ได้แต่ระบบจะไม่นำไปใช้
การกันจ่ายซ้ำ หากมีรายการจ่ายเงินออกที่เหมือนกันทุกประการ (ร้านค้าเดียวกัน รหัสธนาคาร เลขบัญชี และจำนวนเงินเดียวกัน) ถูกสร้างขึ้นภายใน 5 นาที ที่ผ่านมา รายการใหม่จะ ไม่ถูกส่งออก แต่จะถูกสร้างไว้ กันยอดไว้ และรออยู่ในสถานะ
pendingเพื่อให้ตรวจสอบด้วยคน มาตรการนี้กันกรณีที่ระบบต้นทางส่งซ้ำด้วยreference_idใหม่แล้วทำให้จ่ายเงินซ้ำสองครั้ง ให้ติดตามผลด้วยGET /v1/payments/{id}หรือรอ webhook แทนการส่งคำขอซ้ำ
#รหัสธนาคาร
รหัสเหล่านี้คือรหัสที่ระบบรู้จักเมื่อต้องแปลงเป็นชื่อธนาคาร (bankName) ใน webhook
ให้ส่งเป็นรหัสธนาคาร 3 หลักของธนาคารแห่งประเทศไทย
| Code | Thai Name | English Name |
|---|---|---|
002 | ธนาคารกรุงเทพ | Bangkok Bank PCL (BBL) |
004 | ธนาคารกสิกรไทย | Kasikornbank PCL (KBank) |
006 | ธนาคารกรุงไทย | Krungthai Bank PCL (KTB) |
011 | ธนาคารทหารไทยธนชาต | TMBThanachart Bank PCL (TTB) |
014 | ธนาคารไทยพาณิชย์ | Siam Commercial Bank PCL (SCB) |
017 | ธนาคารซิตี้แบงก์ | Citibank N.A. |
020 | ธนาคารสแตนดาร์ดชาร์เตอร์ด (ไทย) | Standard Chartered Bank (Thai) PCL |
022 | ธนาคารซีไอเอ็มบี ไทย | CIMB Thai Bank PCL |
024 | ธนาคารยูโอบี | United Overseas Bank (Thai) PCL |
025 | ธนาคารกรุงศรีอยุธยา | Bank of Ayudhya PCL (Krungsri) |
026 | ธนาคารเมกะสากลพาณิชย์ | Mega International Commercial Bank |
030 | ธนาคารออมสิน | Government Savings Bank (GSB) |
031 | ธนาคารฮ่องกงและเซี่ยงไฮ้ | HSBC Thailand |
032 | ธนาคารดอยซ์แบงก์ | Deutsche Bank |
033 | ธนาคารอาคารสงเคราะห์ | Government Housing Bank (GHB) |
034 | ธนาคารเพื่อการเกษตรฯ | BAAC |
039 | ธนาคารมิซูโฮ | Mizuho Bank |
045 | ธนาคารบีเอ็นพี พารีบาส์ | BNP Paribas |
052 | ธนาคารแห่งประเทศจีน | Bank of China (Thai) |
065 | ธนาคารธนชาต | Thanachart Bank PCL |
066 | ธนาคารอิสลามแห่งประเทศไทย | Islamic Bank of Thailand |
067 | ธนาคารทิสโก้ | TISCO Bank PCL |
069 | ธนาคารเกียรตินาคินภัทร | Kiatnakin Phatra Bank PCL (KKP) |
070 | ธนาคารไอซีบีซี (ไทย) | ICBC (Thai) PCL |
071 | ธนาคารไทยเครดิต | Thai Credit Retail Bank |
073 | ธนาคารแลนด์ แอนด์ เฮ้าส์ | Land and Houses Bank PCL (LH Bank) |
รหัสที่อยู่นอกตารางนี้ระบบยังรับได้ตราบใดที่ยาว 3 ตัวอักษรพอดี แต่ค่า bankName ใน webhook
จะสะท้อนกลับเป็นตัวรหัสนั้นเอง
#การจ่ายเงินออกแบบ PromptPay — ยังไม่รองรับผ่าน API นี้
ระบบตรวจ bank_code ว่าต้อง ยาว 3 ตัวอักษรพอดี ค่าตรงตัวอย่าง PROMPTPAY จึงถูกปฏิเสธ
ด้วย 400 INVALID_REQUEST แม้ผู้ให้บริการจ่ายเงินปลายทางจะรองรับ PromptPay proxy อยู่
(เลขบัญชี 10 หลักจะถูกส่งเป็น proxy แบบ MOBILE ส่วนที่ยาวกว่านั้นเป็น TXID)
แต่ปัจจุบันยังเรียกใช้เส้นทางนั้นผ่าน public API ไม่ได้ ให้ใช้รหัสธนาคารกับเลขบัญชีธนาคารแทน
#ตัวอย่างคำขอ
{
"amount": 5000.00,
"currency": "THB",
"reference_id": "ORD888888889",
"bank_code": "014",
"account_number": "1234567890",
"account_holder_name": "John Doe",
"webhook_url": "https://example.com/path/to/your/webhook"
}#Response
{
"id": "660e8400-e29b-41d4-a716-446655440000",
"reference_id": "ORD888888889",
"type": "withdraw",
"status": "pending",
"amount": 5000.00,
"currency": "THB",
"created_at": "2026-09-20T18:00:00+07:00"
}ค่า status ตอนสร้างจะเป็น pending เมื่อรายการเข้าคิวรอตรวจสอบหรือถูกกันไว้เพราะสงสัยว่าซ้ำ
และเป็น processing เมื่อส่งต่อให้ผู้ให้บริการจ่ายเงินแล้ว ทั้งสองค่ายังไม่ใช่สถานะสุดท้าย
ให้รอ webhook หรือติดตามผลเอง
การจ่ายเงินออกจะไม่คืนค่า qr_code, qr_code_image, paid_amount หรือ expires_at
#ตัวอย่างโค้ด
#Python
# Create withdraw
response = make_request("POST", "/v1/payments/withdraw", {
"amount": 5000.00,
"currency": "THB",
"reference_id": "ORD888888889",
"bank_code": "014",
"account_number": "1234567890",
"account_holder_name": "John Doe",
"webhook_url": "https://example.com/path/to/your/webhook"
})
print(response.json())#Node.js
// Create withdraw
makeRequest("POST", "/v1/payments/withdraw", {
amount: 5000.0,
currency: "THB",
reference_id: "ORD888888889",
bank_code: "014",
account_number: "1234567890",
account_holder_name: "John Doe",
webhook_url: "https://example.com/path/to/your/webhook",
}).then((res) => console.log(res.data));#PHP
// Create withdraw
$response = makeRequest('POST', '/v1/payments/withdraw', [
'amount' => 5000.00,
'currency' => 'THB',
'reference_id' => 'ORD888888889',
'bank_code' => '014',
'account_number' => '1234567890',
'account_holder_name' => 'John Doe',
'webhook_url' => 'https://example.com/path/to/your/webhook'
]);
print_r($response);#Go
// Create withdraw
result, _ := makeRequest("POST", "/v1/payments/withdraw", map[string]interface{}{
"amount": 5000.00,
"currency": "THB",
"reference_id": "ORD888888889",
"bank_code": "014",
"account_number": "1234567890",
"account_holder_name": "John Doe",
"webhook_url": "https://example.com/path/to/your/webhook",
})
fmt.Printf("%+v\n", result)#ดูยอดคงเหลือ (Get Balance)
คืนสรุปยอดคงเหลือของร้านค้าที่เรียกใช้ ตาม environment ของร้านค้านั้น
GET /v1/payments/get-balance → 200 OK
ไม่มีพารามิเตอร์ — ระบบดูว่าเป็นร้านค้าใดจาก API key
{
"available_balance": 125340.50,
"pending_balance": 3000.00,
"total_deposited": 980000.00,
"total_withdrawn": 854659.50
}| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
available_balance | number | เงินที่ถอนออกได้ทันที |
pending_balance | number | เงินที่ถูกกันไว้โดยรายการถอนที่กำลังดำเนินการ หรือยังไม่เคลียร์ |
total_deposited | number | ยอดรับเงินสะสมทั้งหมด |
total_withdrawn | number | ยอดจ่ายเงินออกสะสมทั้งหมด |
การเซ็นทำเหมือน GET อื่น ๆ คือ GET|/v1/payments/get-balance|<timestamp>
#ดูรายการชำระเงิน (Get Payment)
ดึงรายละเอียดของรายการชำระเงินจากรหัสรายการ
GET /v1/payments/{id} → 200 OK
#พารามิเตอร์ใน path
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
id | string | รหัสรายการ (UUID) ที่ได้ตอนสร้างรายการ |
การค้นหาจำกัดอยู่เฉพาะร้านค้าของคุณและ environment ของคุณ หากเป็นรายการของร้านค้าอื่น
ระบบจะตอบ 404 NOT_FOUND เหมือนกับกรณีที่ไม่มีรายการนั้นอยู่จริง
#ตัวอย่าง Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"reference_id": "ORD888888888",
"type": "deposit",
"status": "completed",
"amount": 1500.00,
"currency": "THB",
"created_at": "2026-09-20T17:30:00+07:00",
"expires_at": "2026-09-20T17:40:00+07:00"
}ข้อมูล QR คืนให้เฉพาะตอนสร้างรายการเท่านั้น endpoint นี้ ไม่ คืน
qr_code,qr_code_image,paid_amountและpayment_urlให้เก็บค่าเหล่านี้จาก response ตอนสร้างรายการรับเงินไว้เอง ส่วนexpires_atจะไม่มีในรายการจ่ายเงินออก
API รับ-จ่ายเงินไม่มีการค้นหาด้วย reference_id หากต้องการค้นด้วยเลขที่คำสั่งซื้อของคุณเอง
ให้ใช้ GET /v1/merchant-reports/transactions?q=<order id>
#ยกเลิกรายการ (Cancel Payment)
ยกเลิกรายการที่ยังรอชำระ ยกเลิกได้เฉพาะรายการที่สถานะเป็น pending เท่านั้น
สถานะอื่นจะได้ 400 PAYMENT_CANNOT_BE_CANCELLED
POST /v1/payments/{id}/cancel → 200 OK
คำขอนี้ ไม่มี body จึงเซ็นเพียงสามส่วน:
POST|/v1/payments/<id>/cancel|<timestamp>
#พารามิเตอร์ใน path
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
id | string | รหัสรายการที่ต้องการยกเลิก |
#ตัวอย่าง Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"reference_id": "ORD888888888",
"type": "deposit",
"status": "failed",
"amount": 1500.00,
"currency": "THB",
"created_at": "2026-09-20T17:30:00+07:00"
}รายการที่ยกเลิกแล้วจะรายงานสถานะเป็น
status: "failed"โดยมีเหตุผลความล้มเหลว ภายในระบบว่าCancelled by merchantAPI จะไม่คืนสถานะcancelledสำหรับรายการ ที่สร้างผ่าน API นี้ ให้ถือว่าfailedหลังการยกเลิกสำเร็จคือ "ยกเลิกโดยฉันเอง"
#อัปโหลดสลิป (กู้รายการรับเงินที่หมดอายุ)
อัปโหลดรูปสลิปโอนเงินให้กับรายการรับเงินที่เข้าสู่สถานะ expired แล้ว เพื่อให้ระบบตรวจสอบ
และเข้ายอดให้ โดยไม่ต้องผ่านแดชบอร์ดหรือผู้ดูแลระบบ
POST /v1/payments/{id}/upload-slip → 200 OK
ชนิดเนื้อหา: multipart/form-data มีฟิลด์ไฟล์เดียวชื่อ file (ไม่เกิน 10 MB)
#รูปแบบลายเซ็นที่ต่างออกไป
body แบบ multipart ไม่สามารถสร้างซ้ำให้ตรงกันทุกไบต์ได้ในทุก HTTP client เส้นทางนี้ จึงเซ็น ค่าแฮชของไฟล์ แทน body:
SignatureData = METHOD|PATH|TIMESTAMP|X-Content-SHA256X-Content-SHA256 คือ SHA-256 ของไบต์ไฟล์ในรูปเลขฐานสิบหกตัวพิมพ์เล็ก และเป็นค่าที่
จำเป็นต้องส่ง เซิร์ฟเวอร์จะคำนวณแฮชของไฟล์ที่ได้รับใหม่และปฏิเสธหากไม่ตรงกัน
TXN_ID="550e8400-e29b-41d4-a716-446655440000"
REQ_PATH="/v1/payments/$TXN_ID/upload-slip"
TS=$(date +%s)
HASH=$(sha256sum slip.jpg | cut -d' ' -f1)
SIG=$(printf "POST|%s|%s|%s" "$REQ_PATH" "$TS" "$HASH" \
| openssl dgst -sha256 -hmac "$SECRET_KEY" -hex | sed 's/^.* //')
curl -X POST "https://api.paymenow.asia$REQ_PATH" \
-H "X-API-Key: $API_KEY" \
-H "X-Timestamp: $TS" \
-H "X-Content-SHA256: $HASH" \
-H "X-Signature: $SIG" \
-F "[email protected]"#กติกา
- รายการต้องอยู่ในสถานะ
expiredเท่านั้น หากเป็นpendingหรือสำเร็จไปแล้ว ระบบจะปฏิเสธโดยไม่ตรวจสลิปเลย - ต้องอัปโหลดสลิปภายใน 24 ชั่วโมง นับจากเวลาที่รายการหมดอายุ
- เมื่ออัปโหลดสำเร็จ รายการจะเปลี่ยนเป็น
completedและเข้ายอดคงเหลือทันที หากอัปโหลดซ้ำจะได้NOT_ELIGIBLEและจะไม่มีการเข้ายอดซ้ำ — หนึ่งสลิปเข้ายอดได้ครั้งเดียว
#Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"reference": "ORD888888888",
"type": "deposit",
"status": "completed",
"amount": 1000.00,
"fee": 25.00,
"net_amount": 975.00,
"currency": "THB",
"slip_trans_ref": "01490000...",
"credited": true
}#เหตุผลที่ถูกปฏิเสธ
| HTTP | code | ความหมาย |
|---|---|---|
| 400 | NOT_ELIGIBLE | รายการไม่ได้อยู่ในสถานะ expired |
| 400 | EXPIRED_TOO_OLD | เลย 24 ชั่วโมงนับจากเวลาหมดอายุแล้ว |
| 400 | AMOUNT_MISMATCH | จำนวนเงินในสลิปไม่ตรงกับรายการ |
| 400 | RECEIVER_NOT_RECOGNIZED | สลิปไม่ได้โอนเข้าบัญชีรับเงินของรายการนี้ |
| 400 | SLIP_TOO_OLD | เวลาโอนบนสลิปอยู่นอกช่วงที่อนุญาต |
| 400 | SLIP_ALREADY_USED | สลิปนี้ถูกใช้ไปแล้ว (โดยคุณเองหรือร้านค้าอื่น) |
| 400 | PAYER_BANK_MISMATCH | ธนาคารต้นทางบนสลิปต่างจากธนาคารของผู้ชำระเงินที่แจ้งไว้ |
| 400 | SLIP_INVALID | อ่านสลิปไม่ได้ หรือไม่ใช่สลิปที่ถูกต้อง |
| 400 | CONTENT_HASH_MISMATCH | ไบต์ของไฟล์ที่อัปโหลดไม่ตรงกับ X-Content-SHA256 |
| 400 | FILE_REQUIRED | ไม่มีฟิลด์ file ใน body แบบ multipart |
| 401 | MISSING_CONTENT_HASH | ไม่มี header X-Content-SHA256 |
| 404 | NOT_FOUND | ไม่พบรายการรหัสนี้ของร้านค้าคุณ |
| 413 | FILE_TOO_LARGE | ไฟล์ใหญ่เกิน 10 MB |
#รายงานสำหรับร้านค้า (ERP)
GET /v1/merchant-reports/daily-summary, /transactions, /statement,
/statement/entries และ /refunds ยืนยันตัวตนเหมือน API รับ-จ่ายเงินทุกประการ
(คีย์เดียวกัน ลายเซ็นแบบเดียวกัน รายการ IP ชุดเดียวกัน) และให้บริการบนโฮสต์เดียวกัน
คืนข้อมูลเป็น JSON, CSV หรือ XLSX มีโควตาการเรียกแยกของตัวเองต่อร้านค้า และเป็นวิธีที่
รองรับอย่างเป็นทางการสำหรับการดึงรายการธุรกรรม กระทบยอดคงเหลือ และดูประวัติการคืนเงิน
รายละเอียดทั้งหมดอยู่ใน Merchant Reports API (ERP)
#Health
GET /health และ GET /health/detailed ไม่ต้องยืนยันตัวตน และรายงานว่าเกตเวย์กับ
Redis ที่เกตเวย์ใช้งานอยู่ทำงานปกติหรือไม่:
{ "status": "healthy", "environment": "production" }หากมีส่วนประกอบใดล่มจะตอบ 503 พร้อม "status": "unhealthy" ค่าเหล่านี้สะท้อนเฉพาะ
ตัวโปรเซสของ API gateway เท่านั้น ไม่ใช่หน้าสถานะของทั้งแพลตฟอร์ม และไม่ได้บอกอะไร
เกี่ยวกับผู้ให้บริการชำระเงินหรือการเชื่อมต่อกับธนาคาร
หน้านี้แปลจากเอกสารต้นฉบับภาษาอังกฤษ ส่วนที่เป็นค่าทางเทคนิค — path, ชื่อฟิลด์, header, รหัสข้อผิดพลาด และชื่อคอลัมน์ในไฟล์ส่งออก — คงไว้เป็นภาษาอังกฤษตามที่ระบบใช้จริง

