← กลับหน้าลูกค้าและสิทธิ์
เป็นใจ · คู่มือสำหรับผู้พัฒนาระบบลูกค้า

Customer Command API v1

ส่งคำสั่งจากเซิร์ฟเวอร์ของคุณ แล้วตรวจสถานะหรือรับผลผ่าน Webhook

https://penjai.svenme.com/v1/customer

คู่มือติดตั้งและตั้งค่ามือถือรุ่นปัจจุบัน ↗

อัปเดตคู่มือรายงานจากปุ่มทดสอบ SCB วันที่ 26 กันยายน 2569 · ใช้ Customer API v1 และ API Key เดิม

1. เตรียมเชื่อมต่อ

รับ API Key และ accountId จากผู้ดูแลเป็นใจ ส่วน Webhook secret รับได้เมื่อตั้งค่าใน APK เป็นใจหรือผ่านผู้ดูแล เก็บในระบบจัดการความลับของเซิร์ฟเวอร์ ไม่ใส่ใน JavaScript ฝั่งเบราว์เซอร์หรือแอพลูกค้า API Key และ Key เปิดแอพมีหน้าที่ต่างกัน แต่เป็นของลูกค้ารายเดียวกัน API Key ใช้ได้จนกว่าถูกยกเลิก ไม่ต้องส่ง PIN ธนาคารหรือ PIN โทรศัพท์

ส่ง Authorization: Bearer pjc_… ทุกคำขอ ไม่ต้องเข้าสู่หน้าแอดมิน บัญชีที่ผูกแล้วใช้อ่านยอดและโอนได้โดยไม่ต้องให้ผู้ดูแลเปิดสิทธิ์เพิ่ม

ความพร้อมมือถือและการอัปเดต

รับงานจาก API ต้องใช้ Android 14 ขึ้นไป ตั้งค่าตัวช่วยให้ขึ้น มือถือพร้อมแล้ว เพิ่มและทดสอบบัญชี อนุญาตให้ทำงานเบื้องหลัง แล้วเปิด รับงานจาก API เมื่อเจ้าของเครื่องมี API Key ที่ใช้งานได้ ระบบจะผูกบัญชี SCB ที่มือถือรายงานให้อัตโนมัติ บัญชีของลูกค้าใช้ได้ทั้งอ่านยอดและโอนเงิน รวมถึงบัญชีเดิม โดยไม่ต้องให้ผู้ดูแลเปิดสิทธิ์รายบัญชี ระบบยังตรวจความพร้อม ความสามารถมือถือ และข้อมูลรายการก่อนทำงาน เครื่องที่เคยปลดยังคงต้องผูกกลับด้วยตนเอง

วิธีใช้หน้าจอสิ่งที่ต้องตั้งค่า
เปิดจอไว้เองไม่ต้องบันทึก PIN โทรศัพท์ในเป็นใจ เปิดหน้าจอและปลดล็อกไว้เอง เปิดตัวเลือกคงหน้าจอในหน้ารับงานจาก API ได้ หากจอดับหรือล็อก ต้องปลดล็อกเองก่อนรับงานใหม่
ปลดล็อกอัตโนมัติในมือถือ เข้า ตั้งค่ามือถือ → จัดการการปลดล็อก กรอก PIN ล็อกหน้าจอแล้วกด บันทึกและทดสอบ PIN ยืนยันเจ้าของเครื่อง รอนับถอยหลังแล้วล็อกจอภายใน 8 วินาที แอพตรวจแป้นก่อนลองรหัสหนึ่งครั้ง และเปิดใช้อัตโนมัติเฉพาะเมื่อปลดล็อกสำเร็จ

รุ่น 3.14.0-rc9 เพิ่มการรองรับแป้น ColorOS ที่ทดสอบปลดล็อกจริงบน OPPO CPH2591 / Android 15 / ภาษาไทย แล้ว รุ่นหรือภาษาอื่นต้องผ่านการทดสอบบนเครื่องนั้นก่อน หากอ่านแป้นไม่ได้หรือทดสอบไม่ผ่าน ยังใช้แบบเปิดจอไว้เองได้ เมื่อเปลี่ยนเครื่อง อัปเดตระบบ หรือเปลี่ยนภาษา ต้องทดสอบปลดล็อกใหม่

