Endpoints

Endpoints

ระบบมี 2 endpoint สำหรับ Merchant

orgId และ merchantId จะได้รับจากผู้ให้บริการเมื่อสมัครใช้งาน ไม่ต้องสร้างเอง


สร้างคำขอรับเงิน (Pay-In)

POST https://api.please-payment.com/api/PaymentRequest/org/{orgId}/action/SubmitPayInRequest/{merchantId}

สร้าง Payment Request แล้วได้รับ QR Code สำหรับให้ลูกค้า scan และโอนเงินเข้าบัญชีของ Merchant โดยตรง

Request Body

Field Type Required คำอธิบาย
RefId1 string ✅ Reference ID จาก Merchant (ต้องไม่ซ้ำกัน)
RefId2 string ❌ Reference เพิ่มเติม 2
RefId3 string ❌ Reference เพิ่มเติม 3
PayerName string ✅ ชื่อผู้จ่าย
RequestedAmount number ✅ จำนวนเงิน (ต้องมากกว่า 0 และอยู่ใน range ที่ Merchant กำหนด)
Currency string ✅ สกุลเงิน — ปัจจุบันรองรับเฉพาะ THB
QrProvider string ✅ ธนาคารที่ออก QR — PP (PromptPay) หรือ SCB
Description string ❌ คำอธิบายรายการ
CustomerEmail string ❌ อีเมลของลูกค้า
CustomerPhone string ❌ เบอร์โทรของลูกค้า
Tags string ❌ Tag สำหรับจัดกลุ่มรายการ

ตัวอย่าง Request

{
  "RefId1": "ORDER-20260701-001",
  "PayerName": "สมชาย ใจดี",
  "RequestedAmount": 325,
  "Currency": "THB",
  "QrProvider": "PP",
  "Description": "ชำระค่าสินค้า",
  "RefId2": "CUST-12345"
}

Response

{
  "status": "OK",
  "description": "Success",
  "paymentResponse": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "sessionId": "session-abc123",
    "type": "PayIn",
    "status": "Pending",
    "requestedAmount": 325.00,
    "generatedAmount": 325.52,
    "currency": "THB",
    "qrCode": "00020101021...",
    "qrCodeImage": "data:image/png;base64,...",
    "paymentUrl": "https://...",
    "websocketPath": "/realtime/payment-tx",
    "createdAt": "2026-07-01T10:00:00Z",
    "expireAt": "2026-07-01T10:15:00Z",
    "isQrAvailable": true,
    "payInBankCode": "SCB",
    "payInBankAccountNo": "xxx-xxxxx-x",
    "payInBankAccountName": "ชื่อบริษัท",
    "payInPromptPayId": null,
    "slipUploadUrl": "/payin-slip-upload/org123/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4-..."
  }
}

Response Fields

Field คำอธิบาย
id UUID ของ Payment Request — เก็บไว้สำหรับ reference
status สถานะปัจจุบัน (ดู สถานะการชำระเงิน)
requestedAmount จำนวนเงินที่ขอ
generatedAmount จำนวนเงินที่ใช้จริง (อาจมีเศษสตางค์ random เพื่อ matching)
isQrAvailable true หาก QR Code พร้อมให้ลูกค้า scan, false หากบัญชีปลายทางไม่รองรับ QR (เช่น ไม่ได้ผูกกับ PromptPay) — ดูรายละเอียดด้านล่าง
qrCodeImage รูป QR Code เป็น Base64 — นำไปแสดงในแอปได้เลย (ว่างเปล่าหาก isQrAvailable เป็น false)
payInBankCode รหัสธนาคารปลายทาง
payInBankAccountNo เลขบัญชีปลายทาง
payInBankAccountName ชื่อบัญชีปลายทาง
payInPromptPayId หมายเลข PromptPay ปลายทาง (ถ้ามี)
sessionId ใช้เชื่อมต่อ WebSocket เพื่อรับสถานะแบบ real-time
websocketPath path สำหรับ WebSocket (/realtime/payment-tx)
expireAt QR Code หมดอายุเมื่อไหร่
slipUploadUrl Relative path สำหรับหน้าอัปโหลดสลิป — ไม่มี domain นำหน้า ต้องนำไปต่อกับ https://merchant.please-payment.com (ดูคำอธิบายด้านล่าง) เพื่อสร้าง URL เต็ม แล้วส่งให้ลูกค้าเปิดหน้าอัปโหลดสลิปได้โดยไม่ต้อง login

