Agent Skill
2/7/2026

taiwan-invoice

Taiwan E-Invoice API integration specialist for ECPay, SmilePay, and Amego. Use when developing invoice systems, implementing B2C/B2B invoice issuance, invoice printing, allowance creation, or working with Taiwan E-Invoice APIs. Handles encryption (AES, MD5), API requests, and service provider differences.

M
moksa1123
4GitHub Stars
1Views
npx skills add Moksa1123/taiwan-ecommerce-toolkit

SKILL.md

Nametaiwan-invoice
DescriptionTaiwan E-Invoice API integration specialist for ECPay, SmilePay, and Amego. Use when developing invoice systems, implementing B2C/B2B invoice issuance, invoice printing, allowance creation, or working with Taiwan E-Invoice APIs. Handles encryption (AES, MD5), API requests, and service provider differences.

name: taiwan-invoice description: Taiwan E-Invoice API integration specialist for ECPay, SmilePay, and Amego. Use when developing invoice systems, implementing B2C/B2B invoice issuance, invoice printing, allowance creation, or working with Taiwan E-Invoice APIs. Handles encryption (AES, MD5), API requests, and service provider differences. user-invocable: true

Taiwan E-Invoice Development Skill

此技能涵蓋台灣電子發票 API 整合開發,包含綠界 (ECPay)、速買配 (SmilePay)、光貿 (Amego) 三家服務商。

快速導覽

相關文件

使用此技能時,請參考專案中的 API 規格文件:

  • references/ECPAY_API_REFERENCE.md - 綠界 API 規格
  • references/SMILEPAY_API_REFERENCE.md - 速買配 API 規格
  • references/AMEGO_API_REFERENCE.md - 光貿 API 規格
  • EXAMPLES.md - 程式碼範例集

智能工具

  • scripts/search.py - BM25 搜索引擎(查詢 API、錯誤碼、欄位映射)
  • scripts/recommend.py - 加值中心推薦系統
  • scripts/generate-invoice-service.py - 服務代碼生成器
  • scripts/persist.py - 持久化配置工具(MASTER.md 生成)
  • data/ - CSV 數據檔(providers, operations, error-codes, field-mappings, tax-rules, troubleshooting, reasoning)

何時使用此技能

  • 開發電子發票開立功能
  • 整合台灣電子發票服務商 API
  • 實作 B2C(二聯式)或 B2B(三聯式)發票
  • 處理發票列印、作廢、折讓等功能
  • 處理加密簽章(AES、MD5)
  • 解決發票 API 整合問題

智能搜索與推薦

搜索引擎 (search.py)

使用 BM25 算法在資料庫中搜索相關資訊:

# 搜索加值中心
python scripts/search.py "ecpay" --domain provider

# 搜索錯誤碼
python scripts/search.py "10000016" --domain error

# 搜索欄位映射
python scripts/search.py "MerchantID" --domain field

# 搜索稅務規則
python scripts/search.py "B2B 稅額計算" --domain tax

# 搜索疑難排解
python scripts/search.py "列印空白" --domain troubleshoot

# JSON 輸出
python scripts/search.py "折讓" --format json

搜索域:

說明CSV 檔案
provider加值中心比較providers.csv
operationAPI 操作端點operations.csv
error錯誤碼查詢error-codes.csv
field欄位映射field-mappings.csv
tax稅務計算規則tax-rules.csv
troubleshoot疑難排解troubleshooting.csv
reasoning推薦決策規則reasoning.csv

推薦系統 (recommend.py)

根據需求自動推薦最適合的加值中心:

# 高交易量電商
python scripts/recommend.py "電商 高交易量 穩定"
# → 推薦 ECPay (市佔率高,穩定性佳)

# 快速整合需求
python scripts/recommend.py "簡單 快速 小型專案"
# → 推薦 SmilePay (整合最簡單)

# API 設計優先
python scripts/recommend.py "API 設計 MIG標準"
# → 推薦 Amego (MIG 4.0 最新標準)