ตั้งแต่แอพ 3.14.0-rc4 อัปเดตผ่าน ตั้งค่ามือถือ → ตรวจสอบและอัปเดตแอพ ได้ รุ่นเก่ากว่านี้ต้องติดตั้ง APK ใหม่ทับก่อน หลังติดตั้งให้เริ่มตัวช่วยใหม่และตรวจการปลดล็อกก่อนเปิดรับงานอีกครั้ง หลังรีสตาร์ทมือถือ เจ้าของต้องปลดล็อกครั้งแรกและเริ่มตัวช่วยก่อน

ระบบลูกค้าใช้คำสั่งเดิม ไม่ต้องเพิ่ม PIN หรือรุ่นโทรศัพท์ใน request และไม่มี endpoint Customer API สำหรับส่ง PIN หรือสั่งปลดล็อกโดยตรง การอัปเดตและปลดล็อกตั้งค่าบนมือถือ

ดาวน์โหลดตัวอย่าง Node.js client · ดาวน์โหลดตัวตรวจลายเซ็น Webhook

2. Endpoint

Method / Pathผลที่ได้
GET /accountsitems: accountId, platform, last4, deviceName, ready, readEnabled, transferEnabled, transferSupported, pendingJobs
GET /banksitems: code และ name ของธนาคารปลายทาง
POST /jobs202 งานใหม่ / 200 งานเดิมจาก requestId ซ้ำ
GET /jobs/{jobId}สถานะและผลของงานลูกค้ารายนั้นเท่านั้น
GET /manual-transfer-reportsรายงานสลิปจากปุ่มทดสอบ SCB ของลูกค้ารายนั้น สูงสุด 100 รายงานใน 30 วันล่าสุด แยกจากงานโอน API

หากได้ items: [] ให้ตรวจว่าเพิ่มและยืนยันบัญชี SCB ในมือถือแล้ว ใช้ Key เปิดแอพของลูกค้ารายเดียวกับ API Key และเปิดรับงานจาก API ให้มือถือส่งรายการมา หากเคยปลดเครื่อง ให้ผู้ดูแลผูกกลับด้วยตนเอง งานเดิมที่ยังไม่จบต้องจบก่อนผูกเครื่องครั้งแรก

อ่านความพร้อมจาก GET /accounts

ฟิลด์ความหมาย
readyสถานะพร้อมล่าสุดที่มือถือรายงานภายใน 45 วินาที พร้อมสิทธิ์เครื่องที่ยังใช้ได้ อาจเปลี่ยนก่อนเริ่มงาน จึงไม่ยืนยันว่าเครื่องว่างหรือคำสั่งโอนจะสำเร็จ
readEnabled / transferEnabledคงฟิลด์ไว้เพื่อรองรับระบบที่เชื่อมต่อเดิม ทั้งสองค่าเป็น true สำหรับบัญชีของลูกค้าที่ผูกอยู่ การโอนยังต้องตรวจ transferSupported และความพร้อมมือถือ
transferSupportedความสามารถในการโอนลูกค้าที่มือถือเคยรายงานสำหรับรุ่นแอพนั้น ไม่ใช่สถานะพร้อมโอนทันที
pendingJobsจำนวนงานที่ยังไม่จบบนมือถือทั้งเครื่อง รวมงานของบัญชีอื่นบนเครื่องเดียวกัน

accountId เป็นรหัสคงที่ 32 ตัวอักษรฐานสิบหก ให้ใช้รหัสจาก /accounts ไม่ใช้เลขท้ายบัญชีแทน API รับงานเข้าคิวได้แม้ ready เป็น false หากสิทธิ์และเงื่อนไขของงานผ่าน โดยงานโอนต้องเคยรายงานความสามารถในการโอนที่ระบบยอมรับแล้ว

curl --fail-with-body 'https://penjai.svenme.com/v1/customer/accounts' \
  -H "Authorization: Bearer $PENJAI_API_KEY"

3. ส่งคำสั่ง

สร้าง UUID และบันทึกคำสั่งในฐานข้อมูลของคุณก่อนส่ง เก็บ requestId เดิมตลอดอายุรายการ จำนวนเงินใช้ข้อความทศนิยมสองตำแหน่ง หน่วย THB เช่น "100.00" ไม่ใช่ JSON number มีตัวเลขก่อนจุด 1–15 หลัก และต้องมากกว่า 0 เลขบัญชีเป็นข้อความตัวเลข 6–20 หลัก ไม่มีขีดหรือช่องว่าง ฟิลด์นอก schema จะถูกปฏิเสธ งาน read_balance ใช้เฉพาะ requestId, type และ accountId

