top of page
ค้นหา
รูปภาพนักเขียนSathit Jittanupat

Connect VAT Service with Node.js



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


จนถึงวันที่เขียนบันทึกนี้ VAT Service น่าจะให้บริการกว่า 12 ปีแล้ว อ้างอิงจาก source code ของ page VATINFO พบว่าเขียนโดยคุณสดใส (Sodsai.L) ตั้งแต่ปี 2011 นับว่าผ่านร้อนผ่านหนาว ใช้ตรวจสอบข้อมูลผู้ประกอบการที่จดทะเบียน VAT มาอย่างยาวนาน



บังเอิญว่าช่วงสองเดือนที่ผ่านมา (มิ.ย. - ก.ค. 2566) ผมมีปัญหากวนใจเกี่ยวข้องกับบริการ VAT Service ของกรมสรรพากร จะเล่าให้ฟัง


ครั้งแรกเป็นปัญหาความไม่เสถียรของเซิร์ฟเวอร์ที่เกิด error จนใช้งานไม่ได้ตลอดวัน


ครั้งที่สองเป็นปัญหาข้อมูลที่ตอบกลับมาเปลี่ยน (breaking change) ทำให้รับข้อมูลมาแล้วเกิด error ตีความไม่ได้


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


ทีแรกพบว่าเซิร์ฟเวอร์ของเราที่ทำหน้าที่เป็นตัวกลางติดต่อกับเซิร์ฟเวอร์ของสรรพากร มี load เพิ่มขึ้นไปถึง 90% ทำให้ไม่ตอบสนอง เมื่อ restart แล้วกลับมาใช้ได้ แต่อีกประมาณ 10 นาทีก็กลับมา 90% อีก ดูเหมือนว่าจะมี process อะไรสักอย่างในที่ทำงานผิดปกติ


หลังจากที่ไล่หาสาเหตุ จนกระทั่งเจอสมมติฐานที่น่าเป็นไปได้ พบว่าไม่ได้เป็นเฉพาะของเรา โปรแกรม ERP ของผู้ให้บริการอื่นที่ติดต่อกับ VAT Service ก็มีปัญหาเหมือนกัน ดูเหมือนว่าเกิดจากเซิร์ฟเวอร์สรรพากรใช้งานไม่ได้ แต่คำถามต่อมาของเราคือ แล้วทำไมจึงลากให้เซิร์ฟเวอร์ของเราพังทุก 10 นาทีด้วย


ปัญหาส่วนหนึ่งเกิดจากโค้ด ที่ไม่ทันคิดถึงกรณีนี้ เดิมเราออกแบบเผื่อไว้สำหรับกรณีเซิร์ฟเวอร์ของสรรพากรทำงานไม่ทัน ไม่ตอบสนองชั่วคราว จึงเพิ่มส่วน retry หากส่งคำขอครั้งแรกไปแล้วไม่สำเร็จ พยายามส่งซ้ำไปใหม่โดยเว้นระยะ แต่หากเซิร์ฟเวอร์สรรพากรไม่ตอบสนองเลย คำขอที่รอคำตอบเหล่านั้นก็จะเป็น process ค้างสะสมเพิ่มขึ้นเรื่อย ๆ จนหน่วยความจำของเซิร์ฟเวอร์ไม่เหลือให้ใช้อีก



เพื่อพิสูจน์ต้นตอปัญหา ผมจึงเขียนโค้ดสั้น ๆ ทดสอบเรียกข้อมูลจากเชิร์ฟเวอร์ของสรรพากร ทีแรกกะว่าให้ AI ช่วยเขียน ปรากฏว่าตัวอย่างโค้ดออกมาดูดีแต่ใช้ไม่ได้ แบบว่าออกทะเลไปไกลมาก (เศร้า) จนต้องพึ่งตัวเอง


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


ต่อไปนี้ เป็นตัวอย่างโค้ด Node.js ที่สามารถติดต่อกับเซิร์ฟเวอร์สรรพากรเพื่อขอข้อมูล VAT Info ได้จริง ๆ


เริ่มจาก สร้างโฟลเดอร์ใหม่ แล้วติดตั้ง package soap


