2.4 · การเชื่อมต่อกับระบบภายนอก
บทนี้แมประบบภายนอกทั้งหมดที่ VTRC พูดด้วย — แต่ละตัวเชื่อมอย่างไร ผ่านบริการไหน auth อะไร
ถ้าระบบใดระบบหนึ่งล่ม — บทนี้บอกว่า VTRC จะเจอ error แบบไหน และต้องแก้ที่ไหน
ภาพรวม — ระบบภายนอก 7 ตัว
vtrc-api
│
┌──────────┬──────────┬───────┼────────┬──────────┬──────────┐
│ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼
HRMI/MSSQL LDAP/AD KBANK SMS Conicle GCP SMTP
(HR data) (identity) (K-Cash) (OTP) (training) (Drive+FCM) (email)
│ │
│ │ bind
│ ▼
│ cu-central-api ─── SFTP (file transfer)
│ ▲
│ │ GraphQL (END_POINT_CENTRALIZE)
│ │
└───────────┘
│
│ (NestJS centralize-api ก็อ่าน HRMI ได้เช่นกัน
│ แต่ caller จาก vtrc-api ยังไม่ยืนยัน — ดูบท 5.9)
▼
NestJS centralize-api (port 3000 REST)สำคัญ — path ที่ vtrc-api ใช้จริงเมื่อต้องการ HR data คือ
END_POINT_CENTRALIZE→ cu-central-api GraphQL (CLIENT_TARGET ตัวอย่างอาจใช้พอร์ต 8082; CODE_DEFAULT ของ cu-central คือAPP_PORT=8080) ไม่ใช่ NestJScentralize-api
1. HRMI / MSSQL — source of truth ทาง HR
HRMI = HR Management Information ของสภากาชาด เป็น source of truth ของข้อมูลพนักงานทุกอย่าง (profile, ตำแหน่ง, เงินเดือน, สาขา, ผู้บังคับบัญชา)
เชื่อมผ่าน 2 ทาง (ทั้งคู่ไป MSSQL HRMI แต่ caller ไม่เหมือนกัน)
| ทาง | บริการที่เชื่อม | Database | Connection | Caller จาก vtrc-api |
|---|---|---|---|---|
| Production path | cu-central-api | DB_HR_NAME, DB_MASTER_DATA_NAME, DB_HRMI_CENTER_HIS | cu-central-api/main-api/src/connector.js:8-170 (Sequelize × 6) | ใช่ — ผ่าน END_POINT_CENTRALIZE |
| NestJS facade | centralize-api | dbHRMI_Center + dbHRMI_Center_NBC | centralize-api/src/app.module.ts:23-60 (TypeORM mssql × 2) | ยังไม่ยืนยัน — ดู บท 5.9 |
รายละเอียด connection
cu-central-apiเปิด pool 6 ตัว (db,dbHr,dbHrTemp,dbMasDb,dbHRMI_test,dbHRMI_Center_HIS) —cu-central-api/main-api/src/connector.js:8-170- ทุก pool ตั้ง
max: 100(ยกเว้นdbHrTempที่ 50) ดังนั้น cu-central-api เปิด connection ได้สูงสุด ~550 จาก process เดียว - NestJS
centralize-apiเปิด connection pool 2 ตัว (center + nbc) ไปที่ host เดียวกัน แต่ database ต่างกัน —centralize-api/src/app.module.ts:25,44
ระวัง — ถ้า MSSQL ล่ม → VTRC ไม่สามารถ
- ยืนยันตัวตนพนักงานใหม่ (verifyEmpCodeLogin)
- ดึงรายชื่อผู้อนุมัติการลา (chain อยู่ใน HRMI)
- แสดงสลิปเงินเดือน, ภาษี, เวลาทำงาน
login ที่เคย login แล้วยังใช้ได้ (JWT ยังไม่หมดอายุ) แต่ action ใหม่ที่ต้อง query HRMI จะ fail
2. LDAP / Active Directory — identity ของจุฬา
LDAP ใช้สำหรับ verify password ของพนักงานที่ affiliated กับจุฬาลงกรณ์มหาวิทยาลัย (โรงพยาบาลจุฬาฯ)
เชื่อมผ่าน cu-central-api → ldapjs — cu-central-api/main-api/src/lib/auth/activeDirectory.connector.js:26-36
flow การ auth
1. cu-central-api bind service account (AD_USERNAME + AD_PASSWORD)
2. cu-central-api bind ด้วย DN + password ของ user
3. ถ้าผ่าน → mint JWT (ใน cu-central-api)
4. ส่ง JWT กลับ vtrc-api ผ่าน centralize bridgeระวัง
- TLS verification ปิดอยู่ (
rejectUnauthorized: falseที่activeDirectory.connector.js:21) — LDAP ไม่ได้ตรวจ cert - AD username ที่ใช้ bind มาจาก CRC64 ของ identityCard (
auth.controller.js:226-230) — CRC64 ไม่ใช่ cryptographic hash เลย collision ได้ - ถ้า
AD_IS_ENABLED=0(default ในconfig.js:50) →bindAdWithUserAndPasswordreturn null ทันที → ใครก็ login ผ่าน AD ไม่ได้
3. KBANK K-Cash — ระบบจ่ายเงินสวัสดิการ
KBANK รับไฟล์ batch (KBank_welfare.txt) ประมวลผล T+1 ถึง T+3 วันทำการ แล้วส่งไฟล์ผลกลับมา
เชื่อมผ่าน ไม่มี API — เป็น manual file exchange
1. HR เลือกรายการใน backoffice → vtrc-api generate ไฟล์ .txt + .xlsx
2. HR download zip จากระบบ (ผ่าน fetchUrlExportWdHospital)
3. HR เอาไฟล์ไป upload ที่หน้าเว็บ K-Cash ของธนาคาร ด้วยมือ
4. KBANK ประมวลผล (T+1 ถึง T+3 วันทำการ)
5. HR download ไฟล์ผลจาก K-Cash
6. HR upload ไฟล์ผลเข้า vtrc-api → importUpdateStatus(file)
7. vtrc-api parse ไฟล์ + map status → update WDHospital + ส่ง notification ให้พนักงานจุดที่เชื่อมในโค้ด
- Export —
vtrc-api/api/src/routes.js:772-901(REST/wdHospital/export) - Import —
vtrc-api/api/src/routes.js(ค้นหาimportUpdateStatus) - Status mapping —
vtrc-api/api/src/config.js:488-519(statusKcash— code 6/7/8/9/10)
ระวัง — ไม่มี cron อัตโนมัติ ถ้า HR ลืม upload ไฟล์ผล → สถานะพนักงานจะค้างที่ "exported" ตลอดไป
4. SMS — OTP และ notification
SMS gateway อยู่ที่ SMS_GATEWAY_URL + SMS_GATEWAY_KEY (cu-central-api/main-api/src/lib/sms.js:29-61)
เชื่อมผ่าน cu-central-api ส่ง HTTP POST ไปยัง gateway
เคสที่ใช้ SMS
- OTP ตอน register / reset password (
cu-central-api/main-api/src/lib/otp/sendOtp.js:74-106) - OTP TTL 15 นาที (
SMS_OTP_EXPIRE_MINUTESdefault 3 นาที จากconfig.js:74) - ส่งได้ใหม่ทุก 30 วินาที (
SMS_RESENT_SECONDS)
ระวัง
- ถ้า env
SMS_SANDBOX_PHONE_NUMBERตั้งไว้ → ทุก SMS จะถูกส่งไปเบอร์นั้นแทน (sms.js:14-16) — เอาไว้ทดสอบ staging แต่ถ้าลืมปิดใน prod พนักงานจะไม่ได้รับ OTP จริง - vtrc-api เองก็มี stub
/ais-smsgw(vtrc-api/api/src/routes.js:990-993) แต่แค่ echo OK ไม่ได้ทำอะไรจริง
5. Conicle — ระบบ training ภายนอก
Conicle เป็น LMS (Learning Management System) ภายนอก ที่ต้อง sync รายชื่อพนักงานไปทุกวัน
เชื่อมผ่าน SFTP — cu-central-api/main-api/src/lib/transferFile/transferFile.class.js:1-60
flow
1. cron 03:40 ทุกวัน → transferFileToConicle('long')
(cu-central-api/main-api/src/cron.js:21-23)
2. query รายชื่อพนักงานทั้งหมดจาก HRMI (limit 999,999)
3. generate ไฟล์ .xlsx (พนักงาน + org unit)
4. SFTP upload ไปที่ Conicle server
5. log ผลใน Models.ConicleFileLogระวัง
/api/conicle/longtermendpoint (cu-central-api/main-api/src/routes.js:11-19) ไม่มี auth — ใครก็ยิง POST แล้ว trigger SFTP push ได้- ไฟล์ที่ push มี identityCard + birthDate ของพนักงานทั้งหมด — ถ้า SFTP creds รั่ว เท่ากับ PII leak
6. GCP — file storage + push notification
GCP ให้บริการ 2 อย่าง
- Google Drive — เก็บไฟล์แนบ (เอกสารลา, ใบเสร็จ)
- Firebase Cloud Messaging (FCM) — push notification ไปมือถือ
เชื่อมผ่าน vtrc-api → googleapis / firebase-admin
ไฟล์เชื่อมต่อ
vtrc-api/vtrc-gcp-sa-key.json— service account key (committed to repo — ห้าม log ห้าม exfiltrate)vtrc-api/api/src/lib/firebase/— module สำหรับส่ง FCM
ระวัง — service account key committed อยู่ใน git ถ้าทำ security audit ต้อง rotate key + ย้ายเก็บที่ secret manager
7. SMTP — ส่ง email
ใช้ nodemailer — เชื่อมจากทั้ง vtrc-api และ cu-central-api
เคสที่ใช้ email
- แจ้งเตือน HR เมื่อมี action สำคัญ
- ส่งใบเสร็จ / เอกสารทางการเงิน
ไฟล์
cu-central-api/main-api/src/lib/mailer/email.js:1-107- ใช้
email-templateslibrary — templates อยู่ในcu-central-api/main-api/email-templates/
ระวัง
- ถ้า env
EMAIL_TLS_REJECT_UNAUTHORIZED=falseตั้งไว้ → TLS verification จะปิด EMAIL_BCC_RECEIVE_BACKUPถ้าตั้ง → ทุก email จะ BCC ไปที่เบอร์นี้ด้วย
ตารารางสรุป contract
| ระบบ | Protocol | Auth | Service | Endpoint |
|---|---|---|---|---|
| HRMI MSSQL | TCP 1433 (SQL) | DB credentials | centralize-api, cu-central-api | centralize-api/.env:7-10 |
| LDAP/AD | TCP 389/636 (LDAP) | service bind + user bind | cu-central-api | cu-central-api/main-api/src/lib/auth/activeDirectory.connector.js:26-36 |
| KBANK K-Cash | File exchange (manual) | — | vtrc-api (generate + parse) | vtrc-api/api/src/routes.js:772-901 |
| SMS | HTTPS POST | apiKey body | cu-central-api | cu-central-api/main-api/src/lib/sms.js:29-61 |
| Conicle | SFTP | username/password | cu-central-api | cu-central-api/main-api/src/lib/transferFile/transferFile.class.js:5-19 |
| GCP Drive | HTTPS | service account JSON | vtrc-api | vtrc-api/api/src/lib/firebase/ |
| GCP FCM | HTTPS | service account JSON | vtrc-api | (เดียวกับ Drive) |
| SMTP | SMTPS / SMTP | user/pass | cu-central-api, vtrc-api | cu-central-api/main-api/src/lib/mailer/email.js:1-107 |
| SSO จุฬา | HTTPS + basic auth | SSO_USERNAME / SSO_PASSWORD | cu-central-api | cu-central-api/main-api/src/lib/sso/sso.js:103-126 |
เคล็ดลับตอนทำงานจริง
ลำดับการล่มที่เจอบ่อย
จากประสบการณ์ — ลำดับความถี่ที่ระบบภายนอกล่ม
- LDAP/AD — เพราะ TLS verification ปิดอยู่ และมักมีปัญหาเรื่อง cert หมดอายุ
- SMS gateway — เคยมีเรื่อง quota เต็ม หรือ gateway ไม่ตอบ
- MSSQL — connection pool เต็ม (เพราะมีหลาย pool เปิดพร้อมกัน)
- KBANK — ไม่ใช่ "ล่ม" แต่ "ช้า" (T+1 ถึง T+3)
- GCP / SMTP — แทบไม่เคยล่ม
ตอน debug "OTP ไม่ถึง"
อย่าเริ่มที่โค้ด ให้เริ่มที่
- เบอร์โทรใน HRMI ถูกไหม — VTRC อ่านจาก HRMI ไม่ใช่จากตัวเอง
SMS_SANDBOX_PHONE_NUMBERตั้งไว้ไหม — ถ้าตั้ง OTP จะถูกเบี่ยงไปเบอร์นั้น- OTP หมดอายุไปแล้วไหม (default 3 นาที) — ถ้า user รอนานเกินไป OTP จะ invalid
อย่าทำ assumed trusted ระหว่าง internal services
แม้ vtrc-api → cu-central-api จะอยู่ใน internal network แต่ auth ยังใช้ API_CENTRALIZE_KEY ที่ static — ถ้าเครื่องหนึ่งโดน compromise มันสามารถเรียกอีกเครื่องได้ทันที
ถ้าทำ modernization — ควรเปลี่ยนเป็น mTLS หรือ short-lived token แทน