---
name: ezpay-einvoice
description: >-
  在程式裡串接、開發或除錯台灣 ezPay（簡單行動支付，藍新 NewebPay 家族）電子發票 API 時使用本 skill ——
  任何語言或框架皆適用（Laravel/PHP、Python、Node、Go…）。典型任務：開立 B2C/B2B 發票、觸發開立、作廢發票、
  開立或作廢折讓（allowance）、查詢發票、手機條碼與捐贈碼載具驗證、字軌管理；釐清某支 API
  （invoice_issue／allowance_issue／invoice_invalid／checkBarCode／createNumber）要帶哪些欄位、
  B2C 含稅 vs B2B 未稅金額怎麼算；處理底層 PostData_ 的 AES 加密、CheckValue／CheckCode 簽章、
  商店與會員的 Hash Key／Hash IV 雙金鑰；除錯 KEY10002 解密錯誤等回應錯誤碼；或只是想寫支腳本確認手上的
  ezPay 金鑰與測試環境打不打得通。只要情境圍繞 ezPay／簡單行動支付開立的發票、且要動手寫或修程式，
  即使沒講「skill」也要觸發。這是動手實作的領域 skill，不是 POS 架構／設計討論。不適用於綠界 ECPay、
  藍新 NewebPay 金流（MPG）、Stripe，或與 ezPay 無關的通用 AES 加解密／發票彙總報表。
---

# ezPay 電子發票串接

協助在任何專案／語言實作 ezPay（簡單行動支付）電子發票串接，並提供可實機驗證的工具。
這份 skill 把「手冊不會明講、或前後矛盾、踩過才知道」的知識濃縮下來，讓你不必重新考古。

## 整合模型速覽

- **傳輸**：HTTP 標準 Form POST，UTF-8，平台以 Web Service 回應。
- **環境**：測試 `https://cinv.ezpay.com.tw`、正式 `https://inv.ezpay.com.tw`（同一套 API、換網址與金鑰）。
- **加密**：商業欄位組成 query string → **AES-256-CBC（PKCS7）** → 小寫 hex，放入 `PostData_`。
- **簽章**：`CheckValue`（送出，BDV 才需要）與 `CheckCode`（驗回應）皆 SHA256 大寫，但**夾 Key/IV 的順序相反**。
- **雙金鑰**：發票/BDV 用「商店金鑰」搭 `MerchantID_`；字軌用「會員金鑰」搭 `CompanyID_`，**兩把不同**。
- **回應**：發票/字軌類 `Result` 是明文 JSON；BDV 類 `Result` 是 AES 加密 hex，需解密。

> ⚠️ 機敏資訊：本 skill **不含任何真實金鑰／商店代號**。所有密鑰一律由使用者填入專案的 `.env`，
> 程式只從環境讀取、絕不寫死、絕不進版控。唯一出現的金鑰是手冊「公開範例向量」，僅供離線自我測試。

## 來源與版本時效性（務必先確認）

- **官方文件下載頁（唯一權威來源）**：https://inv.ezpay.com.tw/Invoice_index/download
  ezPay 會不定期改版手冊，**本 skill 的規格不保證永遠最新**。
- **本 skill 依據的手冊版本**（驗證日期 **2026-06-03**，測試環境實機跑綠）：
  - 開立／作廢／折讓／查詢：`EZP_INVI_1.2.2`（最後異動 2024-04-22）
  - 字軌管理：`EZP_Track_1.0.0`（2018-10-03）
  - 手機條碼／捐贈碼驗證：`EZP_BDV_1.0.0`（2021-02）
- **動手前先做版本檢查**：到上方下載頁取得最新手冊、比對文件版號。
  - 版號相同 → 可直接信任本 skill。
  - 版號較新 → **切勿照舊規格開發**。先看手冊開頭「版本異動」表，針對變動章節重新核對
    端點／Version／參數，更新 `reference/` 後再進行。
  - 加解密與簽章邏輯（`crypto.md`）歷來穩定，`selftest` 仍可先驗；但**端點與參數最易隨版本變動**。
- 詳細的版本對照與漂移檢查清單見 `reference/source-and-versioning.md`。

## 建置工作流

照這個順序走，能最快做出可驗證的串接：

1. **確認範圍**：問清楚要哪些功能（開立？作廢？折讓？查詢？條碼/捐贈碼驗證？字軌？）與目標語言/框架。
   各功能的端點、版本號、必填參數見 `reference/api-reference.md`。

