Sign in
การชำระเงินและการถอน/Payout API

Payout API

ส่งการถอนจากยอดคงเหลือของผู้ค้าไปยังที่อยู่บล็อกเชนใด ๆ

Payout API ให้คุณถอนเงินจากยอดคงเหลือของผู้ค้าไปยังที่อยู่บล็อกเชนใด ๆ ได้ผ่านโปรแกรม

สำหรับ endpoint การถอนทั้งหมด คุณต้องใช้ Payout API key แยกต่างหากเพื่อสร้างลายเซ็น sign คีย์นี้แตกต่างจาก API key ปกติของคุณและต้องสร้างขึ้นในการตั้งค่าโปรเจกต์

สร้างการถอน

สร้างคำขอถอนเงินจากยอดคงเหลือของผู้ค้า

POST/v1/payout

พารามิเตอร์ของคำขอ

FieldTypeRequiredDescription
currencystringyesสกุลเงินที่ถอน (ดู References)
networkstringyesรหัสเครือข่าย (ดู References)
amountstringyesจำนวนเงินที่ถอน
to_addressstringyesที่อยู่บล็อกเชนของผู้รับ
order_idstringnoคีย์ idempotency — ไม่ซ้ำกันภายในโปรเจกต์ การส่ง POST ซ้ำด้วย order_id เดิมจะไม่สร้างการถอนใหม่ — ระบบจะคืนรายการที่มีอยู่แทน
url_callbackstringnoURL สำหรับ Webhook ของการถอน เว้นว่างไว้เพื่อปิดใช้งาน Webhook สำหรับการถอนนี้
memostring | nullnoDestination tag / memo ปัจจุบันใช้กับเครือข่าย TON และ SOL เท่านั้น สูงสุด 255 ตัวอักษร
from_currencystringnoยอดคงเหลือต้นทางที่จะถูกตัดและแปลงอัตโนมัติเป็น currency ในขณะที่ทำการถอน ช่วยให้คุณถอนเป็นสินทรัพย์ที่มีความผันผวน (BTC, ETH, …) ได้โดยที่ยังเก็บยอดคงเหลือเป็นสเตเบิลคอยน์อย่าง USDT — คุณไม่ต้องถือคริปโตที่มีความผันผวนเอง ส่ง "USDT" เพื่อตัดจากยอดคงเหลือ USDT
fee_optionstringnoวิธีคิดค่าธรรมเนียม deduct (ค่าเริ่มต้น) — ค่าธรรมเนียมเครือข่าย + แพลตฟอร์มหักจาก amount ผู้รับได้ amount - fees add — ค่าธรรมเนียมบวกเพิ่ม ผู้ค้าถูกตัด amount + fees ผู้รับได้ amount พอดี

Idempotency ภายในโปรเจกต์เดียวกัน การถอนจะไม่ซ้ำตาม order_id การส่ง POST ซ้ำด้วย order_id เดิมเป็นเรื่อง ปลอดภัย — API จะคืนการถอนที่มีอยู่แทนการสร้างซ้ำ ในระบบโปรดักชันให้ระบุ order_id เสมอสำหรับการถอน

ตัวอย่างคำขอ

Shell
curl -X POST https://api.2328.io/api/v1/payout \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"TRX","network":"TRX-TRC20","amount":"1.00","to_address":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","order_id":"9ed25264-8be4-439f-acf5-2a8732538d27","url_callback":"https://your-site.com/webhook/payout","memo":null,"fee_option":"deduct"}'

ตัวอย่างการตอบกลับ

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dea62-1727-72aa-ac2c-eaf2ade193ef",
    "order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
    "status": "pending",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "1.00",
    "merchant_amount": "1",
    "network_amount": "0.89",
    "amount_usd": "0.33",
    "to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "memo": null,
    "txid": null,
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-02T23:29:50+03:00",
    "updated_at": "2026-05-02T23:29:50+03:00"
  }
}

ค่าธรรมเนียม ค่าเริ่มต้น fee_option: deduct — ค่าธรรมเนียมเครือข่าย + แพลตฟอร์มจะถูกหักจาก amount (ผู้รับได้ amount - fees) ส่ง fee_option: add เพื่อบวกค่าธรรมเนียมเพิ่ม — ผู้รับจะได้ amount พอดี และผู้ค้าจะถูกตัด amount + fees

คำนวณการถอน

ประเมินจำนวนเงินและค่าธรรมเนียมการถอน โดยไม่สร้างการถอนจริง และไม่หักจากยอดคงเหลือ ใช้เพื่อแสดงจำนวนเงินที่ผู้ใช้จะได้รับ (หรือจ่าย) อย่างแม่นยำก่อนยืนยัน

POST/v1/payout/calc

พารามิเตอร์ของคำขอ

เหมือนกับ สร้างการถอน ทุกประการ — ฟิลด์เดียวกัน วิธีลงนามเดียวกัน ฟิลด์ order_id, url_callback, to_address และ memo รับได้แต่จะถูกละเว้น: ไม่มีการบันทึกการถอนและไม่มีการส่ง callback

ตัวอย่างคำขอ

Shell
curl -X POST https://api.2328.io/api/v1/payout/calc \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"USDT","network":"TRX-TRC20","amount":"100","fee_option":"add"}'

ตัวอย่างการตอบกลับ

JSON
{
  "state": 0,
  "result": {
    "currency": "USDT",
    "network": "TRX-TRC20",
    "amount": "100",
    "fee_option": "add",
    "merchant_amount": "103.00000000",
    "network_amount": "100",
    "total_fee": "3.00000000",
    "total_fee_usd": "3.00000000"
  }
}