อ่านยอด

{
  "requestId": "f07d476b-881c-4453-ab4f-e6970047ff7d",
  "type": "read_balance",
  "accountId": "ACCOUNT_ID_FROM_ACCOUNTS"
}

โอนเงิน

{
  "requestId": "94c03493-b0e2-4584-8460-a1ad2d9f0f2b",
  "type": "transfer",
  "accountId": "ACCOUNT_ID_FROM_ACCOUNTS",
  "bankCode": "TTB",
  "recipientAccount": "RECIPIENT_DIGITS",
  "amount": "100.00"
}

แทนค่าตัวอย่างและบันทึกเป็น command.json แล้วส่ง:

curl --fail-with-body 'https://penjai.svenme.com/v1/customer/jobs' \
  -H "Authorization: Bearer $PENJAI_API_KEY" \
  -H 'Content-Type: application/json' --data-binary @command.json

ธนาคารเริ่มต้น: SCB, KBANK, KTB, BBL, TTB, GSB, BAY, BAAC, UOB, GHB, BNPP ให้ยึดรายการ /banks ล่าสุด มือถือจะตรวจว่ารายการนั้นพร้อมใช้งานจริงอีกครั้ง

202 หมายถึงรับเข้าคิวแล้ว ยังไม่ใช่โอนสำเร็จ หนึ่งมือถือทำทีละงาน สูงสุด 20 งานที่ยังไม่จบ และต้องเริ่มภายใน 5 นาที อ่านยอดมีเวลาทำงาน 180 วินาที โอน 300 วินาทีหลังเริ่ม

ตัวอย่างตอบรับงานใหม่ · HTTP 202

{
  "jobId": "934f211a-22ee-4ea7-9fb8-b40101658a80",
  "requestId": "f07d476b-881c-4453-ab4f-e6970047ff7d",
  "accountId": "0123456789abcdef0123456789abcdef",
  "type": "read_balance",
  "state": "queued",
  "createdAt": "2026-09-22T00:00:00Z",
  "queueExpiresAt": "2026-09-22T00:05:00Z",
  "startedAt": null,
  "finishedAt": null,
  "result": null,
  "error": null,
  "requiresReconciliation": false
}

ตัวอย่างใช้รหัสสมมติ การส่ง requestId เดิมพร้อมคำสั่งเดิมตอบ HTTP 200 ด้วย jobId เดิมและสถานะปัจจุบัน ซึ่งอาจเสร็จแล้ว ไม่สร้างงานใหม่

Node.js

import {penjaiClient} from './customer-client.mjs';
const penjai = penjaiClient(process.env.PENJAI_API_KEY);
const accounts = await penjai.accounts();
// Load the EXACT saved command from your database:
const accepted = await penjai.submit(savedCommand);
// Persist accepted.jobId before polling:
const current = await penjai.job(accepted.jobId);

หาก timeout หรือตอบกลับหาย ให้ส่ง command เดิมรวม requestId เดิม ระบบคืนงานเดิมโดยไม่ทำซ้ำ หากใช้ requestId เดิมกับข้อมูลต่างกันจะได้ 409 request_conflict รหัสคำขอแยกตามลูกค้า การหมุน API Key ไม่เปลี่ยนการกันคำขอซ้ำ

4. สถานะและผล

stateความหมาย
queuedรอคิวหรือรอมือถือรับ
runningมือถือเริ่มทำงานแล้ว
succeededอ่านยอดหรืออ่านผลโอนสำเร็จจากธนาคารแล้ว
failedทำงานไม่สำเร็จ ดู error
expiredไม่ได้เริ่มภายในเวลารอคิว
unknownยังยืนยันผลไม่ได้ ตรวจประวัติธนาคารก่อนส่งรายการใหม่

ทุกงานมี jobId, requestId, accountId, type, state, createdAt, queueExpiresAt, startedAt, finishedAt, result, error, requiresReconciliation ค่าเวลาที่ยังไม่เกิดและผลที่ยังไม่มีเป็น null

ตรวจผลด้วย polling หรือ Webhook