# JSON 輸出
python scripts/recommend.py "穩定 文檔完整" --format json

推薦關鍵字:

  • ECPay: 穩定、市佔、文檔、SDK、高交易量、電商
  • SmilePay: 簡單、快速、小型、測試、無加密、便宜
  • Amego: API、設計、新、MIG、標準

代碼生成器 (generate-invoice-service.py)

自動生成服務商專用代碼:

# 生成 TypeScript 服務
python scripts/generate-invoice-service.py ECPay --output ts

# 生成 Python 服務
python scripts/generate-invoice-service.py SmilePay --output py

# 輸出到檔案
python scripts/generate-invoice-service.py Amego --output ts > amego-service.ts

持久化配置 (persist.py)

將發票配置保存為 MASTER.md,供 AI 助手持續參考:

# 初始化配置
python scripts/persist.py init ECPay
python scripts/persist.py init SmilePay -p "MyProject"

# 顯示當前配置
python scripts/persist.py show

# 列出可用服務商
python scripts/persist.py list

# 強制覆蓋
python scripts/persist.py init Amego --force

生成結構:

invoice-config/
└── MASTER.md       # 專案發票配置
    ├── 基本資訊
    ├── 服務商配置
    ├── API 端點
    ├── 發票類型設定
    ├── 環境變數建議
    └── 開發檢查清單

發票類型

B2C 二聯式發票

  • 買受人無統編
  • BuyerIdentifier = 0000000000
  • 金額為含稅價
  • 可使用載具或捐贈
  • 示例:一般消費者購物

B2B 三聯式發票

  • 買受人有 8 碼統編
  • BuyerIdentifier = 實際統編(需驗證格式)
  • 金額為未稅價,需另計稅額
  • 不可使用載具或捐贈
  • 示例:公司採購

各服務商特性比較

特性綠界 ECPay速買配 SmilePay光貿 Amego
測試/正式 URL不同 URL不同 URL相同 URL
認證方式AES 加密 + HashKey/HashIVGrvc + Verify_keyMD5 簽章 + App Key
列印方式POST 表單提交GET URL 參數API 取得 PDF URL
B2B 金額欄位SalesAmount (未稅)UnitTAX=NDetailVat=0
傳輸格式JSON (AES 加密)URL ParametersJSON (URL Encode)

開發實作步驟

1. 服務實作架構

創建服務時遵循以下結構:

// lib/services/invoice-provider.ts - 介面定義
export interface InvoiceService {
    issueInvoice(userId: string, data: InvoiceIssueData): Promise<InvoiceIssueResponse>
    voidInvoice(userId: string, invoiceNumber: string, reason: string): Promise<InvoiceVoidResponse>
    printInvoice(userId: string, invoiceNumber: string): Promise<InvoicePrintResponse>
}

// lib/services/{provider}-invoice-service.ts - 各服務商實作
export class ECPayInvoiceService implements InvoiceService {
    private async encryptData(data: any, hashKey: string, hashIV: string): Promise<string> {
        // AES-128-CBC 加密實作
    }

    async issueInvoice(userId: string, data: InvoiceIssueData) {
        // 1. 取得使用者設定
        // 2. 準備 API 資料
        // 3. 加密簽章
        // 4. 發送請求
        // 5. 解密回應
        // 6. 回傳標準格式
    }
}

2. 金額計算邏輯

含稅總額 → 未稅金額 + 稅額:

function calculateInvoiceAmounts(totalAmount: number, isB2B: boolean) {
    if (isB2B) {
        // B2B: 需分拆稅額
        const taxAmount = Math.round(totalAmount - (totalAmount / 1.05))
        const salesAmount = totalAmount - taxAmount
        return { salesAmount, taxAmount, totalAmount }
    } else {
        // B2C: 含稅總額
        return { salesAmount: totalAmount, taxAmount: 0, totalAmount }
    }
}

// 範例
const amounts = calculateInvoiceAmounts(1050, true)
// { salesAmount: 1000, taxAmount: 50, totalAmount: 1050 }