เฉพาะตัวอย่าง. Endpoint นี้เป็นแบบอ่านอย่างเดียว — ไม่มีการหักยอดคงเหลือและไม่มีการสร้างเรกคอร์ดการถอน เรียกใช้ได้ตามต้องการเพื่อแสดงรายละเอียดค่าธรรมเนียมใน UI

สถานะการถอน

ดูสถานะของคำขอถอน

GET/v1/payout/status/{uuid}

พารามิเตอร์ใน Path

FieldTypeRequiredDescription
uuidstringyesUUID ของการถอน (จาก result.uuid ตอนสร้าง)

ตัวอย่างการตอบกลับ

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
    "order_id": "4dfdcc84402b1185b71cbe399321533e",
    "status": "completed",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "3.00",
    "merchant_amount": "3.00",
    "network_amount": "3.00",
    "amount_usd": "1.04",
    "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
    "memo": null,
    "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-07T00:08:38+03:00",
    "updated_at": "2026-05-07T00:08:54+03:00",
    "from_currency": "USDT",
    "debited_amount": "1.050735",
    "debited_currency": "USDT"
  }
}

สำหรับคำขอ GET นี้ลายเซ็นคำนวณจาก body ที่ว่าง: hash_hmac('sha256', base64_encode(''), $apiKey)

ฟิลด์ในการตอบกลับ

ฟิลด์ที่คืนใน result จาก POST /v1/payout และ GET /v1/payout/status/{uuid}:

FieldTypeDescription
uuidstringUUID ของการถอนที่ระบบกำหนด
order_idstringตัวระบุการถอนภายในของคุณ (ไม่ซ้ำกันภายในโปรเจกต์)
statusstringสถานะปัจจุบันของการถอน (ดูด้านล่าง)
currencystringสกุลเงินที่ถอน
networkstringรหัสเครือข่าย
amountstringจำนวนเงินถอนที่ร้องขอ
merchant_amountstringจำนวนเงินที่หักจากยอดคงเหลือผู้ค้า
network_amountstringจำนวนเงินที่ส่งจริงบนเชน (หลังหักค่าธรรมเนียมเครือข่าย + แพลตฟอร์ม)
amount_usdstringมูลค่าเทียบเท่า USD ของจำนวนเงินถอน
to_addressstringที่อยู่บล็อกเชนของผู้รับ
memostring | nullDestination tag / memo (TON, SOL) null ในกรณีอื่น
txidstring | nullhash ของธุรกรรมบล็อกเชน null จนกว่าจะส่งธุรกรรม
block_numberint | nullหมายเลขบล็อกที่บรรจุธุรกรรม null จนกว่าจะถูกบรรจุ
error_typestring | nullสาเหตุที่ล้มเหลวเมื่อ status = failed (ดู Error types ด้านล่าง) null ในกรณีอื่น
created_atstring (ISO 8601)เวลาที่สร้างการถอน
updated_atstring (ISO 8601)เวลาที่สถานะเปลี่ยนแปลงล่าสุด
from_currencystring | nullยอดคงเหลือต้นทางที่ถูกตัดเมื่อใช้การแปลงอัตโนมัติ (เช่น USDT สำหรับการถอนเป็น BTC) เป็น null หากไม่มีการแปลง
debited_amountstring | nullจำนวนเงินที่ถูกตัดจริงจากยอดคงเหลือต้นทางหลังการแปลง ปรากฏเฉพาะเมื่อใช้การแปลงอัตโนมัติ
debited_currencystring | nullสกุลเงินของ debited_amount — ยอดคงเหลือที่เงินถูกตัดออก

สถานะของการถอน

ฟิลด์ status รับค่าต่อไปนี้:

StatusDescription
pendingสร้างแล้ว รอการดำเนินการ
completedดำเนินการสำเร็จ — txid ถูกตั้งค่า
failedเกิดข้อผิดพลาดในการส่ง — ดู error_type
cancelledยกเลิกแล้ว

ประเภทข้อผิดพลาด

เมื่อ status = failed ฟิลด์ error_type อธิบายสาเหตุ:

CodeDescription
aml_riskการถอนถูกบล็อกโดยการตรวจสอบความเสี่ยง AML (ที่อยู่ผู้รับถูกแฟล็กว่ามีความเสี่ยงสูง)

การแจ้งเตือน Webhook

เมื่อ status ของการถอนเปลี่ยน ระบบจะส่ง Webhook แบบ POST ไปยัง URL url_callback ที่ระบุตอนสร้างการถอน หากไม่ได้ระบุ url_callback จะไม่มีการส่ง Webhook สำหรับการถอนนั้น

  • Method: POST
  • Content-Type: application/json
  • Signature: ฟิลด์ sign ใน body ของคำขอ คำนวณด้วย Payout API key (คีย์เดียวกับที่ใช้ลงลายเซ็นคำขอถอน)

payload สะท้อนออบเจกต์ result จาก GET /v1/payout/status/{uuid} พร้อมเพิ่มฟิลด์ sign สำหรับการตรวจสอบ

Payload

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

การตรวจสอบลายเซ็น ใช้อัลกอริทึมเดียวกับ payment webhooks แต่ลงลายเซ็นด้วย Payout API key แทน API key ปกติ ตัดฟิลด์ sign ออก แปลง payload ที่เหลือเป็น JSON เข้ารหัสด้วย Base64 จากนั้นคำนวณ hash_hmac('sha256', $base64, $payoutApiKey) แล้วเปรียบเทียบกับ sign ที่ได้รับ