Skip to content

1.11 · การชำระผ่าน KBANK K-Cash

บทนี้อธิบาย integration กับธนาคารกสิกรไทย (KBANK) ผ่านระบบ K-Cash — channel หลักที่ VTRC ใช้จ่ายเงินสวัสดิการให้พนักงานเป็น batch

flow นี้เป็นการทำงานแบบ asynchronous + manual — ไม่ใช่ real-time API call แต่เป็น "export file → bank processes → import file"


แผนภาพ flow ทั้งรอบ

1. HR เลือก WDHospital หลายรายการ (status = APPROVE, bank = KBANK)


2. createExportWDHospital(wdHospitalIds, ...)
   - สร้าง WDExport row
   - stamp wdExportId ในแต่ละ WDHospital


3. HR download zip ผ่าน fetchUrlExportWdHospital
   - ไฟล์: ${exportCode}_KBank_welfare.txt
   - ไฟล์: ${exportCode}_Smartcredit_welfare.txt
   - ไฟล์: ${exportCode}_FMIS.xlsx

            │  (HR upload ไฟล์ KBank_welfare.txt ที่ระบบ K-Cash ของธนาคาร)

4. ธนาคารกสิกรไทยประมวลผล (T+1 ถึง T+3 วันทำการ)


5. ธนาคารส่งไฟล์ผลกลับมา


6. HR upload ไฟล์ผลผ่าน importUpdateStatus(file)
   - VTRC parse ไฟล์
   - map K-Cash code → VTRC status
   - update WDHospital + WDHistory
   - ถ้าครบทุก row → WDExport.isImport = 1


7. ส่ง notification ให้พนักงาน (SUCCESS หรือ FAILED — จาก statusKcash)

WDExport — ติดตาม batch

vtrc-api/api/src/models/core/withdraw/export.js:1-78

Fieldหน้าที่
exportCodeรหัส batch (ใช้ในชื่อไฟล์ + ใน KBANK header)
yearsปีงบประมาณ
payDateวันที่กำหนดจ่าย
totalExportจำนวนรายการที่ส่ง
totalImportจำนวนรายการที่ประมวลผลแล้ว
totalCurrentWithdrawยอดเงินรวม
isImport0/1 — flip เป็น 1 เมื่อ totalExport == totalImport
isCancel0/1 — HR cancel batch นี้
cancelNote / cancelBy / cancelDateaudit ตอน cancel
wdHospitalIds (TEXT)list ของ id ตอนสร้าง batch
exportBy (UUID)userId ของ HR ที่สร้าง

K-Cash status map — หัวใจของ integration

vtrc-api/api/src/config.js:488-519statusKcash map

K-Cash codeENTHVTRC status
6ISSUED and/or STOPPAY WITH DUPLICATEการดำเนินการและ/หรือหยุดการจ่ายจากการทำซ้ำFAILED
7CANCELLEDยกเลิกรายการFAILED
8STOPPAYหยุดการจ่ายFAILED
9PAID (label เท่านั้น)โอนสำเร็จSUCCESS
10UNSUCCESS CREDITโอนไม่สำเร็จFAILED

สำคัญ — code 9 มี label: 'PAID' / labelTH: 'โอนสำเร็จ' แต่ฟิลด์ status ที่เขียนลง WDHospital คือ SUCCESS (config.js:508-511) — ไม่ใช่ document status PAID แยกจาก import

ถ้าเจอ code อื่นที่ไม่อยู่ใน map — VTRC จะไม่อัปเดต status (row นั้นค้าง) — เป็น edge case ที่ HR ต้องดูด้วยตัวเอง


Export zip — 3 ไฟล์ทำงานคนละอย่าง

vtrc-api/api/src/routes.js:776-811

ไฟล์Encodingหน้าที่ผู้รับ
${exportCode}_KBank_welfare.txtTIS-620K-Cash payroll input (หัวหลัก)KBANK K-Cash
${exportCode}_Smartcredit_welfare.txt(default)SmartCredit input (อีกระบบของ KBANK)KBANK SmartCredit
${exportCode}_FMIS.xlsxbinaryFMIS accounting reportฝ่ายบัญชีสภากาชาด

เงื่อนไข — KBank_welfare.txt สร้างเฉพาะเมื่อ length > 179 (routes.js:803) — ถ้า batch ว่างไฟล์นี้จะไม่อยู่ใน zip


การนำเข้าผล — Algorithm

lib/controllers/withdraw/hospital.js:2160-2316importUpdateStatus(file)

