Peter 工程日誌

如何在WSL 2上存取USB讀卡機並讀取健保卡內容

前言

近期,我需要使用讀卡機來讀取健保卡資訊,並將取得資訊作為身分驗證使用;但是手上僅有Windows 11筆電且日後標的作業系統為Linux類型的作業系統。因此,為了要達到此目的,需要使用WSL作為測試與開發環境;在本文中,將展示如何設定讀卡機供WSL 2使用,並插上健保卡後能夠讀取到健保卡資訊。

前置條件

需要達到前言所描述的目的,則需要完成與準備下列的項目:

讀卡機的選擇

因為需要在基於Linux發行的作業系統執行,因此讀卡機所使用的驅動就顯得重要,目前支援Linux的驅動晶片讀卡機型號如下:

CCID讀卡機是指符合 USB 晶片卡介面設備規範(Chip Card Interface Device)的硬體。

這類型的讀卡機採用免驅動通用標準,插入電腦或裝置後即可自動支援 PC/SC 協定,無須安裝驅動光碟即可直接讀取。

設定USB讀卡機

首先,以「系統管理員」身分開啟Windows終端機,後續關於操作USB讀卡機指令皆在此終端機執行,開啟後的示意圖如下所示:

接著,執行下列的指令並下載USB管理工具:


winget install --interactive --exact dorssel.usbipd-win

若尚未安裝此工具,則會跳出安裝視窗,並依照視窗呈現的訊息指示執行安裝即可。若已經安裝此工具,則會顯示下列的圖示。

完成USB管理工具的安裝後,插上讀卡機,並在系統管理員下的Windows終端機中,執行下列的指令來取得目前電腦上所有的USB清單:


usbipd list

執行前述的指令後,輸出的USB清單如下圖所示:

從上述的截圖,我們能夠得知「EZ100PU Smart Card Reader 」之Bus ID為2-4。接著,開啟WSL 2之「Ubuntu 22.04」後,執行下列的指令,「–busid」後的參數為前述截圖讀卡機裝置所對應的Bus ID:


usbipd bind --busid 2-4

如果是InfoThink訊想科技訊的IT-500U晶片讀卡機,則執行「usbipd list」指令會顯示「Microsoft Usbccid Smartcard Reader (WUDF)」
如下列的截圖所示:

執行完成後,可能會出現「usbipd: warning: USB filter ‘USBPcap’ is known to be incompatible with this software; ‘bind –force’ will be required.」之警告訊息,若要讓警告訊息不會輸出,則需要在前述的指令中,加入「–force」參數;但是,此警告訊息這不會影響後續的操作。

接下來,我們可以再執行「usbipd list」指令來驗證此讀卡機之狀態是否變成「Shared」。

確定USB讀卡機的狀態後,再執行下列指令將讀卡機交由WSL 2的作業系統作為管理(假設Bus ID是2-4)。


usbipd attach --wsl --busid 2-4

# 若要指定WSL的版本與名稱,則執行下列的指令,以指定Ubuntu 24.04為例:
usbipd attach --wsl "Ubuntu-24.04" --busid 2-4

需要注意的是,此指令執行完成後,將會發生下列的事項:

  1. Windows中,我們將無法使用與存取此USB讀卡機,原因是已經交由WSL 2上的作業系統操作與管理。
  2. 在「Ubuntu 22.04」中,執行「lsusb」指令來驗證USN讀卡機能夠使用與存取。
  3. 若「lsusb」指令不存在,則需要先執行「sudo apt update」與「sudo apt install -y usbutils」指令。

建置健保卡讀卡服務

接著,切換至「Ubuntu 22.04」,並依序執行下列的指令來安裝與設定讀取健保卡服務,此健保卡讀卡服務是使用了「magiclen/tw-nhi-icc」專案並加以容器化後的版本:


git clone https://github.com/peter279k/docker-tw-nhi-icc

cd docker-tw-nhi-icc/

docker compose build

完成後,再執行「docker compose up -d」即可將健保卡讀卡服務運行在此Ubuntu 22.04上了。

我們同時可以執行「docker compose ps」來檢查目前健保卡讀卡服務運行的狀態:

此服務同時具有讀卡資訊頁面可以透過Windows上的瀏覽器,瀏覽「http://localhost:12346/demo.html」之頁面,作並為簡易判斷健保卡所讀取到的資訊;若沒有讀取到訊息則會呈現下列的截圖:

當使用自己的健保卡讀取到資訊,則會呈現如下截圖:

健保卡讀取服務能夠將讀取到的資訊以JSON陣列的方式呈現,讀取到的訊息與欄位如下:

除了能夠透過既有健保讀卡服務的簡易頁面取得健保卡資訊外,也能夠使用API的方式來呼叫並取的健保卡資訊,健保卡讀卡的後端服務預設是監聽在「12345」,因此我們能夠使用下列的cURL與jq指令取得健保卡資訊:


curl -q http://localhost:12345/ | jq

從API所取得到的健保卡資訊,其欄位名稱有些許不同:

  1. reader_name,讀卡機型號名稱。
  2. card_no,健保卡卡號。
  3. full_name,健保卡持有者姓名。
  4. id_no,身分證字號。
  5. birth_date,持卡人之生日。
  6. birth_date_timetstamp,持卡人生日之時間戳記。
  7. sex,持卡人性別;若顯示「M」則為男性(male),女性則為「F」(female)。
  8. issue_date,此健保卡發卡日期。
  9. issue_date_timestamp,此健保卡發卡日期之時間戳記。

當完成讀卡後,即可將健保卡取出,並換下一張健保卡讀取。

故障排除

以下是有可能發生問題的原因:

參考資料

Exit mobile version