3. 加密實作

綠界 (ECPay) - AES 加密:

import crypto from 'crypto'

function encryptECPay(data: object, hashKey: string, hashIV: string): string {
    // 1. JSON 轉字串並 URL Encode
    const jsonString = JSON.stringify(data)
    const urlEncoded = encodeURIComponent(jsonString)

    // 2. AES-128-CBC 加密
    const cipher = crypto.createCipheriv('aes-128-cbc', hashKey, hashIV)
    let encrypted = cipher.update(urlEncoded, 'utf8', 'base64')
    encrypted += cipher.final('base64')

    return encrypted
}

function decryptECPay(encryptedData: string, hashKey: string, hashIV: string): object {
    const decipher = crypto.createDecipheriv('aes-128-cbc', hashKey, hashIV)
    let decrypted = decipher.update(encryptedData, 'base64', 'utf8')
    decrypted += decipher.final('utf8')

    const urlDecoded = decodeURIComponent(decrypted)
    return JSON.parse(urlDecoded)
}

光貿 (Amego) - MD5 簽章:

function generateAmegoSign(data: object, time: number, appKey: string): string {
    const dataString = JSON.stringify(data)
    const signString = dataString + time + appKey
    return crypto.createHash('md5').update(signString).digest('hex')
}

4. 服務商綁定

關鍵:開立發票時必須記錄使用的服務商,列印時才能正確調用

// 開立時儲存服務商
await prisma.financialRecord.update({
    where: { id: recordId },
    data: {
        invoiceNo: result.invoiceNumber,
        invoiceProvider: actualProvider,  // 'ECPAY' | 'SMILEPAY' | 'AMEGO'
        invoiceRandomNum: result.randomNumber, // **重要**:列印時需要
        invoiceDate: new Date(),
    }
})

// 列印時使用開立時的服務商
const service = record.invoiceProvider
    ? InvoiceServiceFactory.getService(record.invoiceProvider)
    : await InvoiceServiceFactory.getServiceForUser(userId)

5. 列印回應處理

前端需根據回應類型處理:

// 後端回應格式
interface InvoicePrintResponse {
    success: boolean
    type?: 'html' | 'redirect' | 'form'
    htmlContent?: string      // 綠界
    printUrl?: string          // 速買配/光貿
    formUrl?: string
    formParams?: Record<string, string>
}

// 前端處理範例
if (result.type === 'html') {
    const win = window.open('', '_blank')
    win.document.write(result.htmlContent)
} else if (result.type === 'redirect') {
    window.open(result.url, '_blank')
} else if (result.type === 'form') {
    // 動態建立表單提交
    const form = document.createElement('form')
    form.method = 'POST'
    form.action = result.formUrl
    form.target = '_blank'
    // ... 添加參數
    form.submit()
}

常見問題排除

問題 1: 開立發票失敗,錯誤訊息不明確

診斷步驟:

  1. 檢查 logger 輸出,查看 raw 欄位完整錯誤
  2. 確認環境變數(測試/正式)是否正確
  3. 驗證必填欄位是否完整

綠界常見錯誤:

  • 10000006: RelateNumber 重複 → 訂單編號已使用
  • 10000016: 金額計算錯誤 → 檢查 B2C/B2B 金額計算
  • 10000019: 打統編不可使用載具 → 移除 CarrierType

速買配常見錯誤:

  • -10066: AllAmount 驗算錯誤 → 檢查是否傳入 TotalAmount
  • -10084: orderid 格式錯誤 → 限制 30 字元
  • -10053: 載具號碼錯誤 → 驗證手機條碼格式

光貿常見錯誤:

  • 1002: OrderId 已存在 → 使用唯一訂單編號
  • 1007: 金額計算錯誤 → 檢查 DetailVat 設定
  • 1012: 打統編發票不可使用載具或捐贈

問題 2: 列印時顯示「查詢不到該發票」

解決方案: 確認 invoiceProvider 欄位有正確儲存,列印時使用開立時的服務商。