npm install soap

เลือกใช้ end point ที่ตอบกลับมาเป็น JSON ตามนี้



ตามสเปคประกอบด้วย method "Service" และ "ServiceArr"


หลังจากที่ทดสอบแล้วพบว่า ServiceArr นั้นใช้ไม่ได้ ไม่ว่าจะส่งค่า TINs อะไรไปถาม ก็ตอบกลับเป็น null ดังนั้นจึงเหลือแต่ "Service" ที่ใช้ได้ สามารถเลือกถามด้วย เลขผู้เสียภาษี หรือ ชื่อก็ได้ และอาจระบุเลขสาขาที่ต้องการได้ด้วย


  • TIN เลขผู้เสียภาษี ต้องเป็นเลข 13 หลัก

  • Name ชื่อผู้ประกอบการ เป็นการค้นหาชื่อบางส่วน

  • BranchNumber เลขสาขา


ตัวอย่าง โค้ดด้านล่างนี้ ทดสอบอ่านค่าจากเลขผู้เสียภาษี เปลี่ยน "<ANY-TAXID>" เป็นเลขผู้เสียภาษีที่ต้องการทดสอบ โดยโปรแกรมจะแสดงผลลัพธ์ที่ได้มาทาง console พร้อมทั้งจับเวลาว่าการติดต่อกับเซิร์ฟเวอร์ใช้เวลาเท่าไหร่



const soap = require("soap");

// reference - https://www.rd.go.th/42535.html
const url = "https://rdws.rd.go.th/jsonRD/vatserviceRD3.asmx?wsdl"
const wsdl_options = {timeout: 1 * 60 * 1000}

const method = "Service"

const args = {
  username: "anonymous",
  password: "anonymous",
  TIN: "<ANY-TAXID>",  // <== replace with valid taxid 
};

const ts = Date.now()
soap.createClient(url, {wsdl_options}, (err, client) => {

  if (err) {
    console.error(err);

  } else {

    client[method](args, function(err, result) {
      console.log(method)

      if (err) {
        console.error(err);

      } else {
        const r = result[method + 'Result']
        console.log(r.$value || JSON.stringify(r));
      }

      console.log(`\n-- consume ${(Date.now() - ts)/1000} secs.\n`)
    });
  }
});

บทเรียนจากกรณีนี้ ทำให้ได้ปรับปรุงเซิร์ฟเวอร์ฝั่งเรา ทำอย่างไรจึงรับมือได้ดีกว่าเดิม ประมาณว่าถ้าฝั่งสรรพากรพังยาว ๆ อีก ก็ต้องไม่กระทบทำให้เซิร์ฟเวอร์เราพังตามไปด้วย ใช้วิธีตั้งค่า timeout ถ้าฝั่งโน้นไม่ตอบกลับมาภายในเวลาที่กำหนดเช่น 10 วินาที ก็ตัดการติดต่อให้กลายเป็น error เพื่อรีบตัดจบ แล้วเว้นระยะเพื่อ retry ใหม่อีกครั้ง แทนที่จะรอไปเรื่อย ๆ จนทำงานไม่ได้



ผ่านพ้นปัญหาแรกไปได้ไม่นาน ไม่กี่วันต่อมาก็มีข้อสังเกตจากผู้ใช้โปรแกรมว่าใส่เลขผู้เสียภาษีแล้วข้อมูลไม่มาอีกแล้ว คราวนี้เซิร์ฟเวอร์ของเราไม่พัง แค่ตอบข้อมูลมาให้ไม่ได้ แสดงข้อความขึ้นมาว่า "ข้อมูล BusinessFirstDate ไม่อยู่ในรูปแบบวันที่ที่ถูกต้อง"


เมื่อตรวจสอบแล้วพบว่าฝั่งสรรพากรตอบข้อมูลฟิลด์ดังกล่าวมาเป็น "-" (ขีดเดียว) แทนที่จะเป็นค่าวันที่เหมือนก่อนหน้านั้น แก้ปัญหาด้วยการปรับโค้ด เมื่อรู้ว่าทางโน้นอาจส่ง "-" มาแทนค่าวันที่ จึงแก้ไขให้ยอมรับข้อมูลนั้นไม่ถือว่าเป็น error เพื่อให้ทำงานต่อได้