สำคัญ — ต้อง concat กับโดเมนไหน: slipUploadUrl เป็น relative path เท่านั้น ต้องนำไปต่อกับโดเมน https://merchant.please-payment.com เอง เช่น หาก slipUploadUrl คือ /payin-slip-upload/org123/xxx/yyy ก็ให้สร้าง URL เต็มเป็น https://merchant.please-payment.com/payin-slip-upload/org123/xxx/yyy

การแสดงผล QR และข้อมูลบัญชี

ควรตรวจสอบ isQrAvailable ก่อนแสดงผลเสมอ:

สถานการณ์ วิธีแสดงผล
isQrAvailable = true แสดง QR Code จาก qrCodeImage ให้ลูกค้า scan ตามปกติ
isQrAvailable = false ไม่มี QR Code — แสดงข้อมูลบัญชี (payInBankCode, payInBankAccountNo, payInBankAccountName, payInPromptPayId) เพื่อให้ลูกค้ากรอกข้อมูลโอนเงินเอง

หมายเหตุ: แนะนำให้แสดงข้อมูลบัญชี (payInBankCode, payInBankAccountNo, payInBankAccountName, payInPromptPayId) ควบคู่กับ QR Code เสมอ — ลูกค้าบางรายอาจต้องการโอนด้วยตัวเองแม้มี QR

แนะนำ: นำ slipUploadUrl ไปทำเป็น QR Code แสดงในหน้าชำระเงินของคุณ — ลูกค้าสแกน QR ด้วยกล้องมือถือแล้วเปิดหน้าอัปโหลดสลิปได้เลย ไม่ต้องพิมพ์ URL เอง ใช้ได้ทั้ง Pay-In ปกติ และ Pay-In P2P

หน้าอัปโหลดสลิป

เมื่อลูกค้าเปิด Slip Upload URL ลูกค้าจะเจอหน้าอัปโหลดสลิปสำหรับ Payment Request นั้นๆ ซึ่งมีฟีเจอร์ดังนี้:

  • อัปโหลดรูปสลิป — เลือกรูปจากกล้องหรือ Gallery ของมือถือ
  • เลขอ้างอิงสลิป — กรอก 4 หลักแรกและ 4 หลักสุดท้ายของเลขอ้างอิงสลิป (alphanumeric) เพื่อ matching และตรวจจับสลิปซ้ำ
  • หมายเหตุ — ช่องเสริมสำหรับข้อความเพิ่มเติม
  • ตรวจสอบสลิปซ้ำ — ระบบแจ้งเตือนอัตโนมัติถ้าพบสลิปที่มีเลขอ้างอิงเดียวกันในระบบแล้ว
Upload Payment Slip
อัปโหลดสลิปการโอนเงิน

Select a payment slip image to upload

Tap to select image
JPG, PNG, WebP
—
First 4 digits Last 4 digits
⚠️
พบสลิปซ้ำในระบบ!
หากพบเลขอ้างอิงเดียวกัน ระบบจะแสดงคำเตือน พร้อมตัวเลือก อัปโหลดต่อไป หรือ ยกเลิก

ลูกค้าไม่ต้อง login เพื่อใช้หน้านี้ — URL มี token ฝังอยู่แล้ว และหมดอายุใน 24 ชั่วโมง

แม้ HTTP status code จะเป็น 200 แต่ต้องตรวจสอบ status ใน response body ด้วย — ถ้า "OK" คือสำเร็จ ถ้าค่าอื่นคือมีข้อผิดพลาด (ดู การจัดการ Error)


สร้างคำขอรับเงินแบบ P2P (Pay-In P2P)

POST https://api.please-payment.com/api/PaymentRequest/org/{orgId}/action/SubmitPayInRequestP2P/{merchantId}

สร้าง Pay-In Request แบบ Peer-to-Peer (P2P) — ระบบจะจับคู่กับ Pay-Out Request ที่รอดำเนินการอยู่โดยอัตโนมัติ แล้วให้ลูกค้าโอนเงินตรงไปยังบัญชีของผู้รับ (แทนที่จะโอนผ่าน QR Code ของระบบ)

P2P คืออะไร? แทนที่เงินจะเข้าบัญชีของ Merchant ก่อน แล้วค่อยโอนออก — P2P ให้ผู้ส่งโอนตรงถึงผู้รับเลย ระบบทำหน้าที่จับคู่และยืนยัน

Request Body

Field Type Required คำอธิบาย
RefId1 string ✅ Reference ID จาก Merchant (ต้องไม่ซ้ำกัน)
RefId2 string ❌ Reference เพิ่มเติม 2
RefId3 string ❌ Reference เพิ่มเติม 3
PayerName string ✅ ชื่อผู้จ่าย
RequestedAmount number ✅ จำนวนเงิน (ต้องมากกว่า 0 และอยู่ใน range ที่ Merchant กำหนด)
Currency string ✅ สกุลเงิน — ปัจจุบันรองรับเฉพาะ THB
QrProvider string ✅ PP หรือ SCB (ระบบใช้สำหรับ internal matching)
Description string ❌ คำอธิบายรายการ