ถ้ายังไม่มี Webhook ใช้ GET /jobs/{jobId} ได้ เก็บ jobId ที่ได้จากการส่งคำสั่ง แล้วเริ่มตรวจทุก 2–5 วินาที โดยรวมคำขออ่านทั้งหมดของลูกค้าไม่เกิน 180 ครั้งต่อนาที เมื่อได้ succeeded, failed, expired หรือ unknown ให้หยุด polling ปกติ งานโอน unknown ต้องตรวจประวัติและติดตามการตรวจทานของผู้ดูแล

curl --fail-with-body "https://penjai.svenme.com/v1/customer/jobs/$PENJAI_JOB_ID" \
  -H "Authorization: Bearer $PENJAI_API_KEY"

หากมือถือไม่พร้อม งานอาจค้าง queued จนหมดเวลารอคิว 5 นาที ตรวจสถานะและแก้ที่มือถือโดยใช้ jobId เดิม อย่าสร้าง requestId ใหม่เพียงเพราะผลตอบช้า หากงานหมดอายุแล้ว การส่ง requestId เดิมจะคืนงานหมดอายุเดิม

ตัวอย่าง result เมื่ออ่านยอดสำเร็จ

{
  "fullName": "ชื่อบัญชีตัวอย่าง",
  "last4": "1234",
  "balance": "250.00",
  "currency": "THB",
  "readAt": "2026-09-22T00:00:20Z"
}

ตัวอย่าง result เมื่อโอนสำเร็จ

{
  "amount": "100.00",
  "currency": "THB",
  "transactionId": "BANK_REFERENCE_25_CHARACTR",
  "bankCompletedAt": "2026-09-15T07:30:00Z",
  "bankTimePrecision": "minute"
}

เวลาของงานใน GET /jobs/{jobId} เป็น ISO 8601 พร้อมเขตเวลา ใช้ UTC (Z) ให้แปลงเป็น Asia/Bangkok เมื่อต้องการแสดงเวลาไทย เวลา SCB ละเอียดระดับนาที เลขวินาที 00 ไม่ใช่วินาทีจริงที่โอน ไม่ส่งไฟล์สลิป

ผลอ่านยอดมี fullName, last4, balance (ข้อความทศนิยม), currency และ readAt โดย currency อาจเป็นข้อความว่างเมื่อ UI ธนาคารไม่ได้แสดงสกุลเงิน เก็บผล 30 วัน จากนั้น result เป็น null แต่เก็บ ID เพื่อป้องกันคำขอซ้ำ

งานโอน unknown จะขวางโอนถัดไปบนเครื่องจนผู้ดูแลตรวจประวัติ การตรวจทานทำให้ requiresReconciliation เป็น false แต่ไม่เปลี่ยน state เป็น succeeded ระบบไม่ยืนยันซ้ำหรือสร้างโอนใหม่อัตโนมัติ

5. Webhook

ตั้ง HTTPS URL สาธารณะหนึ่งรายการต่อลูกค้า ระบบไม่ตาม redirect และไม่ส่งไป IP ภายใน URL ต้องไม่มีข้อมูลล็อกอินและต้อง URL-encode เส้นทางที่ไม่ใช่ ASCII ทุกครั้งที่ส่งจะตรวจ DNS และใบรับรอง TLS ใหม่

ตั้งจาก APK ได้ตั้งแต่รุ่น 3.13.1: เปิดเป็นใจ → หน้าบัญชี → ตั้งค่า Webhook (รุ่น 3.13.5 ขึ้นไป) หรือ ตั้งค่า → รับงานจาก API → ตั้งค่า Webhook รับผล → กรอก URL → เปิดส่งผล → บันทึก แล้วคัดลอก secret ที่แสดงครั้งเดียวไปตั้งค่าบนเซิร์ฟเวอร์รับผล ทุกมือถือที่เปิดใช้งานของลูกค้ารายเดียวกันตั้งค่า URL ร่วมกันได้ หน้าจอแสดงชื่อลูกค้าและสถานะการแจ้งผลล่าสุด โดยไม่ต้องใส่รหัสแอดมินหรือ API Key ลง APK

การแก้จากมือถือมีผลกับทุกเครื่องของลูกค้ารายนั้น หากมีผู้แก้ค่าระหว่างเปิดหน้า ให้โหลดค่าล่าสุดก่อนบันทึก ผู้ดูแลยังแก้ผ่านหน้าเว็บได้ เปลี่ยน URL หรือออก secret ใหม่แล้วต้องอัปเดตค่าบนเซิร์ฟเวอร์ที่รับผลด้วย