หลังจากนั้นผมก็เลยสุ่ม ลองสุ่มถามข้อมูลเลขผู้เสียภาษี ปรากฏว่าทั้งหมดตอบว่าเป็น "-" เพราะฉะนั้นน่าจะเป็นที่เจตนาไม่ตอบวันที่จดทะเบียนผ่าน VAT Service อีกแล้ว แต่ถ้าเอาเลขผู้เสียภาษีเดียวกันไปถามข้อมูลใน page VAT Info ยังคงแสดงวันที่จดทะเบียนได้



สรุปแนวทางการใช้งาน VAT Service จากสรรพากร ซึ่งเป็นการใช้บริการที่ไม่มี SLA (Service Level Agreement) ควรเผื่อกรณีเซิร์ฟเวอร์ทางฝั่งสรรพากรไม่สามารถให้บริการ ทั้งกรณีที่เกิดจากมีผู้อื่นเรียกใช้งานมากเกินไปจนให้บริการไม่ทันชั่วคราว หรือกรณีแย่กว่านั้นใช้งานไม่ได้เป็นเวลานานหลายชั่วโมงหรือหลายวัน ทำอย่างไรไม่กระทบต่อโปรแกรมของเรา ผมมีแนวทางดังนี้


หนึ่ง ควรมีเซิร์ฟเวอร์ของตัวเองคั่นกลาง และทำหน้าที่เป็น cache เพื่อช่วยลดความถี่ในการติดต่อกับ VAT Service ไม่ให้เป็นภาระมากเกินไป


สอง เก็บวันเวลาล่าสุดที่อ่านมาได้สำเร็จไว้กับข้อมูลใน cache ด้วย เป็น valid time เอาไว้ตรวจสอบว่า ข้อมูลนี้เจอครั้งสุดท้ายเมื่อไหร่


สาม เพิ่มกลไก refresh อ่านข้อมูลจาก VAT Service มาใหม่เพื่อ update กรณี valid time นานเกินไปแล้ว ระยะเวลาที่เหมาะสมอยู่ที่ประมาณ 1 เดือน เท่ากับรอบยื่นภาษีมูลค่าเพิ่ม เหตุผลที่ต้อง refresh เนื่องจากมีกรณี ผู้ประกอบการแจ้งถอนการจดทะเบียน (เลิกกิจการ) เปลี่ยนชื่อกิจการ เปลี่ยนที่อยู่ ทำให้ข้อมูลที่อยู่ใน cache อาจล้าสมัย


ที่อยากจะฝากทิ้งท้ายไว้ มีปัญหาที่ผมยังคิดไม่ตกว่าควรทำอย่างไร คือ กรณีเลิกกิจการ หรือ เลิกบางสาขา ทำให้เมื่อ refresh กับ VAT Service จะได้คำตอบว่า ไม่พบข้อมูลผู้ประกอบการนี้ ซึ่งตีความว่าไม่ใช่ผู้ประกอบการจดทะเบียนภาษีมูลค่าเพิ่ม บังเอิญเคยเจอเคสที่ว่า กิจการเพิ่งปิดสาขาไปไม่กี่เดือน ขณะเดียวกันผู้ใช้โปรแกรมก็มีใบกำกับภาษีซื้อของเดือนเก่าที่จะยื่นขอคืนภาษี เมื่อตรวจใบกำกับภาษีปลอม โดยเช็คกับสถานะล่าสุดของผู้ประกอบการรายนั้นกลายเป็นผลตรวจผิดพลาด รวมทั้งเราอาจไม่สามารถตรวจสอบใบกำกับภาษีซื้อปลอม สำหรับรายงานภาษีซื้อที่ย้อนหลังนานมาแล้วด้วย ยังไม่มีวิธีขอข้อมูลของผู้ประกอบการเมื่อ 6 เดือนที่แล้ว


อ้างอิง

ดู 3 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

Comments


Post: Blog2_Post
bottom of page