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
