Use with AIให้ AI อ่านคู่มือและช่วยเชื่อมต่อ Payment API
DOCUMENTATION / API V1

คู่มือใช้งาน
Payment CytechTeam Dev.

ศูนย์รวมเอกสารการใช้งาน ตั้งแต่ตั้งค่าร้าน สร้างระบบรับชำระเงิน ไปจนถึงเชื่อมต่อ Webhook และดูแลระบบอย่างครบถ้วน

GETTING STARTED

เอกสารประกอบการใช้งาน

เรียนรู้ระบบ Payment CytechTeam Dev ตั้งแต่ขั้นตอนพื้นฐานไปจนถึงการเชื่อมต่อ API พร้อมตัวอย่างโค้ดและแนวทางการใช้งานจริง

PromptPay QRออก QR สำหรับรับชำระเงินและสร้างลิงก์ให้ลูกค้า
Webhookแจ้งสถานะการชำระเงินกลับไปยังระบบร้านค้า
Live APIใช้งาน API จริงพร้อม Authentication และการตรวจสอบสถานะ
GUIDES & REFERENCE

หัวข้อใช้งานหลัก

เลือกหัวข้อที่ต้องการศึกษาเพื่อเริ่มต้นใช้งานและเชื่อมระบบได้รวดเร็ว

22 หัวข้อในคู่มือ
01 เริ่มต้นใช้งาน คู่มือสมัครร้าน ตั้งค่าเริ่มต้น และเตรียมเชื่อม API อ่านเพิ่มเติม 02 การสร้าง Checkout สร้างบิลและลิงก์รับชำระเงินผ่าน PromptPay อ่านเพิ่มเติม 03 Webhook รับเหตุการณ์ชำระเงินและตรวจสอบลายเซ็น HMAC อ่านเพิ่มเติม 04 จัดการร้านค้า ตั้งข้อมูล Merchant และตรวจสอบบัญชีรับเงิน อ่านเพิ่มเติม 05 Projects แยกเว็บไซต์ บอท และสิทธิ์ API Key ตามโปรเจกต์ อ่านเพิ่มเติม 06 การแก้ปัญหา ตรวจ Error 401 / 409 / 422 และสถานะที่ไม่อัปเดต อ่านเพิ่มเติม 07 การตรวจสอบยอดโอน เลือกวิธีจับคู่โอนผ่าน LINE Bank Alerts อ่านเพิ่มเติม 08 เชื่อมต่อเว็บไซต์และบอท ตัวอย่าง Node.js, Python และระบบเครดิต อ่านเพิ่มเติม 09 คำถามที่พบบ่อย แนวทางใช้งานจริงและขอบเขตการให้บริการ อ่านเพิ่มเติม
กำลังเชื่อมต่อระบบรับเงิน?

ศึกษาการใช้งาน Live API และทดสอบเงื่อนไขชำระเงินจริงก่อนเริ่มให้บริการ

คำแนะนำก่อนเปิดใช้งาน

รู้จัก Payment CytechTeam Dev

ระบบสร้าง QR PromptPay และจับคู่รายการรับเงินอัตโนมัติจาก LINE Bank Alerts สำหรับร้านค้า เว็บไซต์ หรือระบบสมาชิกที่ต้องการเชื่อมต่อด้วย API

Payment CytechTeam Dev API สร้าง PromptPay checkout และคืนสถานะจาก LINE bank notification. ระบบภายนอกใช้ Merchant API Key ผ่าน Authorization: Bearer; หน้า Merchant Console ใช้ Session Cookie แบบ HttpOnly. การเข้าถึงข้อมูลร้านถูกจำกัดตามสิทธิ์ของ credential

Base URL: https://payment.cytechteam.devJSON onlyUTF-8No browser secrets
Live Release: API สร้าง QR จากข้อมูล PromptPay ที่ตั้งค่าใน Merchant Console ตรวจสอบบัญชีผู้รับและทดสอบ webhook ก่อนใช้งานจริง

เริ่มใช้งานใน 5 ขั้นตอน

ทำตามลำดับนี้ได้แม้ไม่เคยใช้ Payment API มาก่อน ถ้าต้องการเริ่มแบบสั้น ๆ อ่าน หน้า Quickstart เพิ่มเติมได้

01

สมัครและเข้าสู่ Merchant Console

เปิด Console สร้างบัญชีผู้ใช้งานหรือเข้าสู่ระบบ เลือก Workspace และสร้างร้านค้าของคุณ

02

กำหนดบัญชีรับเงิน

กรอกชื่อร้าน หมายเลข PromptPay ธนาคารที่รับเงิน และเลขบัญชีผู้รับ 4 หลักท้ายให้ตรงกับบัญชีจริง ตรวจข้อมูลก่อนยืนยันการตั้งค่า

03

ออก Merchant API Key

ไปที่เมนู API & Checkout สร้าง Key สำหรับฝั่งเซิร์ฟเวอร์ คัดลอกเก็บทันที เพราะค่าจริงจะแสดงเพียงครั้งเดียว

04

สร้าง Checkout และส่งลิงก์จ่ายเงิน