ตัวอย่าง Request

{
  "RefId1": "P2P-ORDER-20260701-001",
  "PayerName": "สมชาย ใจดี",
  "RequestedAmount": 1000,
  "Currency": "THB",
  "QrProvider": "PP"
}

Response

{
  "status": "OK",
  "description": "Success",
  "paymentResponse": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "type": "PayIn",
    "status": "Pending",
    "requestedAmount": 1000.00,
    "generatedAmount": 1000.00,
    "currency": "THB",
    "qrCode": null,
    "qrCodeImage": "",
    "isQrAvailable": false,
    "payInBankCode": "KBANK",
    "payInBankAccountNo": "012-3-45678-9",
    "payInBankAccountName": "ชื่อผู้รับปลายทาง",
    "payInPromptPayId": "0812345678",
    "slipUploadUrl": "/payin-slip-upload/org123/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4-..."
  }
}

ความแตกต่างจาก Pay-In ปกติ

Pay-In ปกติ Pay-In P2P
isQrAvailable true (ส่วนใหญ่) false (ส่วนใหญ่) — บัญชี P2P มักไม่ผูกกับ PromptPay
qrCodeImage รูป QR Code ว่างเปล่า ("") เมื่อ isQrAvailable = false
payInBankAccountName บัญชี Merchant บัญชีของผู้รับปลายทาง (จาก Pay-Out Request ที่จับคู่)
การโอนเงิน สแกน QR Code โอนตรงไปยังบัญชีที่ระบุใน response (กรอกข้อมูลบัญชีเอง)
slipUploadUrl ✅ ✅ (สำคัญมาก — ลูกค้าต้องอัปโหลดสลิปเป็นหลักฐาน)

สำคัญ: สำหรับ P2P — isQrAvailable มักเป็น false เพราะบัญชีปลายทางอาจไม่ผูกกับ PromptPay ในกรณีนี้ ต้องแสดงข้อมูลบัญชี (payInBankCode, payInBankAccountNo, payInBankAccountName, payInPromptPayId) เพื่อให้ลูกค้ากรอกโอนเงินเองด้วยตัวเอง พร้อมทั้งแสดง slipUploadUrl เพื่อให้อัปโหลดสลิปหลักฐานการโอน

สำคัญ — ต้อง concat กับโดเมนไหน: slipUploadUrl เป็น relative path เช่นเดียวกับ Pay-In ปกติ ต้องนำไปต่อกับ https://merchant.please-payment.com เอง เช่น https://merchant.please-payment.com/payin-slip-upload/org123/xxx/yyy (ดูคำอธิบายเต็มในหัวข้อ Response Fields ด้านบน)

แนะนำ: นำ slipUploadUrl ไปทำเป็น QR Code แสดงควบคู่กับข้อมูลบัญชีปลายทาง — ลูกค้าโอนเงินแล้วสแกน QR เปิดหน้าอัปโหลดสลิปได้เลยโดยไม่ต้องพิมพ์ URL เอง (ดูตัวอย่างหน้าอัปโหลดสลิปด้านบน)

Error ERROR_NO_P2P_ACCOUNT_MATCH: หากไม่มี Pay-Out Request ที่รอดำเนินการอยู่ในระบบ จะได้รับ error นี้ — แปลว่าในขณะนั้นไม่มีรายการที่สามารถจับคู่ได้


สร้างคำขอโอนเงินออก (Pay-Out)

POST https://api.please-payment.com/api/PaymentRequest/org/{orgId}/action/SubmitPayOutRequest/{merchantId}

สร้างคำขอโอนเงินออกไปยังบัญชีปลายทาง

Request Body

Field Type Required คำอธิบาย
RefId1 string ✅ Reference ID จาก Merchant (ต้องไม่ซ้ำกัน)
RefId2 string ❌ Reference เพิ่มเติม 2
RefId3 string ❌ Reference เพิ่มเติม 3
RequestedAmount number ✅ จำนวนเงิน (ต้องมากกว่า 0)
QrProvider string ✅ ต้องเป็น PP (PromptPay เท่านั้น สำหรับ Pay-Out)
BankCode string ✅ รหัสธนาคารปลายทาง เช่น SCB, KBANK, BAY — ดูรหัสธนาคารที่รองรับทั้งหมด
BankAccountNo string ✅ เลขบัญชีปลายทาง
BankAccountName string ✅ ชื่อบัญชีปลายทาง
PromptPayId string ❌ หมายเลข PromptPay ปลายทาง
AccountType string ❌ ประเภทบัญชี: Native หรือ PromptPay

