# 如何用JS建構POS系統 - 發票機跟刷卡機 - 高逸宸(Logan) {%hackmd @HWDC/BJOE4qInR %} >#### 》[議程介紹](https://hwdc.ithome.com.tw/2024/session-page/3125) >#### 》[填寫議程滿意度問卷|回饋建言給辛苦的講者](https://forms.gle/Zji1xkyDjvQWzbSZ6) --- ## Javascript POS 系統商支援線上電商 需求:原本有實體Pos 有多個通路 有線上跟線下 ## 如何解決線下通路問題 POS(Point of Sale) - 出單機 - 終端機 - 展示螢幕 - 收銀機 出單機? 大家都沒碰過XD 你機械系畢業你應該碰過吧 !? 原本是想用Browser 內建的 ctrl + p 遇到二聯三聯發票的瓶頸 # EPSON 出單機 USB 電源 RS232(早期的通訊埠):Pos 機設備經常使用的規格 --可能廠商不支援下列通訊方式-- LAN(新型):網路通訊 使用TCP IP ,適合長距離控制 藍芽(新型):移動 POS 設備可能會使用藍牙進行無線通信,適合需要靈活佈置的應用 # 通訊文本格式 - ECS/POS EPSON制定給POS的碼(ASCII) 連結:https://download4.epson.biz/sec_pubs/pos/reference_en/escpos/commands.html ## Web Serial / USB API 瀏覽器會跳視窗提醒,導致每次列印都會跳提醒。 > 解決策略 Node.js USB > https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API ![](https://i.imgur.com/l1j2ynY.png) ## Node.js USB - escpos - escpos-web https://www.npmjs.com/package/escpos https://github.com/node-escpos/driver 範例程式碼 ``` js const escpos = require("escpos"); escpos.USB = require("escpos-usb"); const device = new escpos.USB(0x04b8, 0x0e17); const options = { encoding: "BIG5" }; const printer = new escpos.Printer(device, options); device.open(function (error) { printer .font("a") .align("ct") .style("bu") .size(1, 1) .text("The quick brown fox jumps over the lazy dog") .text("敏捷的棕色狐狸跳過懶狗") .barcode("1234567", "EAN8") .table(["One", "Two", "Three"]) .tableCustom([ { text: "Left", align: "LEFT", width: 0.33, style: "B" }, { text: "Center", align: "CENTER", width: 0.33 }, { text: "Right", align: "RIGHT", width: 0.33 }, ], { encoding: "cp857", size: [1, 1] } // Optional ) .qrimage("https://github.com/song940/node-escpos", function (err) { this.cut(); this.close(); }); }); ``` - 客戶端防火牆的 port 打開 ## 部署流程 由於需求要以線下為主,因此必須將開發的內容包裝成能夠 Local 執行 方案 1. - JS POS Client click button - Local Serrver - pkg --output pos.exe - Printer 2. Electron.js ## 刷卡機 - 確認通訊方式 - 確認通訊文本格式(文件跟信用卡機要) - 機台還要跟信用卡中心要求開啟 POS 連線功能 乙太網路(需要跟銀行要求開啟) 電話孔(跟銀行通訊確認信用卡資訊的) 電源 Serial Port USB to RS232 當時只是看到伽利略的名字很厲害就買了 > https://www.npmjs.com/package/serialport 連接 -> 寫入 -> 監聽 ``` js // 寫入 const sendMessage = (message, callback) => { cardReader.write(message, (err) => { if (err) { console.log("Error on write: ", err.message); res.status(500).send("Failed to write message"); cardReader.close(); return; } console.log("Message sent: ", message); }); }; let completeData = ""; // 監聽 cardReader.on("data", (data) => { completeData += Buffer.from(data).toString("utf8"); console.log("Data received: ", completeData); if (completeData.length >= 400) { cardReader.close((err) => { if (err) { console.log("Error on close: ", err.message); } console.log("Card reader closed"); callback(completeData); }); } }); cardReader.on("error", (err) => { console.log("Error: ", err.message); res.status(500).send("Card reader error"); // cardReader.close(); }); cardReader.on("close", () => { console.log("Serial port closed"); }); ``` 要跟刷卡機的公司要資料格式 需要自己處理fileds製作欄位 信用卡中心要開啟POS連線功能,因為預設POS連線備鎖起來了 ## 如果你要JS串連硬體設備 - 問客服 他們一定有技術客服 - 確認通訊方式和文本格式 - 選擇適合的一條路 新型的有wi-fi 和藍牙 ## 優勢 - 跨平台支援 - 靈活性與擴充性 - 很多人做過惹,網路上很多文件教學函式庫等等可以用 - 低成本