เรียก POST /v1/checkouts นำ payment_path จากผลลัพธ์ไปเปิดเป็นหน้าจ่ายเงินให้ลูกค้า ระบบจะสร้าง QR จาก PromptPay ที่ตั้งไว้

05

ตรวจสถานะและส่งมอบสินค้า

ตั้ง Webhook เพื่อรับ payment.confirmed หรือเรียก API อ่านสถานะ ให้ส่งสินค้า/เติมเครดิตเฉพาะเมื่อสถานะเป็น PAID เท่านั้น

ตรวจสอบก่อนใช้งานจริง

ระบบนี้เป็น Live environment ไม่ใช่ Sandbox การเรียกสร้าง Checkout จะสร้างบิลจริง แนะนำทดสอบกับยอดเล็กและตรวจสอบปลายทางรับเงินจริง

ตั้งค่าร้านค้าและบัญชีรับเงิน

บัญชีร้านค้าคือพื้นที่จัดการ API keys, Projects, Checkout และ Webhook คุณต้องตั้งค่าฝั่ง Merchant ก่อน จึงจะสร้าง QR ที่ลูกค้าชำระเงินจริงได้

01 · STORE

ชื่อร้าน / Merchant

ใช้ชื่อสื่อถึงผู้รับเงิน ลูกค้าจะได้ทราบว่าชำระให้ระบบใด และใช้แยกรายการใน Console

02 · RECEIVER

PromptPay + ธนาคาร

ใส่หมายเลข PromptPay ที่รับเงินจริง เลือกธนาคารผู้รับ และเลขบัญชี 4 หลักท้ายให้ถูกต้องสำหรับการจับคู่แจ้งเตือน

03 · CHECK

ทวนข้อมูลรับเงิน

ข้อมูลบัญชีรับเงินหลักถูกล็อกหลังตั้งค่า เพื่อลดการเปลี่ยนปลายทางโดยไม่ตั้งใจ โปรดตรวจสอบก่อนบันทึก

04 · WEBHOOK

ตั้ง Callback URL

เลือก HTTPS endpoint แบบสาธารณะที่รับ POST แล้วตอบ 2xx ได้ ตรวจ signature ก่อนนำข้อมูลไปดำเนินการ

หากใช้หลายเว็บ: แยกเป็น Projects ภายใน Merchant เดียวกันเพื่อแยก API Key และรายงานได้ ดูหัวข้อ Projects & Workspaces

Authentication และการดูแล API Key

Server-to-server: เข้าสู่ Merchant Console เพื่อสร้างบัญชี ตั้งค่าร้านและ PromptPay แล้วสร้าง Merchant API Key ในหน้า API & Checkout. ส่ง Key ด้วย Authorization: Bearer cyt_next_... เท่านั้น อย่านำ Key ไปฝังใน JavaScript ที่ส่งให้เบราว์เซอร์

API KEYAuthorization: Bearer cyt_next_...

Merchant Console: เข้าสู่ระบบด้วย POST /v1/auth/login จากนั้นเบราว์เซอร์ใช้ __Host-cytech_console ซึ่งเป็น HttpOnly; Secure; SameSite=Strict Cookie อายุ 30 วัน จึงใช้งานข้ามแท็บหรือเปิดเบราว์เซอร์ใหม่ได้หากยังไม่หมดอายุ. ตรวจสถานะด้วย GET /v1/auth/session และออกจากระบบด้วย POST /v1/auth/logout. ไม่ต้องอ่านหรือเก็บ Session Token ใน JavaScript

CONSOLECookie: __Host-cytech_console (browser-managed)

ระบบยังรองรับ Authorization: Bearer cyt_sess_... สำหรับ API client ที่ต้องการใช้ Console Session โดยตรง. Session ใหม่มีอายุ 30 วัน และ Session เก่าที่ยังใช้ได้สามารถย้ายไปใช้ Cookie ได้. API Key และ Session ถูกเก็บเป็น Hash ฝั่ง Server; API Key ใหม่แสดงค่าเต็มเพียงครั้งเดียวตอนสร้าง

CREATE A CHECKOUT · BASH
curl -sS -X POST "https://payment.cytechteam.dev/v1/checkouts" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"merchant_ref":"order-1001","amount":"20.00","verification_method":"decimal"}'

แทน cyt_next_REPLACE_WITH_YOUR_KEY ด้วย Merchant API Key จริงของร้าน และเปลี่ยน merchant_ref ให้ไม่ซ้ำในแต่ละออเดอร์. ตัวอย่างใช้ URL เต็ม ไม่ต้องตั้งตัวแปร BASE หรือ KEY ใน Terminal. คำสั่งนี้สร้างบิลจริงบน Live environment

ออก Checkout แรกแบบเร็ว

ตัวอย่างด้านล่างใช้ URL เต็มของ Live API และใช้ cyt_next_REPLACE_WITH_YOUR_KEY แทนคีย์จริง โดยไม่ต้องตั้งตัวแปร Shell. ดู Quickstart แบบทีละขั้น เพื่อสร้างบิล เปิดหน้าจ่ายเงิน แล้วรับ webhook หรือ polling สถานะ. merchant_ref ต้องไม่ซ้ำสำหรับแต่ละออเดอร์

1. Create

