เริ่มต้นใช้งาน API
หน้านี้พาทำตั้งแต่รับคีย์จนได้รับเงินรายการแรก ตัวอย่างโค้ดใช้ฟังก์ชัน api() จากหน้าการเซ็น request
1. รับ API key และ secret
หัวข้อที่มีชื่อว่า “1. รับ API key และ secret”-
เข้าสู่ระบบหน้าเว็บจัดการของ FIN ที่ https://portal.finixpay.app ด้วยบัญชีเจ้าของพาร์ทเนอร์
-
ไปที่เมนู ตั้งค่าบัญชี (Account settings) ส่วน คีย์ จะมี API key ของคุณ (ขึ้นต้นด้วย
pk_live_หรือเป็นตัวอักษร hex 32 ตัวสำหรับบัญชีเดิม) กดคัดลอกได้ -
กด สร้างคีย์ลับใหม่ ยืนยัน แล้วคัดลอก secret ที่แสดง secret จะแสดงเพียงครั้งเดียว และ secret เดิม (ถ้ามี) จะใช้ไม่ได้ทันที
-
เก็บทั้งสองค่าไว้ใน environment variable หรือ secret manager ของเซิร์ฟเวอร์
Terminal window export PARTNER_API_KEY="pk_live_xxxxxxxxxxxxxxxxxxxxxxxx"export PARTNER_API_SECRET="<secret ที่คัดลอกมา>"
2. เรียก API ครั้งแรก
หัวข้อที่มีชื่อว่า “2. เรียก API ครั้งแรก”เริ่มจาก GET /v1/account เพื่อตรวจว่าการเซ็นถูกต้อง แล้ว GET /v1/banks เพื่อดูรหัสธนาคารที่รองรับ
import { api } from './partner-api.mjs';
const { data: account } = await api('GET', '/v1/account');console.log(account.status, account.balance.available);
const { data: banks } = await api('GET', '/v1/banks');console.log(banks.map((b) => b.code)); // cache these codesrequire 'partner_api.php';
$account = partner_api('GET', '/v1/account')['data'];echo $account['status'], ' ', $account['balance']['available'], PHP_EOL;
$banks = partner_api('GET', '/v1/banks')['data'];print_r(array_column($banks, 'code')); // cache these codesfrom partner_api import api
account = api("GET", "/v1/account")["data"]print(account["status"], account["balance"]["available"])
banks = api("GET", "/v1/banks")["data"]print([b["code"] for b in banks]) # cache these codesตัวอย่าง response ของ GET /v1/account
{ "data": { "object": "account", "name": "Example Shop", "status": "active", "payinsEnabled": true, "payoutsEnabled": true, "ipAllowListEnabled": false, "limits": { "payinMinimum": "100.00", "payinMaximum": "50000.00", "payoutMinimum": "100.00", "payoutMaximum": "50000.00", "dailyWithdrawalLimit": "0.00" }, "balance": { "currency": "THB", "total": "125000.00", "available": "120000.00" }, "createdAt": "2026-01-01T00:00:00.000Z" }, "requestId": "req_Z3k9QmP2xR7tLw4NbV8cYh1s"}ถ้าได้ 401 ให้ดูข้อผิดพลาดที่พบบ่อยของการเซ็น
3. สร้าง pay-in
หัวข้อที่มีชื่อว่า “3. สร้าง pay-in”เรียกครั้งเดียวก็พอ ส่งบัญชีธนาคารของผู้จ่ายแบบ inline ใน payer พร้อมยอดเงิน เลขคำสั่งซื้อของคุณใน reference และ URL ที่จะรับ webhook ใน webhookUrl ระบบจะสร้าง payer (บัญชีธนาคารของผู้ใช้ปลายทาง) ในครั้งแรก และใช้ payer เดิมให้อัตโนมัติกับ pay-in และ payout ครั้งถัดไปที่ bankCode และ accountNumber ตรงกัน
const { data: payin } = await api('POST', '/v1/payins', { payer: { bankCode: 'SCB', accountNumber: '1234567890', accountName: 'สมชาย สบายดี', }, amount: '150.00', currency: 'THB', reference: 'order-10001', webhookUrl: 'https://shop.example.com/webhooks/payments', returnUrl: 'https://shop.example.com/orders/10001',});// save payin.id with the order (and payin.payerId with your user, if you like)$payin = partner_api('POST', '/v1/payins', [ 'payer' => [ 'bankCode' => 'SCB', 'accountNumber' => '1234567890', 'accountName' => 'สมชาย สบายดี', ], 'amount' => '150.00', 'currency' => 'THB', 'reference' => 'order-10001', 'webhookUrl' => 'https://shop.example.com/webhooks/payments', 'returnUrl' => 'https://shop.example.com/orders/10001',])['data'];payin = api("POST", "/v1/payins", { "payer": { "bankCode": "SCB", "accountNumber": "1234567890", "accountName": "สมชาย สบายดี", }, "amount": "150.00", "currency": "THB", "reference": "order-10001", "webhookUrl": "https://shop.example.com/webhooks/payments", "returnUrl": "https://shop.example.com/orders/10001",})["data"]ส่วนสำคัญของ response
{ "object": "payin", "id": "pin_3f2b1c0d9e8f4a7b8c6d5e4f3a2b1c0d", "reference": "order-10001", "payerId": "payer_7c0a4b8e2f3d4a1b9c8d7e6f5a4b3c2d", "requestedAmount": "150.00", "amount": "150.37", "currency": "THB", "method": "promptpay_qr", "status": "pending", "checkoutUrl": "https://pay.example.com/3f2b1c0d-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "payTo": { "bankCode": "KBANK", "bankName": "Kasikorn Bank", "accountNumber": "0987654321", "accountName": "Example Co., Ltd.", "promptpayId": "0812345678", "qrPayload": "00020101021229370016A000000677010111011300668123456785802TH53037645406150.3763046572" }}ถ้ามี payer อยู่แล้วแต่ชื่อต่างจากที่ส่งมา ระบบจะคงชื่อเดิมไว้ (เพราะใช้จับคู่การโอน) และ response จะมี payer_name_differs ใน warnings ดูส่ง payer แบบ inline
4. แสดงช่องทางจ่ายให้ผู้จ่าย
หัวข้อที่มีชื่อว่า “4. แสดงช่องทางจ่ายให้ผู้จ่าย”เลือกวิธีใดวิธีหนึ่ง
- ส่งไปหน้าชำระเงินสำเร็จรูป redirect ผู้จ่ายไปที่
checkoutUrlเมื่อจ่ายเสร็จ หน้าชำระเงินจะพากลับไปที่returnUrl - แสดงในหน้าของคุณเอง สร้าง QR code จาก
payTo.qrPayloadด้วยไลบรารี QR ใดก็ได้ และแสดงข้อมูลบัญชีปลายทางจากpayToสำหรับ pay-in แบบbank_transferค่าqrPayloadเป็นnullให้แสดงเฉพาะบัญชี - ใช้รูปสำเร็จรูป สร้างหรือดู pay-in พร้อม
?include=paymentImage(เช่นPOST /v1/payins?include=paymentImageและเซ็นรวม query string นี้ด้วย) เพื่อรับpaymentImageเป็นรูป PNG แบบ data URI ใส่ใน<img src="...">ได้ทันที
5. รับ webhook
หัวข้อที่มีชื่อว่า “5. รับ webhook”เมื่อระบบจับคู่การโอนได้ จะ POST event payin.succeeded ไปที่ webhookUrl ตัวอย่างขั้นต่ำด้านล่าง ดูการตรวจลายเซ็นแบบครบในหน้า Webhooks
// Expressapp.post('/webhooks/payments', express.raw({ type: 'application/json' }), async (req, res) => { if (!verifyWebhook(req.get('X-Webhook-Signature'), req.body)) return res.status(400).end(); const event = JSON.parse(req.body); if (event.type === 'payin.succeeded') { await markOrderPaid(event.data.reference, event.data.id); // must be idempotent } res.status(200).end(); // reply quickly, do slow work afterwards});6. ตรวจสถานะซ้ำเมื่อจำเป็น
หัวข้อที่มีชื่อว่า “6. ตรวจสถานะซ้ำเมื่อจำเป็น”webhook ไม่มีการส่งซ้ำอัตโนมัติ ถ้า endpoint ของคุณล่มหรือไม่แน่ใจ ให้เรียก GET /v1/payins/{id} เพื่อดูสถานะล่าสุด หรือค้นด้วยเลขคำสั่งซื้อ GET /v1/payins?reference=order-10001
- รายละเอียดฟิลด์และสถานะของ Pay-ins และ Payouts
- จัดการ Payers โดยตรง
- ทดสอบและเช็กลิสต์ก่อนใช้งานจริง