EPW / TKW / TEA 架構

本專案 Django-Taiwan-EInvoice (DTEI) 是由 3 部份: EPW / TKW / TEA 所組成。

TEA 是一個 Django-based 的 Python app ,可直接以 Web Api Service 方式執行,或是導入至其他 Django-based 的專案中。 TEA 支援 WebSocket 協定,當 EPW 系統開機後, EPW 會連線至 TEA WebSocket Api 或 CEC WebSocket Api(以導入 TEA)。

當 TEA 有列印電子發票證明聯的需求,可送出其發票資料(JSON),發票 JSON 透過 WebSocket Channel 傳至 EPW , EPW 再將發票 JSON 轉譯為 ESC/POS 指令,再送至系統 OS 所控管的 Thermal ESC/POS Printer ,由 Printer 印出發票證明聯。

當 TEA 要上傳發票至 EI 大平台時,會使用 HTTP POST 傳送批次編號資料至 TKW 的 Api Endpoint ,成功後,再以 HTTP POST 傳送批次編號相關所有發票的 JSON ,該批次編號發票傳送完畢後, TKW 會將發票 JSON 轉成 MIG 標準的 xml ,存入本地端的 Turnkey 系統所控資料夾,再由 Turnkey 系統(Java Application)處理與 EI 大平台的發票上傳作業。

TEA 資料設定

  1. 創建「統編(legalentity)」紀錄

  2. 創建「賣家(seller)」紀錄

  3. 創建「Turnkey 服務(turnkeyservice)」紀錄:
    • name

    • note

    • seller

    • transport_id: EI 提供

    • party_id: EI 提供

    • routing_id: EI 提供

    • hash_key: 可自動隨機產生

    • qrcode_seed: 須透過 Turnkey 程式>工具>守門員>QRCode驗證 來產生

    • turnkey_seed: 須透過 Turnkey 程式>工具>守門員>QRCode驗證 來產生

    • download_seed: 須透過 Turnkey 程式>工具>守門員>QRCode驗證 來產生

    • epl_base_set: 預設值是 GHIJKLMNOPQRSTUVWXYZ ,用來驗證「電子發票證明聯列印序號」用的字元集合,建議使用「大寫英文、符號」並打亂順序

    • auto_upload_c0401_einvoice: True/False ; if True, then it upload B2C certificate invoices at upload_cronjob_format time

    • upload_cronjob_format: 5, 10, 15, 20, 30, 60; 5 => 「*/5 * * * *」(cron format)

  4. 創建「發票機(escposweb)」紀錄:
    • name: 建議包含發票機外形、地點、特徵

    • slug: 可自動隨機產生

    • hash_key: 可自動隨機產生

EPW 資料設定

備註

安裝 EPW 的步驟,請見: 在 Pi 或其他 Linux Distro 安裝設定 EPW 伺服器

  1. 套用 TEA 的 escposweb 紀錄來新增 EPW 中的 TEAWeb 紀錄,需要資料有:
    • escpos_web uri ,如: wss://<CEC or TEA url>/ws/taiwan_einvoice/escpos_web/<turnkeyservice id>/

    • slug ,如: BB737

    • hash_key ,如: 5817f0172c9482605d16386a263a7296de8b22f8

  2. 更新 EPW 中的 Printer 紀錄,當 USB printer 開機並連線到 EPW 後,系統就會自動抓取 serial_number, type, vendor_number, product_name, profile ,後 3 者是在 python-escpos 函式庫有支援下,才能正確讀取。需要手動更新的,只有 3 個欄位:
    • nickname: 建議在列表機外殼,標記代號,並將此代號紀錄至本欄位

    • receipt_type: 選項有 0, 5, 6, 8 。意義分別是 0 表不能使用、 5 表 58mm 收據、 6 表 58mm 電子發票、 8 表 80mm 收據

    • default_encoding: 選項有 B, G 。為印表機內置的編碼表設定,其中 B 表 CP950 、 G 表 GB18030 編碼表

  3. 若 TEAWeb 紀錄設定超過 1 個,那建議額外 設定 EPW Portal(非必要)

TKW 資料設定

備註

TKW 安裝部份,請見: 在 Linux 安裝 Turnkey 及 TKW 伺服器

  1. 將 TKW 中的 EITurnkey Api Endpoint 登記到 CEC 中,類似 SNS subscribe 模式,先瀏覽 https://<tkw url>/turnkey_wrapper/api/v1/eiturnkey/ ,再使用 HTTP POST 新增 EITurnkey 紀錄,輸入欄位有:
    • execute_abspath: 以 / 開頭的本地端路徑來指出 EINVTurnkey 程式的 einvTurnkey.sct 的資料夾所在

    • data_abspath: 放置 Data 的資料夾所在

    • transport_id: 對應 turnkeyservice 紀錄

    • party_id: 對應 turnkeyservice 紀錄

    • routing_id: 對應 turnkeyservice 紀錄

    • hash_key: 對應 turnkeyservice 紀錄

    • tea_turnkey_service_endpoint ,如: https://<CEC or TEA url>/taiwan_einvoice/api/v1/turnkeyservice/<turnkeyservice id>/

    • endpoint: 無需填寫, POST 後由 TKW 自動計算

    • allow_ips: 若要使用 TKW Portal 功能,才需填寫

TEA supports ASGI with daphne, supervisor and nginx

$ sudo apt install nginx supervisor
$ sudo mkdir /run/daphne/
$ sudo chown jenkins:jenkins /run/daphne/ # I use jenkins user to execute app
$ cat << 'EOF' > /usr/lib/tmpfiles.d/daphne.conf
d /run/daphne 0755 jenkins jenkins
EOF
#/etc/supervisor/conf.d/my-site.com.conf
[fcgi-program:my_site]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8001

# Directory where your site's project files are located
directory=/var/www/my-site.com

# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=/var/www/my-site.com-py3-env/bin/daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers my_site.asgi:application

# Number of processes to startup, roughly the number of CPUs you have
numprocs=4

# Give each process a unique name so they can be told apart
process_name=asgi%(process_num)d

# Automatically start and recover processes
autostart=true
autorestart=true

# Choose where you want your log to go
stdout_logfile=/var/www/my-site.com.asgi.log
redirect_stderr=true
$ sudo supervisorctl reread
$ sudo supervisorctl update
#/etc/nginx/site-enabled/my-site.conf
server {
    server_name     www.my-site.com;
    access_log      /var/log/nginx/my-site.log;
    error_log       /var/log/nginx/my-site_error.log;

    listen          443 ssl;       # Listen on port 80 for IPv4 requests

    include         /native-nginx/conf.d/ssl.conf;
    ssl_certificate /native-nginx/certs/my-site.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /native-nginx/certs/my-site.com/privkey.pem; # managed by Certbot

    add_header      Content-Security-Policy "frame-ancestors 'self' hwww.my-site.com hwww.bio-pipe.com";

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 631;
        proxy_send_timeout 631;
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $remote_addr;
        proxy_set_header    REMOTE_ADDR $remote_addr;
        proxy_set_header    HTTP_HOST $host;
    }
}
$ sudo nginx -t
$ sudo systemctl restart nginx