POST /v1/checkouts
curl -X POST "https://payment.cytechteam.dev/v1/checkouts" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"merchant_ref":"order-1001","amount":"20.00","verification_method":"decimal"}'

2. Open

Response มี payment_path เช่น /pay/pay_... ให้เปิดหรือส่งให้ลูกค้า

3. Confirm

ฟัง payment.confirmed ที่ webhook หรือ poll GET /v1/checkouts/<id> จนสถานะเป็น PAID

เงินหนึ่งรายการ เดินทางอย่างไร?

ความเข้าใจวงจรของบิลสำคัญมาก โดยเฉพาะระบบเติมเครดิตหรือส่งสินค้าอัตโนมัติ

PENDINGรอลูกค้าโอนเงินหลังสร้าง Checkout จะได้ URL และ QR บิลมีอายุ 15 นาที
→
PAIDหลักฐานตรงเพียงบิลเดียวตรวจแจ้งเตือนจาก LINE ธนาคารแล้วจับคู่ได้อย่างไม่กำกวม
→
WEBHOOKแจ้งร้านให้ส่งมอบส่ง payment.confirmed และใช้ event ID ป้องกันทำซ้ำ
EXPIRED

หมดอายุ

ครบ 15 นาทีแล้วยังไม่ยืนยัน ไม่ควรใช้ QR เดิม ให้สร้างออเดอร์ใหม่ด้วย merchant_ref ใหม่

UNMATCHED / AMBIGUOUS

หลักฐานจับคู่ไม่ได้

ไม่พบออเดอร์ที่ตรง หรือพบหลายออเดอร์ ระบบจะไม่สุ่มเลือกบิล ต้องตรวจเหตุการณ์และยอดรับเงินจริง

สำคัญสำหรับระบบอัตโนมัติ

การที่ลูกค้าเห็น QR หรืออัปโหลดรูปสลิป ไม่ได้แปลว่าบิลสำเร็จ ห้ามเปลี่ยนสถานะออเดอร์เองจนกว่าจะได้รับหลักฐานสถานะ PAID จาก Server

เลือกวิธีตรวจสอบยอดโอน

เลือกให้เหมาะกับข้อมูลที่คุณรู้เกี่ยวกับผู้โอน และตรวจให้แน่ใจว่าเงื่อนไขตรงตามธุรกรรมจริง

หนึ่งบิลเลือกได้หนึ่งวิธี และจะถูกจับคู่กับ LINE bank notification ที่ผ่านการตรวจผู้ส่งและเงื่อนไขอื่นของรายการ (บัญชีผู้รับ ยอดเงิน และเวลา) เท่านั้น

MethodValueMatch rule
decimalไม่ต้องส่งเศษสตางค์ของยอดจริงตรงกับ expected cents
name_exact2–150 charsชื่อผู้โอน normalize แล้วตรง exact
account_last44 digitsเลขบัญชีผู้โอน 4 หลักท้ายตรง
bankBank code/nameธนาคารผู้โอนตรง

เลือกวิธีไหนให้เหมาะ?

decimal: เหมาะกับบิลทั่วไปเมื่อยืนยันด้วยเศษสตางค์ แต่ถ้าเปิดบิลยอดเดียวกันหลายใบพร้อมกัน แนะนำ amount_mode: "unique_cents" เพื่อให้ระบบจัดสรรเศษสตางค์ไม่ซ้ำ

name_exact: ใช้เมื่อทราบชื่อบัญชีผู้โอนที่จะแสดงในแจ้งเตือนอย่างแน่นอน · account_last4: ใช้เลขบัญชี ผู้โอน 4 หลักท้าย ไม่ใช่เลขบัญชีรับเงิน · bank: เหมาะเมื่อทราบธนาคารของผู้โอน

แยกบิลยอดเท่ากันด้วย Unique Cents

UNIQUE CENTS · POST CHECKOUT
curl -sS -X POST "https://payment.cytechteam.dev/v1/checkouts" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"merchant_ref":"order-1003","amount":"20.00","verification_method":"decimal","amount_mode":"unique_cents"}'
ยอดที่ลูกค้าต้องโอน คือ checkout.amount ที่ API ตอบกลับ

เช่น ร้านขอ 20.00 บาท แต่ระบบอาจคืน 20.01 บาท เพื่อแยกบิล อย่าแสดงยอด 20.00 แทนค่าที่ตอบกลับ โหมดนี้ใช้ได้เฉพาะจำนวนเต็มบาทและวิธี decimal เท่านั้น

ถ้าพบศูนย์บิล ระบบเก็บ event เป็น UNMATCHED. ถ้าพบหลายบิลเป็น AMBIGUOUS และไม่เปลี่ยนบิลใด ๆ

เชื่อมต่อกับเว็บไซต์ บอท และระบบสมาชิก

ไม่ว่าลูกค้าจะกดซื้อจากหน้าเว็บ Discord bot หรือเกม ขั้นตอนหลักเหมือนกัน: Server ของคุณสร้างออเดอร์ → ขอ Checkout → ส่งลิงก์ให้ลูกค้า → รอ PAID → ส่งมอบบริการ

WEB STORE

เว็บขายสินค้า

สร้างบิลเมื่อกดสั่งซื้อ บันทึก merchant_ref คู่กับหมายเลขออเดอร์ ส่งลิงก์จ่ายเงินไปหน้า checkout จากนั้นรอ Webhook

