Withdraw verify
ขั้นตอนฝั่งร้านค้า สำหรับยืนยันคำขอถอนเงินอีกชั้นก่อนระบบทำรายการจริง
Withdraw verify คืออะไร? เป็นระบบยืนยันการถอนเงินสองชั้น (second-layer verification) — ก่อนระบบจะทำรายการถอนเงินจริง ระบบจะส่งคำขอ (webhook) ไปยัง backend ของร้านเพื่อตรวจสอบว่าคำขอถอนนั้นถูกต้องหรือไม่ หากร้านตอบ อนุมัติ (HTTP 200) ระบบจึงดำเนินการถอน หากตอบเป็นอย่างอื่นจะถือว่า ปฏิเสธ ช่วยลดความเสี่ยงกรณีมีการนำ API key ของร้านไปใช้สั่งถอนเงินโดยไม่ได้รับอนุญาต
- 1
เปิดใช้งานในหน้า API Key & Webhook
SETUPไปที่ Developer → ตั้งค่า Webhook แล้วตั้งค่า 3 รายการต่อไปนี้:

หน้า API Key & Webhook → ตั้งค่า Webhook - 1Webhook URL — URL ที่ระบบจะส่งคำขอยืนยันไปยัง (ใช้ร่วมกับ webhook ของร้าน) — ควรเป็น HTTPS และ whitelist IP ตามที่หน้าจอแจ้ง
- 2App Secret Verify (HMAC) — กด “สร้าง Secret” เพื่อสร้าง secret สำหรับตรวจ signature — แสดงครั้งเดียว คัดลอกเก็บทันที (เช่น
WPAY_VERIFY_SECRET) - 3Automatic Approve Withdrawal — สวิตช์เปิดการยืนยัน — เมื่อเปิดใช้งาน ระบบจะอนุมัติเฉพาะเมื่อร้านตอบ HTTP 200 เท่านั้น จากนั้นกด “บันทึก”
ต้องตั้งค่า Webhook URL และ Secret ให้ครบก่อนเปิดใช้งาน มิฉะนั้นระบบจะแจ้ง error
10061การปิดใช้งานหรือเปลี่ยน Webhook URL จะระงับการถอนเงินเป็นเวลา 24 ชั่วโมง (cooldown) ทั้งนี้ การสร้าง Secret ใหม่จะไม่ทำให้เกิดการระงับดังกล่าว - 2
ระบบส่ง webhook เพื่อขอให้ร้านยืนยัน
RUNTIMEเมื่อมีคำขอถอน ระบบจะส่ง POST ไปยัง
Webhook URLของร้าน และรอคำตอบไม่เกิน 10 วินาที โดยขั้นตอนนี้เกิดขึ้นก่อนการสร้างรายการถอนจริงRequestระบบเป็นฝ่ายส่ง ร้านเป็นฝ่ายรับPOST /wpay/withdrawal-verify Trust-X-Event: WITHDRAWAL_VERIFY Trust-X-Request-ID: verify_ORDER-DEMO-00111 x-timestamp: 1750072460 x-signature: sha256=4fdf737a8354e312619911b45a406bab75fb1e4fe956e439e26edbbfcfa2fdc7 Content-Type: application/json { "event": "WITHDRAWAL_VERIFY", "type": "FIAT", "request_id": "verify_ORDER-DEMO-00111", "data": { "order_id": "ORDER-DEMO-00111", "order_user_reference": null, "withdrawal_mode": "FIAT", "amount": 311, "currency": "THB", "withdrawal_address": "9999999999", "receiver_bank": "SCB", "receiver_name": "MR. John Snow", "chain": null, "asset_type": null, "agent_id": "d272d889-886f-41ba-98cf-52d55c1fbe21" } }เก็บ
x-timestamp(Unix วินาที),x-signatureและ body ดิบ (raw) ไว้ใช้ตรวจ signature ในขั้นถัดไป - 3
ร้านตรวจ signature แล้วตัดสินใจอนุมัติหรือปฏิเสธ
RUNTIMEคำนวณ signature ด้วย HMAC-SHA256 จาก เฉพาะ object
data(ไม่ใช่ทั้ง body) ตามสูตรHMAC_SHA256(secret, "{x-timestamp}.{JSON ของ data}")แล้วเทียบกับx-signatureเมื่อตรงกันจึงตรวจสอบออเดอร์และยอดเงินต่อไปsigning stringtimestamp ต่อด้วย JSON ของ data — จากตัวอย่างขั้น 21750072460.{"order_id":"ORDER-DEMO-00111","order_user_reference":null,"withdrawal_mode":"FIAT","amount":311,"currency":"THB","withdrawal_address":"9999999999","receiver_bank":"SCB","receiver_name":"MR. John Snow","chain":null,"asset_type":null,"agent_id":"d272d889-886f-41ba-98cf-52d55c1fbe21"}# ทดสอบส่ง verify webhook ไปยัง endpoint ของคุณ curl -X POST https://merchant.example.com/wpay/withdrawal-verify \ -H "Trust-X-Event: WITHDRAWAL_VERIFY" \ -H "x-timestamp: 1750072460" \ -H "x-signature: sha256=<hmac>" \ -H "Content-Type: application/json" \ -d '{"event":"WITHDRAWAL_VERIFY","data":{"order_id":"ORDER-DEMO-00111","amount":311,"currency":"THB"}}'Response → ระบบ wpayร้านเป็นฝ่ายตอบกลับHTTP/1.1 200 OK Content-Type: application/json { "ok": true }เกณฑ์ตัดสินคือ HTTP status code ไม่ใช่ body — 2xx = อนุมัติ; non-2xx, ตอบช้าเกิน 10 วินาที หรือเชื่อมต่อไม่ได้ = ปฏิเสธ (fail-closed: หากเกิดข้อผิดพลาดใด ๆ ระบบจะถือว่าปฏิเสธไว้ก่อนเพื่อความปลอดภัย)
- 4
ระบบตอบผลคำขอถอนกลับให้ผู้เรียก API (PENDING)
RUNTIMEเมื่อร้านตอบ 200 ระบบจะกันยอดเงิน (reserve) แล้วสร้างรายการถอนสถานะ
PENDINGซึ่งเป็น response ที่ ผู้เรียกcreateRequestได้รับResponse 200แสดงเฉพาะฟิลด์หลัก{ "success": true, "code": 0, "data": { "id": "4d59bdf7-c762-4f09-94f2-cfaabefc52e7", "order_id": "ORDER-DEMO-00111", "withdrawal_mode": "FIAT", "amount": "311", "currency": "THB", "receiver_bank": "SCB", "receiver_name": "MR. John Snow", "address": "9999999999", "withdrawal_status": "PENDING", "created_at": "2026-06-16T11:14:20.366Z", "agent_id": "d272d889-886f-41ba-98cf-52d55c1fbe21" } }response นี้ ไม่ต้องตรวจ signature — เก็บ
id/order_idไว้ติดตามสถานะ หากขั้น 3 ตอบ non-2xx จะได้ errorWITHDRAWAL_VERIFY_REJECTED (10060)และจะไม่มีการสร้างรายการถอน - 5
รับผลการถอนจริงผ่าน webhook (ภายหลัง)
RUNTIMEหลังโอนเสร็จ ระบบจะส่ง webhook สรุปผลอีกครั้ง —
WITHDRAWAL_COMPLETED(สำเร็จ) หรือWITHDRAWAL_REJECTED(ไม่สำเร็จ)Webhookระบบเป็นฝ่ายส่ง ร้านเป็นฝ่ายรับPOST /wpay/withdrawal-verify Trust-X-Event: WITHDRAWAL_COMPLETED Content-Type: application/json { "event": "WITHDRAWAL_COMPLETED", "type": "FIAT", "data": { "withdrawal": { "id": "4d59bdf7-c762-4f09-94f2-cfaabefc52e7", "order_id": "ORDER-DEMO-00111", "amount": "311", "currency": "THB", "withdrawal_status": "COMPLETED" }, "idempotency_key": "4d59bdf7-...:WITHDRAWAL_COMPLETED" } }อัปเดตสถานะออเดอร์ฝั่งร้านด้วย
id/order_idจากขั้น 4 และรองรับการส่งซ้ำ (idempotent) ด้วยidempotency_keyดู payload ฉบับเต็มได้ที่หน้า Webhook Examples
