Live P2P API — ขอบเขตที่พัฒนาแล้ว
สถานะ: implementation 0092 — รอตรวจและ deploy
หน้านี้อธิบายโค้ดที่พัฒนาแล้ว ไม่ได้ยืนยันว่าเปิดให้ใช้บน production ของคุณแล้ว ให้ผู้ให้บริการยืนยันรุ่นและการตั้งค่า Merchant ก่อนเชื่อมต่อเงินจริง เอกสารส่วนที่ติดป้าย Target contract อธิบายขอบเขตที่กว้างกว่าและไม่ได้เปิดครบในรุ่นนี้
ใช้ https://api.<โดเมน White Label> กับ Live key และ HMAC เดิม (PG-Version: 2026-08-01) environment มาจาก hostname และ credential ไม่รับ field หรือ header สำหรับเปลี่ยนเป็น Live/Test
Endpoint ในขอบเขตนี้
| Method และ path | สิทธิ์ของ key | ผลลัพธ์ |
|---|---|---|
POST /v1/pay/withdrawals | withdrawals:write | สร้าง P2P payout และกันยอด รอการอนุมัติสองคน |
GET /v1/pay/withdrawals/{id} | withdrawals:read | สถานะและยอดของรายการถอนเต็มใบ |
GET /v1/pay/withdrawals | withdrawals:read | รายการถอนของ Merchant นี้ |
GET /v1/pay/deposits | deposits:read | สรุปรายการฝาก ไม่มีบัญชีรับโอน QR หรือคำสั่งชำระเงิน |
GET /v1/pay/balance | wallet:read | ยอด available, pending clearing และ reserved |
GET /v1/pay/events | wallet:read | อ่าน business event ต่อด้วย sequence |
เส้นทางสร้าง/อ่านรายการฝากเดิมยังใช้ flow เดิม รุ่นนี้ไม่ได้เพิ่ม Customer API, API ลงทะเบียน beneficiary, inline beneficiary, Merchant quote หรือคำสั่งยกเลิกรายการถอน
เตรียม key และบัญชีปลายทาง
Live key ใหม่เลือกได้เฉพาะ deposits:read, deposits:write, withdrawals:read, withdrawals:write, wallet:read ตามงานที่ต้องใช้ key เดิมไม่ได้รับสิทธิ์เพิ่มอัตโนมัติ และ rotate คงสิทธิ์ที่ key เดิมได้รับไว้ sandbox:write ใช้ได้เฉพาะ Test key ดู Sandbox ที่รองรับ
ให้ผู้ดูแลจัดเตรียม beneficiary ที่มีอยู่แล้ว ต้องเป็นของ Merchant และ Live mode เดียวกัน มีสถานะ verified รับรายการใหม่ได้ และผ่านเงื่อนไขบัญชี/ธนาคารปัจจุบัน ใช้ ID รูปแบบ ben_ ตามด้วย UUID ที่ตัดขีดออกเป็นเลขฐานสิบหกพิมพ์เล็ก 32 ตัว เช่น ben_92000000000040008000000000000423 ห้ามส่ง raw UUID, เลขบัญชี หรือ object beneficiary อ่าน บัญชีปลายทาง และ สร้างรายการถอน
สร้างรายการถอน
ตัวอย่าง body สำหรับคำขอที่เซ็นแล้ว:
{
"amount_minor": 100000,
"currency": "THB",
"merchant_reference": "WD-20261017-0001",
"end_user_ref": "customer-001",
"beneficiary_id": "ben_92000000000040008000000000000423",
"metadata": { "order": "WD-20261017-0001" }
}amount_minorเป็นจำนวนเต็มบวกหน่วยสตางค์ ไม่เกิน9007199254740991และต้องไม่น้อยกว่ายอดขั้นต่ำตามนโยบาย P2P ปัจจุบัน จำนวนในตัวอย่างยังต้องผ่านนโยบายนั้นmerchant_referenceและend_user_refยาว 1–64 ตัวอักษร ไม่มี control characters reference ไม่ซ้ำต่อ Merchant ส่วนend_user_refเป็น reference ของคุณ ไม่ใช่การสร้าง Customermetadataมีไม่เกิน 20 keys ชื่อ key ยาว 1–40 ตัวอักษร ค่าเป็น string ยาวไม่เกิน 500 ตัวอักษรclientรับเฉพาะdevice_fingerprint,ip,user_agentที่ผ่านการตรวจรูปแบบ ข้อมูล client นี้ไม่ถูกเก็บใน payment metadata หรือ response- ใช้
Idempotency-Key8–200 ตัวอักษรเดิมและ body เดิมเมื่อ retry ทุก attempt ใช้ nonce ใหม่และเซ็นใหม่ exact replay ตอบ receipt เดิมพร้อมIdempotent-Replay: true
201 เริ่มที่ status: "pending_approval", requires_approval: true, version: 0 และกันยอด total_locked_minor = amount_total_minor + fee_total_minor ทันที ต้องผ่านการอนุมัติพนักงานสองคนตาม flow เดิมก่อนเข้า matching pool ยังไม่ใช่การโอนสำเร็จ และไม่ใช่ flow ถอนค่าคอมมิชชันของ Agent
ค่าธรรมเนียมมาจากราคาขาย Payout ของ Merchant โดยตรึง matrix ทั้งสี่ source ตอนสร้าง ฐานค่าธรรมเนียม P2P รุ่นนี้ใช้ wl_pool อ่าน fee_total_minor และ total_locked_minor จาก response ไม่คำนวณว่าเงินที่กันไว้เท่ากับยอดถอนอย่างเดียว 402 insufficient_balance หมายถึงยอด available ไม่พอสำหรับยอดถอนรวม fee และไม่สร้างรายการ บัญชีปลายทางไม่พร้อมได้ 409 beneficiary_not_verified; ยอดต่ำกว่านโยบายได้ 422 amount_below_p2p_minimum
อ่านรายการและยอด
ID รายการถอนเป็น wdr_ + UUID hex พิมพ์เล็ก 32 ตัว ใช้ GET /v1/pay/withdrawals/{id} เป็นสถานะเต็มปัจจุบัน สถานะสาธารณะคือ pending_approval, open, partially_filled, settled, expired, canceled, rejected
ยอด principal แยกเป็นสี่ส่วน โดย A = amount_total_minor: A = filled_minor + reserved_minor + remaining_minor + reversed_minorreserved_minor คือยอดที่จัดสรรให้ผู้ฝากแล้วแต่ยังไม่ยืนยันการโอน จึงอาจได้ remaining_minor: 0, reserved_minor: A, filled_minor: 0 ในรายการ openremaining เป็นศูนย์ไม่ได้แปลว่าจ่ายแล้ว ตรวจสถานะล่าสุดและยอดที่โอนสำเร็จ เมื่อจ่ายครบโดยไม่มียอดย้อนกลับ จะเป็น settled, filled_minor = A และ reserved_minor = remaining_minor = reversed_minor = 0
ทั้งรายการฝากและถอนรับ limit 1–100 (default 20), status, updated_after แบบ UTC เช่น 2026-10-17T00:00:00Z และ cursor จาก next_cursor เท่านั้น cursor มีรูปแบบ cur_<epochmicro>_<uuidhex> ให้ส่งกลับตามเดิม เรียง created_at ใหม่ไปเก่าและใช้ ID ตัดสินเมื่อเวลาเท่ากัน เปลี่ยนตัวกรองให้เริ่มหน้าแรกใหม่; เมื่อ has_more: false จะได้ next_cursor: null นี่คือการแบ่งหน้าข้อมูลปัจจุบัน ไม่ใช่ snapshot ที่ตรึงสถานะตลอดการอ่าน
Balance ตอบ field เหล่านี้ ไม่มีการดึง pending clearing มารวมเป็นยอดถอนได้:
{
"livemode": true,
"available_minor": 250000,
"pending_clearing_minor": 10000,
"reserved_minor": 5000,
"currency": "THB",
"as_of": "2026-10-17T00:00:00.000Z"
}อ่าน event โดยไม่เปลี่ยนสัญญา webhook
เรียก GET /v1/pay/events?since_sequence=0&limit=20 แล้วบันทึก next_sequence เป็น decimal string เพื่อเรียกต่อ sequence ของแต่ละ event เป็น string เช่นกัน ลำดับเพิ่มต่อ Merchant เมื่อมีข้อมูลหน้าถัดไปให้ส่ง next_sequence เดิมกลับใน since_sequence
รุ่นนี้ส่ง business snapshots ของ withdrawal.created, withdrawal.partial_fill, withdrawal.terminal และ deposit.settled เท่านั้น data.object เป็น snapshot แบบเดิมของ event นั้น ไม่ใช่ Withdrawal object เต็มใบ ถ้าต้องแสดงสถานะ/ยอดล่าสุดให้ GET รายการถอน เมื่อ snapshot ใช้ withdrawal_id แบบ UUID ให้ประกอบ public ID เป็น wdr_ ตามด้วย UUID ที่ตัดขีดออก
ซองข้อมูล webhook ที่เซ็นยังคง 7 field เดิม: id, object, type, api_version, livemode, created_at, datasequence และ account เป็น metadata เพิ่มสำหรับ response ของการ polling เท่านั้น ตรวจ Ed25519 จาก raw webhook bytes ที่ได้รับตาม วิธีตรวจลายเซ็น ไม่ใช้ JSON ที่ประกอบใหม่จากผล polling ไปตรวจแทน signed webhook body
ขอบเขตนี้ยังต้องผ่านการตรวจ SQL, การ deploy และการตั้งค่า host/key/policy ของผู้ให้บริการ ก่อนเปิดใช้งานเงินจริง