DISCORD / GAME

เติมเครดิตผ่านบอท

ให้ Backend ของบอทเรียก API แล้วส่ง payment link ไปให้ผู้ใช้ รอ PAID ก่อนเพิ่มเครดิต และบันทึก event ID กันเติมซ้ำ

MEMBERSHIP

ต่ออายุสมาชิก

สร้าง Checkout ใหม่ทุกงวดหรือทุกคำสั่งซื้อ ใช้เลขอ้างอิงใหม่ ไม่ถือว่าจ่ายแล้วเพียงเพราะเปิดลิงก์ชำระเงิน

ตัวอย่าง Node.js — สร้างบิลจาก Backend

NODE.JS · SERVER ONLY
const response = await fetch('https://payment.cytechteam.dev/v1/checkouts', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer ' + process.env.CYTECH_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    merchant_ref: 'order-' + crypto.randomUUID(),
    amount: '20.00',
    verification_method: 'decimal'
  })
});
if (!response.ok) throw new Error('Checkout failed: ' + response.status);
const { checkout } = await response.json();
const paymentUrl = 'https://payment.cytechteam.dev' + checkout.payment_path;
console.log(paymentUrl, checkout.id);

ตัวอย่าง Python — สร้างบิลจาก Backend

PYTHON · REQUESTS
import os
import requests

resp = requests.post(
    "https://payment.cytechteam.dev/v1/checkouts",
    headers={"Authorization": "Bearer " + os.environ["CYTECH_API_KEY"]},
    json={"merchant_ref": "order-1002", "amount": "20.00",
          "verification_method": "decimal"},
    timeout=15,
)
resp.raise_for_status()
checkout = resp.json()["checkout"]
print("https://payment.cytechteam.dev" + checkout["payment_path"])

ตรวจสถานะหากยังไม่มี Webhook

GET /v1/checkouts/{pay_id}
curl -sS "https://payment.cytechteam.dev/v1/checkouts/pay_REPLACE_WITH_REAL_ID" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY"

Polling ควรทำจาก Backend ตามช่วงเวลาที่เหมาะสมและหยุดเมื่อ PAID, EXPIRED หรือ CANCELLED หากต้องการส่งมอบอัตโนมัติแนะนำใช้ Webhook เป็นช่องทางหลักและใช้ GET ตรวจสอบซ้ำได้

เชื่อมต่อ AI ด้วย MCP (Model Context Protocol)

Docs MCP สำหรับอ่านคู่มือสาธารณะผ่าน https://payment.cytechteam.dev/v1/mcp/docs โดยไม่ต้องล็อกอิน ใช้ค้นหัวข้อและอ่าน Markdown เท่านั้น

Manager MCP สำหรับอ่านข้อมูล Workspace โปรเจกต์ และ Checkout ผ่าน https://payment.cytechteam.dev/v1/mcp/manager รองรับ OAuth 2.1 ให้ล็อกอิน Payment แล้วเลือก Workspace และสิทธิ์บนหน้าขออนุญาต ไม่ต้องวาง Merchant API Key ลงในแอป AI

OAuth 2.1 / ความปลอดภัย

รองรับ OAuth Discovery, Dynamic Client Registration, Authorization Code + PKCE (S256), Access/Refresh Token และเพิกถอนแอป AI ใน Console ได้ สิทธิ์อ่าน mcp:read แยกจากสิทธิ์สร้าง Checkout mcp:write โปรดตั้งค่า AI ให้ขออนุมัติก่อนสร้างบิลรับเงินจริง ผู้ใช้ที่ต้องการตั้งค่าแบบเก่าด้วย Merchant API Key ยังใช้ได้ใน MCP Client ที่รองรับ Bearer Header

ดูตัวอย่างการเชื่อมต่อหลายแพลตฟอร์มได้ที่ ตั้งค่าบัญชี → MCP Integration

แยก Projects และจัดการ Workspaces

Workspace ใช้จัดการพื้นที่ร้านและสิทธิ์การเข้าถึงใน Merchant Console ส่วน Project ใช้แบ่งระบบย่อยของร้าน เช่น เว็บ A, Discord Bot, ร้านค้า B โดยใช้รหัส prj_... ของ Project ใน Checkout หรือ API Key ที่ผูก Project

MERCHANT

Key ระดับร้าน

API Key ที่ไม่ได้ผูก Project สามารถทำงานตามสิทธิ์ Merchant และเลือก Project ที่ต้องการสำหรับ Checkout ได้

PROJECT

Key จำกัด Project

สิทธิ์จะถูกจำกัดใน Project เดียว ช่วยแยกข้อมูลและลดการเข้าถึง Checkout ของโปรเจกต์อื่นโดยไม่ตั้งใจ

GET/v1/projects

เรียกรายการโปรเจกต์ที่สิทธิ์ปัจจุบันเข้าถึงได้ เลือก Project จาก Console เมื่อใช้งานหลายระบบ และใช้ project ใน request เฉพาะเมื่อทราบ ID จริงแล้ว

การตรวจเงินด้วย LINE ธนาคาร