2. **備妥金鑰到 `.env`**（請使用者提供，勿寫死）。最多會用到這 6 個值：
   ```
   EZPAY_BASE_URL=https://cinv.ezpay.com.tw      # 測試；正式換 inv.ezpay.com.tw
   EZPAY_MERCHANT_ID=        # 商店代號（發票/BDV）
   EZPAY_COMPANY_ID=         # 會員編號（字軌；不做字軌可略）
   EZPAY_HASH_KEY=           # 商店金鑰 32 碼
   EZPAY_HASH_IV=            # 商店金鑰 16 碼
   EZPAY_COMPANY_HASH_KEY=   # 會員金鑰 32 碼（字軌用，與商店不同）
   EZPAY_COMPANY_HASH_IV=    # 會員金鑰 16 碼
   ```
   範本見 `scripts/.env.example`。把 `.env` 加進 `.gitignore`。

3. **先離線驗證加密正確**（不需金鑰、不連網）：
   ```
   python .claude/skills/ezpay-einvoice/scripts/ezpay_verify.py selftest
   ```
   這支用手冊公開向量驗證 AES 與簽章邏輯。先過這關，才不會把加密 bug 混進串接。

4. **實作串接層**：依 `reference/crypto.md`（加解密+簽章演算法，語言無關）與
   `reference/api-reference.md`（端點/參數）在目標語言實作。`scripts/ezpay_verify.py` 本身就是
   一份可讀的參考實作（Python），照著翻成 PHP/Node/Go 即可。實作時務必先讀 `reference/pitfalls.md`。

5. **實機 smoke test**：填好 `.env` 後跑驗證腳本（見下「驗證 harness」），確認端到端打通。

6. **遇錯查 `reference/error-codes.md`**：含「兩個錯誤碼同現＝金鑰張冠李戴」等除錯心法。

## 關鍵規則（最常踩雷，先讀這段）

這幾條手冊沒明講或前後矛盾，務必遵守，細節各見 reference：

- **雙金鑰別搞混**：字軌(`CompanyID_`)用會員金鑰、其餘用商店金鑰。用錯 → `KEY10002 解密錯誤`。
- **簽章方向相反**：`CheckValue = SHA256("HashKey={k}&{PostData}&HashIV={iv}")`（Key 在前）；
  `CheckCode = SHA256("HashIV={iv}&{ksort後5欄位}&HashKey={k}")`（IV 在前）。兩者皆轉大寫。
- **送出參數分兩類**：BDV 要送 `Version/RespondType/CheckValue`（外層）；發票/字軌**只送** `{ID}_ + PostData_`，
  `Version/RespondType` 包在 `PostData_` 內、不送 CheckValue。
- **端點命名不一致**：作廢發票 `invoice_invalid`（snake）、作廢折讓 `allowanceInvalid`（camelCase）。
- **開立折讓的發票號參數叫 `InvoiceNo`**，不是 `InvoiceNumber`。
- **加密要自補 PKCS7**：openssl 帶 `OPENSSL_ZERO_PADDING` 時不自動補，需先 PKCS7 padding。
- **字軌每期只能一組啟用**：啟用第二組會擠掉現用字軌、影響開立。變更前先記住原啟用字軌、之後還原。
- **參數名結尾有底線**：`MerchantID_`、`CompanyID_`、`PostData_`。

## 參考檔導覽（按需閱讀）

- `reference/api-reference.md` — 11 支端點、必填參數、版本號、Result 編碼、回應欄位。**實作任何 API 前先查。**
- `reference/crypto.md` — AES-256-CBC 加解密 + CheckValue/CheckCode 的逐步演算法（語言無關）+ 公開驗證向量。**寫加密層時讀。**
- `reference/pitfalls.md` — 雙金鑰、金額規則(B2C含稅/B2B未稅)、折讓隔日上傳、字軌啟用風險、作廢期別等。**動手前讀。**
- `reference/error-codes.md` — 錯誤碼意義與除錯心法。**回應非 SUCCESS 時讀。**
- `reference/source-and-versioning.md` — 官方來源、本 skill 依據的手冊版本、版本漂移檢查清單。**開工前先做版本檢查。**

## 驗證 harness

`scripts/ezpay_verify.py` 是自包含的單檔工具（只依賴 `requests`、`pycryptodome`、`python-dotenv`），
既可實機 smoke test，也是可讀的參考實作。常用：

```
python scripts/ezpay_verify.py selftest                       # 離線：用公開向量驗證加密（免金鑰）
python scripts/ezpay_verify.py smoke --env path/to/.env       # 連線：開立 → 查詢，確認金鑰與端到端
python scripts/ezpay_verify.py barcode /ABC.123 --env .env    # 手機條碼驗證
python scripts/ezpay_verify.py issue --category B2B --ubn 12345675 --env .env
python scripts/ezpay_verify.py track-search --env .env        # 字軌查詢（唯讀，需會員金鑰）
```

未指定 `--env` 時，依序找 `EZPAY_DOTENV` 環境變數、當前目錄 `.env`。完整子指令見 `python ezpay_verify.py -h`。
字軌的「新增/管理」具狀態副作用（啟用會擠掉現用字軌），預設 smoke 不含；要測請單獨呼叫並注意還原。