{
  "eventId": "EVENT_ID_32_HEX",
  "event": "job.completed",
  "createdAt": "2026-09-15T07:30:12Z",
  "jobId": "JOB_UUID",
  "requestId": "YOUR_SAVED_UUID",
  "accountId": "ACCOUNT_ID",
  "type": "transfer",
  "state": "succeeded",
  "result": {"amount": "100.00", "currency": "THB", "transactionId": "BANK_REFERENCE_25_CHARACTR", "bankCompletedAt": "2026-09-15T07:30:00Z", "bankTimePrecision": "minute"},
  "requiresReconciliation": false
}

ตัวอย่างย่อ: มีฟิลด์เวลาและ error ชุดเดียวกับ GET /jobs เหตุการณ์คือ job.completed เมื่องานสิ้นสุด และ job.reviewed เมื่อผู้ดูแลตรวจทาน unknown แล้ว

X-Penjai-Event-Id: eventId
X-Penjai-Timestamp: Unix epoch seconds ณ ครั้งที่ส่ง
X-Penjai-Signature: v1=HEX_HMAC_SHA256

คำนวณ HMAC-SHA256 โดยใช้ Webhook secret กับข้อมูล timestamp + "." + raw HTTP body bytes ต้องใช้เนื้อหาเดิมก่อน JSON parser ตรวจ timestamp ภายใน ±5 นาทีด้วยเวลาระบบที่เที่ยงตรง และเทียบลายเซ็นแบบ constant-time

import {verifyPenjaiWebhook} from './customer-webhook.mjs';
const event = verifyPenjaiWebhook(rawBody, request.headers,
  process.env.PENJAI_WEBHOOK_SECRET);
// In one database transaction:
// INSERT event.eventId with UNIQUE constraint + update your order.
// A duplicate eventId returns 200 without repeating processing.
// Respond 200 only AFTER the transaction commits.

ส่งทันที แล้วลองใหม่ที่อายุเหตุการณ์ 1, 5, 15 นาที และ 1, 6, 24 ชั่วโมง รวมสูงสุด 7 ครั้ง หากปลายทางไม่ตอบ 2xx หรือ timeout 10 วินาที eventId และ body คงเดิม แต่ timestamp และลายเซ็นเปลี่ยนในแต่ละครั้ง

ต้องรองรับเหตุการณ์ซ้ำและลำดับที่เปลี่ยนได้ อย่าให้ job.completed ที่มาช้าลบสถานะการตรวจทานจาก job.reviewed ส่งการแจ้งผลซ้ำจากแอดมินได้โดยใช้ eventId เดิมและเริ่มตารางลองใหม่ ไม่สร้างงานธนาคารใหม่ Webhook ที่ล้มเหลวไม่เปลี่ยนผลโอน

เมื่อเปลี่ยน URL/secret หรือปิด Webhook งานส่งที่ค้างจะถูกยกเลิก แต่คำขอที่ส่งออกไปแล้วอาจยังถึงปลายทางเดิมได้ ผู้ดูแลเลือกส่งเหตุการณ์เดิมไปค่าปัจจุบันได้ภายใน 30 วัน

6. ข้อผิดพลาดและการเปิดใช้

รูปแบบข้อผิดพลาด {"error":"code","message":"รายละเอียด"} รหัสหลัก:

HTTPerror / การจัดการ
401invalid_api_key — ตรวจหรือเปลี่ยน API Key
403customer_suspended หรือสิทธิ์มือถือถูกระงับ
404not_found — ไม่พบหรือไม่มีสิทธิ์เข้าถึงบัญชี/งาน
409request_conflict — ข้อมูลไม่ตรงคำขอเดิม; upgrade_required — อัปเดตแอพ/ตัวช่วย; reconciliation_required — ให้ผู้ดูแลตรวจรายการ unknown
422invalid_request — ตรวจชนิดข้อมูล/รูปแบบ/ธนาคาร
429queue_full หรือ rate_limited — รอแล้วส่ง requestId เดิม; รับคำสั่ง 30 ครั้ง/นาที และอ่าน 180 ครั้ง/นาทีต่อลูกค้า
503transfer_unconfigured — ติดต่อผู้ดูแลตั้งค่าการโอน