Payment CytechTeam Dev ไม่ได้เชื่อมกับบัญชีธนาคารโดยตรง แต่รับข้อความแจ้งเตือนผ่าน LINE Worker แล้วตรวจสอบเงื่อนไข เช่น ผู้ส่งที่รู้จัก ยอดโอน ผู้รับ เวลาของรายการ และวิธีจับคู่ที่เลือกไว้

SENDER

ตรวจแหล่งที่มา

Worker ตรวจชื่อ Official Account ตามนโยบายที่กำหนดในระบบ บันทึกข้อมูลเพื่อ audit โดยไม่ได้เท่ากับการรับประกันการยืนยันตัวจากธนาคารโดยตรง

MATCHING

จับคู่บิลที่ตรง

ระบบไม่เดาว่าเงินเข้าบิลไหน เมื่อพบหลายบิลตรงกันจะทำเครื่องหมาย AMBIGUOUS และยังไม่ยืนยันบิลใด

GET/v1/merchant/bank-events?limit=50

ใช้สำหรับตรวจรายการแจ้งเตือนจากธนาคารที่ระบบรับไว้ภายใต้สิทธิ์ของร้าน ควรเปรียบเทียบกับข้อมูลในธนาคารจริงเมื่อเกิดความคลาดเคลื่อน

ดูธนาคารที่ระบบระบุไว้ใน Bank coverage หรือเรียก GET /v1/banks เพื่อดูรายการที่ API ประกาศรองรับ

รับซองอั่งเป้า TrueMoney

รับซองอั่งเป้า TrueMoney เข้า wallet ของร้าน ยิงครั้งเดียวต่อซอง ไม่ retry อัตโนมัติ ผ่านได้เฉพาะ POST เท่านั้น

Request

POST /v1/merchant/truemoney/redeem
curl -X POST "https://payment.cytechteam.dev/v1/merchant/truemoney/redeem" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mobile":"0812345678","voucher":"https://gift.truemoney.com/campaign/?v=..."}'

States

  • SUCCESS — เงินเข้าแล้ว ยอดส่งผ่านตรง ไม่ปัดเป็น 0.00
  • FAILED — upstream ตอบปฏิเสธชัดเจน (code จาก TrueMoney)
  • PENDING_RECONCILIATION — timeout/network ขาด ซองอาจถูกใช้ไปแล้ว ห้ามยิงซ้ำเอง ต้อง reconcile

ซองเดิมเรียกซ้ำคืนแถวเดิม (200 + duplicate:true) ซองเดิมแต่คนละเบอร์ได้ 409. ส่ง "retry":true เพื่อยิงซ้ำเฉพาะเคสชั่วคราว (edge block, rate limit, timeout, 5xx) — SUCCESS กับ code สุดท้ายปฏิเสธด้วย 409 ยกเว้น "retry":"force" ที่ยิงซ้ำได้ครั้งเดียวสำหรับแถวเก่าที่บันทึกด้วยโค้ดรุ่นก่อน (ไม่ใช่ SUCCESS). ประวัติรายการรับซองอยู่ที่ GET /v1/merchant/truemoney/redemptions และดูร่วมกับ Checkout ได้ที่หน้า ธุรกรรม หรือ GET /v1/merchant/transactions?channel=truemoney โดยกรอง channel=all|checkout|truemoney, status, limit, offset ได้ ประวัติรวมแสดงรหัสซองและเบอร์ผู้รับแบบปิดบางส่วน ไม่แสดงลิงก์ซองเต็ม

รายการ TrueMoney ที่สำเร็จแสดงจำนวนเงินจริงตามผลตอบกลับ หากยังยืนยันยอดไม่ได้ ระบบจะแสดงว่าไม่ทราบยอดแทน 0.00 และจะไม่รวมยอดซองเข้ากับสถิติ Checkout โดยอัตโนมัติ เพื่อไม่ให้นับยอดซ้ำ

TrueMoney ใช้ unofficial upstream API และไม่รับประกันความพร้อมใช้งานจากผู้ให้บริการภายนอก. Server Live ติดตั้ง curl-cffi สำหรับ Chrome-compatible TLS แล้ว แต่ยังต้องตรวจผลตอบกลับของแต่ละซองจริง และไม่ควร retry ซองที่สถานะกำกวมก่อน reconcile

สร้าง Checkout

POST/v1/checkouts

Body

FieldTypeRequiredNotes
merchant_refstringyes1–128 chars: A-Z a-z 0-9 _ . : / -
amountstringyesPositive, up to 2 decimals, max 9,999,999.99
verification_methodstringnodecimal (default), name_exact, account_last4, bank
verification_valuestringconditionalRequired except decimal
amount_modestringnoexact (default) or unique_cents (decimal, whole baht)
receiver_promptpaystringnoPer-bill PromptPay; needs receiver_bank + receiver_last4 together, else merchant default
receiver_bankstringnoPer-bill receiver bank code
receiver_last4stringnoPer-bill receiver last4

Response

201 CREATED
{
  "checkout": {
    "id": "pay_...",
    "merchant_ref": "order-1001",
    "amount": "20.00",
    "status": "PENDING",
    "verification_method": "decimal",
    "payment_path": "/pay/pay_...",
    "expires_at": "2026-10-25T12:15:00+00:00"
  }
}