1. Parse ไฟล์ (แยกบรรทัด)
2. หา row header (header == 'h') → ระบุ exportCode
3. สำหรับ detail row แต่ละ row:
   a. อ่าน element.status (K-Cash code), element.effectivePayDate,
      element.totalCurrentWithdraw
   b. map status ผ่าน statusKcash → ได้ VTRC status (SUCCESS หรือ FAILED)
   c. validate ยอด: totalCurrentWithdraw ในไฟล์ต้องตรงกับ DB
      ถ้าไม่ตรง → reject ทั้ง batch, error "ข้อมูลยอดโอน...ไม่ตรงกับไฟล์นำจ่าย"
   d. update WDHospital:
      - importStatus = element.status (raw K-Cash code)
      - status = statusByKcash.status
      - importLabel = statusByKcash.labelTH
      - effectivePayDate = element.effectivePayDate
   e. write WDHistory row
   f. write WDHospital snapshot (isHistory = 1)
4. ถ้า wdExportData.totalExport == totalImport → WDExport.isImport = 1
5. return { status, exportCode, withdrawSuccess, withdrawFailed,
           transactionSuccess, transactionFailed }

ไม่มี cron — manual operator action

ข้อสำคัญ — ไม่มี cron ดึงผล K-Cash อัตโนมัติ

KBANK ไม่ expose API สำหรับดึงผล → HR ต้อง download ไฟล์ผลจากระบบ K-Cash ด้วยตนเอง แล้ว upload เข้า VTRC ผ่าน importUpdateStatus

ถ้า HR ลืม upload — WDHospital ทั้ง batch จะค้าง APPROVE ทั้งที่เงินเข้าบัญชีพนักงานแล้วจริง


Cancel batch — ก่อน import

cancelExportWDHospital (wdHospital.js:398)

HR สามารถ cancel batch export ทั้ง batch ถ้ายังไม่ import ผล

  • ทุก WDHospital ใน batch reset status กลับ APPROVE (hospital.js:2393)
  • WDExport.isCancel = 1
  • บันทึก cancelNote, cancelBy, cancelDate

หลัง import แล้ว — ไม่สามารถ cancel batch ได้ ต้องจัดการที่ละ row (เช่น mark CANCELDOC)


Channel คู่ขนาน — เงินสด

บางกรณี HR จ่ายเงินสดแทนผ่านธนาคาร — cashFlg = 1, bank = 'OTHER'

statusหมายถึง
CASHรอจ่ายสด
PAIDCASHจ่ายสดแล้ว

flow เงินสดไม่ผ่าน KBANK — HR mark ด้วยตนเองในหน้า backoffice (payCashBy, payCashDate, effectivePayDate)


ตัวอย่าง edge cases

สถานการณ์ผล
KBANK ส่ง code 9 (label PAID) แต่ยอดในบัญชีไม่ตรงVTRC mark SUCCESS เพราะ map ใน statusKcash — ถ้ามีปัญหาฝั่งธนาคาร VTRC ไม่รู้
KBANK ส่ง code 8 (STOPPAY)VTRC mark FAILED → HR ต้องตรวจสาเหตุแล้ว retry
HR upload ไฟล์ผลของ batch อื่นโดยผิดexportCode ใน header ไม่ตรง → import ปฏิเสธ
HR upload ซ้ำ batch เดิมWDHospital update ซ้ำด้วยข้อมูลเดิม — ไม่มี idempotency check
บัญชีพนักงานปิดไปแล้วKBANK return code 10 (UNSUCCESS) → VTRC mark FAILED → HR แจ้งพนักงาน

การตรวจสอบสถานะ batch

HR ใช้ query fetchListExportWDHospital เพื่อ list batch ทั้งหมด แล้วกรองตาม

  • isImport = 0 → batch ที่ยังไม่ปิด
  • isCancel = 0 → batch ที่ยัง active
  • วันที่สร้าง, วันที่กำหนดจ่าย

รายงานหลังจ่าย

PDF/Excel reports — lib/controllers/withdraw/hospital.template.js

QueryTemplate
fetchUrlFailPaymentPDFfailPaymentReportTemplate — list รายการ FAILED
fetchUrlWDHospitalPaidPDFReportsumWDHospitalPaidTemplate — สรุปจ่ายแล้ว
fetchUrlAllWithdrawPDFReportoverview + variants

รายงานเหล่านี้ HR ใช้ส่งให้ฝ่ายบัญชีและ audit — รายละเอียดใน บท 1.14


ข้อควรระวังตอน debug

อาการสาเหตุที่ตรวจ
"KBANK ไม่อัปเดต"HR ยังไม่ upload ไฟล์ผลถาม HR ก่อน
"ยอดไม่ตรง"batch มี row ที่ยอดในไฟล์ ≠ DBcheck totalCurrentWithdraw
"Status ค้าง"K-Cash code ไม่อยู่ใน mapดู statusKcash
"พนักงานไม่ได้รับ notification"FCM fail หรือ token หมดอายุcheck notification_fail table
"Duplicate import"ไม่มี idempotency — ระวังต้อง track เอง

ขั้นตอนถัดไป

ไป บท 1.12 การแจ้งเตือน ข่าว นโยบาย →