ปัญหาหลังรับเข้าคิวอ่านจาก error ในงาน เช่น not_ready, read_failed, cancelled, timed_out, account_missing, insufficient_funds, review_mismatch, duplicate_reference ห้ามตีความ HTTP 200/202 ว่าโอนสำเร็จ ถ้า not_ready ให้ตรวจตัวช่วย การเปิดรับงาน สิทธิ์เบื้องหลัง และว่าหน้าจอเปิดปลดล็อกไว้หรือทดสอบปลดล็อกอัตโนมัติผ่านแล้ว ใช้ state และ requiresReconciliation ประกอบเสมอ ไม่ลองโอนซ้ำอัตโนมัติจาก error เพียงอย่างเดียว

ผู้ดูแลสร้างลูกค้า → เพิ่ม Key เปิดแอพให้ลูกค้ารายนั้น → ให้พนักงานตั้งค่ามือถือและยืนยันเพิ่มบัญชี → ออก API Key → เปิดรับงานจาก API เพื่อผูกบัญชีอัตโนมัติ → เรียก GET /accounts เพื่อรับ accountId → ตั้ง Webhook → ทดสอบอ่านยอด → อัปเดตแอพและเริ่มตัวช่วยรุ่นปัจจุบัน → ทดสอบโอนเมื่อมือถือพร้อม โดยไม่ต้องเปิดสิทธิ์รายบัญชี เจ้าของบัญชีเป็นผู้ส่งคำสั่งทดสอบโอนและตรวจประวัติธนาคาร

API ไม่มีเพดานวงเงินต่อรายการหรือต่อวันของเป็นใจ จำนวนเงินต้องมากกว่า 0 และอยู่ในรูปแบบตัวเลขที่ระบบรองรับ ยังคงตรวจบัญชีต้นทาง ธนาคาร เลขบัญชีผู้รับ ยอดเงิน ยอดคงเหลือ และค่าธรรมเนียมก่อนอนุญาตยืนยันหนึ่งครั้ง

7. รายงานสลิปจากปุ่มทดสอบ SCB

ใช้เมื่อเจ้าของเครื่องทำรายการผ่าน ทดสอบเส้นทาง SCB ในแอพเป็นใจ เมื่อแอพอ่านสลิปครบจะส่งรายงานเข้า API อัตโนมัติ หรือเจ้าของเครื่องใช้ปุ่ม อ่านสลิปที่เปิดอยู่และส่ง API กับสลิปที่เปิดไว้แล้วได้ หลังแอพแสดง รายงาน API: ส่งสถานะโอนเรียบร้อยพร้อมข้อมูลสลิปแล้ว ระบบลูกค้าจึงดึงรายงานจาก endpoint ด้านล่างได้

รายงานใช้ reportId และแยกจากงานที่สร้างด้วย POST /jobs จึงไม่มี jobId, requestId หรือ accountId และไม่เปลี่ยนผลของงานโอนเดิม การอ่านรายงานเป็นคำขออ่านข้อมูล ไม่สั่งให้มือถือโอนเงิน

ดึงรายงาน · GET /manual-transfer-reports

ส่ง API Key เดิมผ่าน Authorization: Bearer เซิร์ฟเวอร์คืนเฉพาะรายงานของลูกค้าเจ้าของ Key รวมสูงสุด 100 รายงานที่รับเข้ามาภายใน 30 วันล่าสุด เรียง receivedAt จากใหม่ไปเก่า ปัจจุบันไม่มี pagination, cursor หรือพารามิเตอร์กรอง และหากไม่มีรายงานจะคืน {"items":[]}

curl --fail-with-body 'https://penjai.svenme.com/v1/customer/manual-transfer-reports' \
  -H "Authorization: Bearer $PENJAI_API_KEY"

ตัวอย่างตอบกลับ HTTP 200 ต่อไปนี้ใช้ข้อมูลสมมติทั้งหมด:

{
  "items": [
    {
      "reportId": "11111111-2222-4333-8444-555555555555",
      "receivedAt": 1790391610,
      "operation": "manual_transfer_report",
      "state": "succeeded",
      "origin": "scb_route_test",
      "verificationMode": "visible_scb_receipt",
      "receipt": {
        "transactionId": "AAAAAAAAAAAAAAAAAAAAAAAAA",
        "amount": "12.50",
        "fee": "0.00",
        "bankCompletedAt": 1790391600,
        "bankDateTime": "26 ก.ย. 2569 - 10:00",
        "sourceLast4": "1234",
        "recipientLast4": "5678",
        "sourceName": "ชื่อบัญชีต้นทางตัวอย่าง",
        "recipientName": "ชื่อบัญชีผู้รับตัวอย่าง"
      }
    }
  ]
}