ดึงข้อมูล Checkout และรายการ

GET/v1/checkouts/<pay_id>

คืน checkout ของ merchant นี้เท่านั้น ถ้าไม่พบจะได้ 404 แบบไม่เปิดเผยว่ามีอยู่จริงหรือไม่

POST/v1/checkouts/<pay_id>/cancel

ยกเลิกบิลที่ยังเป็น PENDING โดยส่ง JSON {} พร้อม Merchant API Key หรือ Console session บนเซิร์ฟเวอร์ จะได้ผลลัพธ์ {"checkout":{"status":"CANCELLED",...}} การกดซ้ำปลอดภัย (idempotent) แต่บิล PAID หรือหมดเวลาแล้วตอบ 409, คนละ Workspace/Project ได้ 404 ไม่ใช่การคืนเงิน และควรใช้ merchant_ref ใหม่เมื่อสร้างบิลทดแทน

CANCEL CHECKOUT · BASH
curl -X POST "https://payment.cytechteam.dev/v1/checkouts/pay_REPLACE_WITH_REAL_ID/cancel" \
  -H "Authorization: Bearer cyt_next_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

หน้าจ่ายเงินมีปุ่มยกเลิกสำหรับผู้ถือ URL ของบิลผ่าน POST /pay/<pay_id>/cancel (ต้องเป็น JSON และเรียกจาก Origin เดียวกัน) ระบบหยุดแสดง QR และแจ้ง payment.cancelled ผ่าน Webhook และ Custom Notification ที่สมัคร event นี้ไว้ หากโอนไปแล้วหรือโอนผิดหลังยกเลิก ต้องตรวจยอดและจัดการคืนเงินแยกต่างหาก

GET/v1/merchant/checkouts?status=PAID&limit=50&offset=0

รายการล่าสุดสำหรับ Console และรายงาน. รองรับ status PENDING, PAID, EXPIRED, CANCELLED

GET/v1/merchant/profile

ดูข้อมูล Merchant ปัจจุบัน ใช้ตรวจสอบ Key และรายละเอียดบัญชีรับเงินที่ตั้งค่าไว้

GET/v1/merchant/overview

อ่านภาพรวมธุรกรรมของร้าน หรือระบุ Project เมื่อมีหลายโปรเจกต์

หน้าชำระเงินสาธารณะและ QR

GET/pay/<pay_id>
GET/pay/<pay_id>/status
GET/pay/<pay_id>/qr.png

หน้า public ไม่ต้องใช้ API key. QR จะถูกปฏิเสธเมื่อบิลไม่ใช่ PENDING. Status endpoint คืนเฉพาะสถานะที่ปลอดภัย

ใช้ใน Frontend ได้เฉพาะ Public URL

หน้า /pay/... และ /pay/.../status ออกแบบให้ลูกค้าเข้าถึงได้โดยไม่เปิดเผย Key ส่วน endpoint /v1/checkouts/... ต้องเรียกจาก Backend ที่ยืนยันตัวแล้ว

Webhook: รับสถานะชำระเงินอัตโนมัติ

ตั้งค่าจุดรับในเมนู API & Checkout หรือใช้ POST /v1/merchant/webhook จากบัญชีที่มีสิทธิ์ Merchant และระบุ HTTPS URL ที่เข้าถึงจากอินเทอร์เน็ตได้

เมื่อยืนยันสำเร็จ ระบบเขียน outbox ใน transaction เดียวกับ PAID แล้วส่ง POST ไปยัง URL ของร้าน

POSThttps://merchant.example/payments

Headers

HeaderMeaning
X-Cytech-Event-IDID สำหรับ deduplication
X-Cytech-TimestampUnix seconds
X-Cytech-SignatureHMAC-SHA256(secret, timestamp + "." + raw_body)
PAYLOAD
{
  "type": "payment.confirmed",
  "data": {
    "id": "pay_...",
    "merchant_ref": "order-1001",
    "amount": "20.00",
    "status": "PAID",
    "confirmation_basis": "BANK_LINE_NOTIFICATION",
    "funds_received": true
  }
}

Retries: bounded exponential backoff, สูงสุด 7 ครั้ง. ฝั่งร้านควรตอบ 2xx และ dedup ด้วย event ID

ตรวจสอบลายเซ็น Webhook ด้วย Node.js

บน Backend ติดตั้ง npm install express ใช้ Node.js แบบ ES Modules และกำหนด CYTECH_WEBHOOK_SECRET จาก Console (Secret แสดงครั้งเดียวเมื่อสร้างหรือ Rotate)

คำนวณ HMAC จาก timestamp + "." + raw_body ด้วย Webhook Secret ที่ตั้งค่าของร้าน ตรวจ timestamp เพื่อป้องกัน replay และใช้การเปรียบเทียบแบบ timing-safe ก่อนอ่านข้อมูลคำสั่งซื้อ

NODE.JS · EXPRESS RAW BODY
import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';