// 正確:使用發票記錄中的服務商
const service = record.invoiceProvider
    ? InvoiceServiceFactory.getService(record.invoiceProvider)
    : await InvoiceServiceFactory.getServiceForUser(userId)

// 錯誤:使用使用者當前預設服務商
const service = await InvoiceServiceFactory.getServiceForUser(userId)

問題 3: B2B 發票金額錯誤

各服務商金額欄位:

// 綠界 ECPay
const b2bData = {
    SalesAmount: 1000,      // 未稅銷售額
    TaxAmount: 50,          // 稅額
    TotalAmount: 1050,      // 總計
    ItemPrice: 100,         // 商品單價(未稅)
    ItemAmount: 1000,       // 商品小計(未稅)
    ItemTax: 50             // 商品稅額
}

// 速買配 SmilePay
const b2bData = {
    AllAmount: '1050',      // 含稅總額
    SalesAmount: '1000',    // 未稅銷售額(選填,但建議填)
    TaxAmount: '50',        // 稅額(選填)
    UnitTAX: 'N',           // **重要**:單價未稅
    UnitPrice: '100',       // 商品單價(未稅)
    Amount: '1000'          // 商品小計(未稅)
}

// 光貿 Amego
const b2bData = {
    DetailVat: 0,           // **重要**:0=未稅
    SalesAmount: 1000,      // 未稅銷售額
    TaxAmount: 50,          // 稅額
    TotalAmount: 1050,      // 總計
    ProductItem: [{
        UnitPrice: 100,     // 商品單價(未稅)
        Amount: 1000        // 商品小計(未稅)
    }]
}

問題 4: 速買配列印空白

原因: 回傳 method: 'GET' 時錯誤使用 type: 'form'

解決:

// 正確
if (printData.method === 'GET' && printData.url) {
    return { type: 'redirect', url: printData.url }
}

// 錯誤
return { type: 'form', url: printData.url, params: printData.params }

問題 5: 時間戳記逾時

綠界錯誤 10000005: 時間戳記超過 10 分鐘

解決:

// 確保使用當前時間戳
const timestamp = Math.floor(Date.now() / 1000)

// 光貿:誤差容許 ±60 秒
const time = Math.floor(Date.now() / 1000)

測試帳號

綠界測試環境

MerchantID: 2000132
HashKey: ejCk326UnaZWKisg
HashIV: q9jcZX8Ib9LM8wYk
URL: https://einvoice-stage.ecpay.com.tw

速買配測試環境

Grvc: SEI1000034
Verify_key: 9D73935693EE0237FABA6AB744E48661
測試統編: 80129529
URL: https://ssl.smse.com.tw/api_test/SPEinvoice_Storage.asp

光貿測試環境

統編: 12345678
App Key: sHeq7t8G1wiQvhAuIM27
後台: https://invoice.amego.tw/
測試帳號: test@amego.tw
測試密碼: 12345678

開發檢查清單

使用此清單確保實作完整:

  • 實作 InvoiceService 介面
  • 處理 B2C / B2B 金額計算差異
  • 實作加密/簽章機制(AES 或 MD5)
  • 儲存 invoiceProvider 欄位
  • 儲存 invoiceRandomNum(列印時需要)
  • 處理列印回應類型(html/redirect/form)
  • 實作錯誤處理與 logger
  • 測試環境驗證
  • 處理載具與捐贈互斥邏輯
  • 驗證統編格式(8 碼數字)

新增服務商步驟

  1. lib/services/ 建立 {provider}-invoice-service.ts
  2. 實作 InvoiceService 介面的所有方法
  3. InvoiceServiceFactory 註冊新服務商
  4. prisma/schema.prismaInvoiceProvider enum 新增選項
  5. 執行 prisma migrateprisma db push
  6. 更新前端設定頁面(app/settings/invoice/page.tsx
  7. 撰寫單元測試

參考資料

詳細 API 規格請查看 references/ 目錄:


最後更新:2026/01/29

Skills Info
Original Name:taiwan-invoiceAuthor:moksa1123