ฟิลด์ของรายงาน

ฟิลด์ความหมาย
reportIdUUID ของรายงานที่บันทึกแล้ว ใช้เป็นคีย์กันประมวลผลซ้ำในระบบลูกค้า
receivedAtเวลาที่เซิร์ฟเวอร์รับรายงานครั้งแรก เป็น JSON integer หน่วย Unix seconds ไม่ใช่เวลาโอนและไม่ใช่ milliseconds
operation / originmanual_transfer_report / scb_route_test ระบุรายงานจากหน้าทดสอบของแอพ
state / verificationModesucceeded / visible_scb_receipt หมายถึงแอพอ่านข้อมูลครบจากหน้าสลิป SCB ที่แสดงว่าโอนสำเร็จ ไม่ใช่ผลตรวจ QR สลิปหรือการยืนยันผ่าน API ธนาคาร
receipt.transactionIdรหัสอ้างอิงธนาคาร เป็นข้อความตัวอักษร/ตัวเลข 25 ตัว
receipt.amount / receipt.feeจำนวนเงินและค่าธรรมเนียม หน่วยบาท เป็นข้อความทศนิยมสองตำแหน่ง เช่น "12.50" และ "0.00" ไม่มีฟิลด์ currency ในรายงานนี้
receipt.bankCompletedAtเวลาโอนที่แปลงจากวันเวลาบนสลิป เป็น JSON integer หน่วย Unix seconds ละเอียดระดับนาที แสดงผลไทยด้วยเขตเวลา Asia/Bangkok
receipt.bankDateTimeข้อความวันเวลาตามที่อ่านจาก SCB อาจมีปี พ.ศ. เก็บไว้แสดงผล ใช้ bankCompletedAt เมื่อต้องเปรียบเทียบเวลา
receipt.sourceLast4 / receipt.recipientLast4เลขท้ายบัญชีต้นทางและผู้รับอย่างละ 4 หลัก เป็นข้อความเพื่อรักษาเลขศูนย์นำหน้า ไม่มีเลขบัญชีเต็มในรายงาน
receipt.sourceName / receipt.recipientNameชื่อบัญชีต้นทางและชื่อผู้รับตามที่แสดงบนสลิป

เวลาของรายงานส่วนนี้ (receivedAt และ receipt.bankCompletedAt) เป็น Unix seconds ต่างจากเวลา ISO 8601 ในผล GET /jobs/{jobId} อย่าใช้ตัวแปลงเวลาชุดเดียวกันโดยไม่ตรวจชนิดข้อมูล

การติดตามผลและส่งซ้ำ

รายงานจากปุ่มทดสอบยังไม่สร้าง Webhook job.completed หรือ job.reviewed ให้ดึง endpoint นี้ตามต้องการ โดยรวมคำขออ่าน Customer API ทั้งหมดไม่เกิน 180 ครั้งต่อนาที แล้วบันทึก reportId ที่เคยประมวลผลไว้ รายการที่เกินขอบเขต 100 รายงาน/30 วันไม่สามารถดึงย้อนหลังด้วย pagination ในรุ่นนี้

แอพเก็บรายงานที่ยังไม่ได้รับคำตอบยืนยันไว้ในคิวเข้ารหัส หากส่งไม่สำเร็จ ใช้ ส่งรายงาน API อีกครั้ง ในแอพเพื่อส่งข้อมูลเดิมได้โดยไม่เริ่มรายการธนาคารใหม่ เซิร์ฟเวอร์ตรวจรหัสรายงานและรหัสอ้างอิงเพื่อกันซ้ำ: ข้อมูลเดิมของเครื่องและลูกค้าเดิมจะไม่เพิ่มรายงาน ส่วนข้อมูลที่ขัดแย้งตอบ 409 report_conflict ที่ช่องทางส่งรายงานของมือถือ

แอพส่งผ่าน POST /v1/device/transfer-reports ด้วย operation manual_transfer_report, challenge และลายเซ็นของเครื่อง endpoint นี้เป็นช่องทางของแอพ ไม่รับ Customer API Key แทนลายเซ็น ระบบลูกค้าใช้เฉพาะ GET /v1/customer/manual-transfer-reports เพื่ออ่านรายงาน