const app = express();
app.post('/payments', express.raw({ type: 'application/json' }), (req, res) => {
  const ts = req.get('X-Cytech-Timestamp') || '';
  const sent = req.get('X-Cytech-Signature') || '';
  if (!/^\d+$/.test(ts) || Math.abs(Date.now()/1000 - Number(ts)) > 300)
    return res.sendStatus(401);
  const expected = createHmac('sha256', process.env.CYTECH_WEBHOOK_SECRET)
    .update(ts + '.').update(req.body).digest('hex');
  const received = sent.replace(/^sha256=/i, '');
  if (!/^[a-f0-9]{64}$/i.test(received) ||
      !timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(received, 'hex')))
    return res.sendStatus(401);
  const event = JSON.parse(req.body.toString('utf8'));
  const eventId = req.get('X-Cytech-Event-ID');
  // Queue a transaction: persist eventId uniquely, then fulfill PAID order once.
  // Acknowledge 2xx after durable processing or queuing.
  return res.sendStatus(204);
});
app.listen(Number(process.env.PORT || 3000));
ตัวอย่างนี้เป็นตัวตรวจลายเซ็น

คุณยังต้องทำส่วนบันทึก event ID และอัปเดตออเดอร์ในฐานข้อมูลจริง เพื่อไม่ให้ callback ที่ส่งซ้ำทำให้เติมเงินหรือส่งสินค้าซ้ำ

Idempotency และการป้องกันซ้ำ

(merchant_id, merchant_ref) ไม่ซ้ำ. การเรียก create ซ้ำด้วย ref และข้อมูลเดิมจะคืน checkout เดิม. ถ้า ref เดิมแต่ยอด/วิธีตรวจสอบต่าง จะได้ 409

LINE message ID ซ้ำจะไม่สร้าง event ใหม่และไม่จ่ายบิลซ้ำ

รหัส HTTP Error

StatusMeaningExample
401Missing/invalid credentialunauthorized
404Not found or not ownednot_found
409Conflict / duplicate ref mismatchmerchant_ref already belongs...
422Validation erroramount must have 0 to 2 decimals
500Internal error (no detail exposed)internal_error

ขีดจำกัดและข้อกำหนด

  • Checkout expiry: 15 minutes
  • Amount: positive, max 9,999,999.99 THB
  • merchant_ref: 1–128 token chars
  • API key limit: 10 active keys per merchant
  • Webhook body/outbox: bounded retries, สูงสุด 7 attempts
  • Console session: 30 days, ยกเลิกได้ด้วย Logout หรือ Password Reset

แก้ปัญหาที่พบบ่อย

ตรวจจากขั้นตอนที่เกี่ยวข้องก่อนแก้ไขในระบบร้าน อย่าสร้าง Checkout หรือส่งมอบสินค้าซ้ำโดยไม่ได้ตรวจสถานะเดิม

สร้าง Checkout ไม่ได้ / ได้ 401 Unauthorized

ตรวจว่า Header เป็น Authorization: Bearer cyt_next_... และ Key ไม่ถูกเพิกถอนหรือหมดสิทธิ์ ตรวจว่าใช้ Key ของร้าน/Project ที่ถูกต้อง ไม่ใช่ Session Cookie ของหน้าเว็บ

ได้ 422 หรือสร้างบิลแล้วข้อมูลไม่ผ่าน Validation

ตรวจ merchant_ref ความยาว 1–128 ตัวอักษรและอักขระที่อนุญาต ยอดต้องเป็นสตริงเลขบวกทศนิยมไม่เกิน 2 ตำแหน่ง กรณีเลือก name_exact, bank หรือ account_last4 ต้องระบุ verification_value

ได้ 409 เมื่อใช้ merchant_ref เดิม

หมายเลขอ้างอิงนี้เคยถูกสร้างด้วยข้อมูลไม่เหมือนเดิม ห้ามใช้ ref เดิมกับยอดใหม่ ให้สร้าง order ID ใหม่สำหรับคำสั่งซื้อใหม่ และเก็บ ref เดิมไว้สำหรับการ retry request เดิม

ลูกค้าโอนแล้ว แต่บิลยัง PENDING

ตรวจรายการเงินจริงกับธนาคารก่อน จากนั้นตรวจเวลาบิล (15 นาที), ยอดที่ลูกค้าโอน, ธนาคารและบัญชีผู้รับ 4 หลักท้าย, LINE Worker/Bank alerts, วิธีตรวจที่ระบุ และเหตุการณ์ UNMATCHED/AMBIGUOUS ห้ามปรับ PAID โดยเดา

เปิดหน้าจ่ายเงินแล้ว QR ไม่แสดง / ได้ 410

ตรวจ ID ว่าอยู่ในรูป pay_... และบิลยัง PENDING หากบิลหมดอายุหรือ PAID แล้ว API QR จะไม่ให้ใช้งาน ให้สร้างบิลใหม่หากยังต้องชำระ

สถานะ PAID แต่ฝั่งร้านไม่ได้รับ Webhook

ตรวจ URL ต้องเป็น HTTPS แบบ Public, DNS/TLS ถูกต้อง และ endpoint ตอบ 2xx ได้ ตรวจ Firewall, Log ฝั่งรับ, Event ID และสถานะระบบที่ Status ระบบมี retry สูงสุด 7 ครั้ง จึงควรทำตัวรับให้ idempotent และมีทางเช็กด้วย GET

TrueMoney แสดง PENDING_RECONCILIATION