ข้อมูลบัญชีปลายทาง: ต้องส่ง BankCode+BankAccountNo+BankAccountName เข้ามาเสมอทุกครั้ง (ดูรหัสธนาคารที่รองรับ) แม้จะโอนผ่าน PromptPay ก็ตาม — ถ้าทราบหมายเลข PromptPay ของปลายทางด้วย สามารถส่ง PromptPayId+AccountType เพิ่มเติมได้ หรือจะส่ง PayinBankAccountId (ID จากระบบ) แทนทั้งหมดนี้ก็ได้เช่นกัน

แนะนำ: หากทราบหมายเลข PromptPay ของบัญชีปลายทาง แนะนำให้ส่ง PromptPayId มาด้วย เนื่องจากการโอนผ่าน PromptPay จะช่วยให้ระบบประมวลผลได้เร็วขึ้น และผู้รับได้รับเงินได้รวดเร็วยิ่งขึ้น

ตัวอย่าง Request (โอนผ่านบัญชีธนาคาร)

{
  "RefId1": "PAYOUT-20260701-001",
  "RequestedAmount": 500,
  "QrProvider": "PP",
  "BankCode": "KBANK",
  "BankAccountNo": "0123456789",
  "BankAccountName": "สมชาย ใจดี",
  "AccountType": "Native"
}

ตัวอย่าง Request (โอนผ่าน PromptPay)

{
  "RefId1": "PAYOUT-20260701-002",
  "RequestedAmount": 200,
  "QrProvider": "PP",
  "PromptPayId": "0812345678",
  "AccountType": "PromptPay"
}

Response

{
  "status": "OK",
  "description": "Success",
  "paymentResponse": {
    "id": "7bc95f12-3a21-4f89-c4ed-1d852a77bfc8",
    "type": "PayOut",
    "status": "Pending",
    "requestedAmount": 500.00,
    "currency": "THB",
    "createdAt": "2026-07-01T10:05:00Z"
  }
}

สร้างคำขอถอนเงิน (Withdrawal)

POST https://api.please-payment.com/api/PaymentRequest/org/{orgId}/action/SubmitWithdrawalRequest/{merchantId}

ใช้ endpoint นี้เมื่อ Merchant เองต้องการถอนเงินออกไปยังบัญชีของตัวเอง ต่างจาก Pay-Out ทั่วไปที่เป็นการโอนเงินออกไปให้ ลูกค้า ของ Merchant — ภายในระบบจะสร้างคำขอชนิดเดียวกับ Pay-Out ทุกประการ เพียงแต่ติด flag ว่าเป็น withdrawal เพื่อให้แยกออกจาก Pay-Out ปกติในรายงานต่าง ๆ

Request body, วิธีคิดค่าธรรมเนียม, รูปแบบ Response และ Webhook เหมือนกับ สร้างคำขอโอนเงินออก (Pay-Out) ทุกอย่าง 100% — ต่างกันแค่ endpoint path (SubmitWithdrawalRequest แทน SubmitPayOutRequest) เท่านั้น ส่วนที่อธิบายไว้ด้านบนสำหรับ Pay-Out ใช้กับ endpoint นี้ได้เหมือนกันทุกประการ

Request Body

เหมือนกับ สร้างคำขอโอนเงินออก (Pay-Out) — RefId1, RefId2, RefId3, RequestedAmount, QrProvider และข้อมูลบัญชีปลายทาง (BankCode+BankAccountNo+BankAccountName, หรือ PromptPayId+AccountType, หรือ PayinBankAccountId)

ตัวอย่าง Request

{
  "RefId1": "WITHDRAW-20260701-001",
  "RequestedAmount": 500,
  "QrProvider": "PP",
  "BankCode": "KBANK",
  "BankAccountNo": "0123456789",
  "BankAccountName": "สมชาย ใจดี",
  "AccountType": "Native"
}

Response

{
  "status": "OK",
  "description": "Success",
  "paymentResponse": {
    "id": "7bc95f12-3a21-4f89-c4ed-1d852a77bfc8",
    "type": "PayOut",
    "status": "Pending",
    "requestedAmount": 500.00,
    "currency": "THB",
    "createdAt": "2026-07-01T10:05:00Z"
  }
}

Webhook: ไม่มี event ใหม่ — คำขอถอนเงินยังคงยิง event PaymentOut.Success / PaymentOut.Rejected เหมือนที่อธิบายไว้ใน Webhooks พร้อม payload fields แบบเดียวกันทุกประการ