ปลายทางตอบไม่แน่ชัด (เช่น timeout) ซองอาจถูกใช้แล้ว อย่าเรียก redeem ซ้ำทันที ตรวจประวัติและยอดใน Wallet ก่อน แล้วค่อยจัดการ reconciliation

แนวทางใช้งานจริงที่แนะนำ

✓

แยก Checkout ออกจากคำสั่งซื้อบันทึก pay_id, merchant_ref, ยอด และสถานะในฐานข้อมูลของคุณเสมอ

✓

ตรวจ Webhook signature จาก raw bodyอย่าเอา JSON ที่ parse แล้วไป serialize ใหม่ก่อน HMAC

✓

ส่งมอบครั้งเดียวเท่านั้นใช้ event ID หรือ order ID เป็น unique key และบันทึกว่าเคยเติมเครดิต/ส่งสินค้าแล้ว

✓

เก็บ API Key ใน Serverใช้ environment variables หรือ secret manager ไม่วางใน frontend, แอปที่แจก หรือ GitHub

✓

แยกโปรเจกต์ตามงานใช้ Project-scoped API Key เมื่อมีเว็บ บอท หรือผู้ดูแลหลายชุด

✓

ตรวจความพร้อมและทำแผนสำรองเฝ้าดู /status, มีวิธีตรวจยอดด้วยคน และรองรับความล่าช้าของ LINE notification

คำถามที่พบบ่อย (FAQ)

จำเป็นต้องมีเว็บไซต์หรือเขียนโค้ดไหม?

ดูข้อมูลร้านและสร้างบิลผ่าน Merchant Console ได้ ส่วนการสร้างบิลจากเว็บ บอท หรือเติมเครดิตอัตโนมัติควรมี Backend สำหรับเก็บ API Key และรับ Webhook

ใช้ PromptPay เบอร์โทรหรือเลขบัตรประชาชนได้ไหม?

ใช้รูปแบบ PromptPay ที่หน้าตั้งค่าร้านรองรับและตรวจให้แน่ใจว่าปลายทางที่สร้าง QR ตรงกับบัญชีรับเงินจริง หากไม่มั่นใจให้ทดสอบกับธนาคารของคุณก่อนเปิดขายจริง

ทำไมระบบไม่ยืนยันจากรูปสลิปที่ลูกค้าส่งมา?

ระบบนี้ใช้ LINE bank notification เป็นหลักฐานการรับเงิน ไม่ใช้ภาพสลิปเป็นตัวตัดสิน เพื่อหลีกเลี่ยงการยืนยันจากไฟล์ที่แก้ไขหรือใช้ซ้ำได้

API มี Sandbox สำหรับทดสอบไหม?

ตัวอย่างทั้งหมดในหน้านี้ใช้ Live API ของ payment.cytechteam.dev อย่าทดสอบด้วยยอดจำนวนมาก และอย่าสมมติว่ามี Sandbox แยกหากยังไม่ได้รับข้อมูลยืนยันจากผู้ดูแลระบบ

บิลหมดอายุแล้วลูกค้าเพิ่งโอนควรทำอย่างไร?

ตรวจรายการเงินจริงกับธนาคารและสถานะบิลก่อน อย่าจ่ายเครดิตหรือสร้างรายการ PAID เองโดยไม่พิสูจน์ ตรวจหาธุรกรรมที่ไม่ถูกจับคู่และดำเนินการตรวจสอบด้วยคน

เป็น Payment Gateway หรือ Bank API โดยตรงหรือไม่?

ไม่ใช่บริการชำระเงินของธนาคารหรือ Settlement API โดยตรง ระบบช่วยสร้างบิลและตรวจสอบข้อมูลการรับเงินจากการแจ้งเตือน LINE ธนาคาร ซึ่งมีข้อจำกัดขึ้นกับแหล่งข้อมูลภายนอก

ความปลอดภัยและขอบเขตบริการ

  • Live LINE Worker ปัจจุบันตั้ง CYTECH_LINE_SENDER_POLICY=name ตรวจชื่อ LINE Official Account ที่ normalize แล้วแบบตรงตัวกับชื่อธนาคารที่รู้จัก โดยบันทึก MID เพื่อ audit แต่ไม่ได้ยืนยัน MID allowlist หรือ Verified/Premium badge ในโหมดนี้. โค้ดยังรองรับโหมด mid, badge_name และ mid_or_badge_name เมื่อกำหนดค่าต่างออกไป
  • Internal LINE bridge ใช้ HMAC signature และกรอบเวลา ±90 วินาที; การยืนยันแบบ BANK_LINE_NOTIFICATION ไม่ใช่ Bank Settlement โดยตรง
  • API keys และ Console sessions ถูกเก็บเป็น hash; Browser Console ใช้ Secure HttpOnly SameSite=Strict Cookie อายุ 30 วัน
  • Webhook URLs ต้องเป็น public HTTPS และห้าม resolve ไปยัง private/literal host
  • จำนวนเงินเก็บเป็นจำนวนเต็มหน่วยสตางค์
อ่าน Platform และ Banks เพื่อเข้าใจขอบเขตการยืนยันผ่าน LINE ธนาคารและข้อจำกัดของแต่ละช่องทาง