|
| 1 | +# Research Report: Taiwan E-Invoice Development Kit |
| 2 | + |
| 3 | +## 1. Executive Summary |
| 4 | + |
| 5 | +The goal is to create `invoicekit`, a modern, modular, and framework-agnostic TypeScript toolkit for Taiwan Electronic Invoices (e-Invoice/eGUI), similar in philosophy to `linekit`. |
| 6 | + |
| 7 | +Currently, developers usually integrate with **Value Added Service Centers (加值中心)** like ECPay (綠界) or EZpay (簡單付) because connecting directly to the Ministry of Finance (MOF) Turnkey system is technically complex and regulated. |
| 8 | + |
| 9 | +**Opportunity**: There is no single, unified TypeScript SDK that abstracts these different providers (MOF, ECPay, EZpay) into a consistent API. Existing libraries are often outdated, provider-specific, or lack TypeScript support. |
| 10 | + |
| 11 | +## 2. The Ecosystem |
| 12 | + |
| 13 | +### A. Ministry of Finance (MOF) Platform |
| 14 | + |
| 15 | +- **Role**: The central government source. |
| 16 | +- **Access**: |
| 17 | + - **Turnkey**: For high-volume B2B/B2C issuance. Requires strict certification and MIG 4.0 xml formats. |
| 18 | + - **API (AppID)**: For querying invoice details, winning numbers, and verifying carriers (手機條碼). **Not for issuing B2C invoices** directly without a Turnkey or aggregator. |
| 19 | +- **Key APIs**: `getInvoiceDetail`, `getWinningNumbers`, `checkMobileBarCode`. |
| 20 | + |
| 21 | +### B. Third-Party Aggregators (Providers) |
| 22 | + |
| 23 | +- **Role**: Intermediaries that handle the Turnkey complexity. Businesses pay them a fee per invoice. |
| 24 | +- **Major Players**: |
| 25 | + - **ECPay (綠界)**: Dominant market share. Uses AES encryption + HashKey/IV. |
| 26 | + - **EZpay (簡單付)**: Another popular option. |
| 27 | + - **Others**: NewebPay (藍新), LINE Pay (sometimes bundles). |
| 28 | +- **Mechanism**: RESTful-ish APIs (often XML or JSON with specific encryption). |
| 29 | + |
| 30 | +## 3. Proposed Architecture (`invoicekit`) |
| 31 | + |
| 32 | +Drafting a similar monorepo structure to `linekit`: |
| 33 | + |
| 34 | +```text |
| 35 | +packages/ |
| 36 | + core/ # Common types (MIG 4.0), validators, utilities |
| 37 | + mof/ # Ministry of Finance Public API (Winning #, Carrier check) |
| 38 | + ecpay/ # ECPay specific implementation |
| 39 | + ezpay/ # EZpay specific implementation |
| 40 | + universal/ # (Optional) Unified Interface for "Issuing" |
| 41 | +``` |
| 42 | + |
| 43 | +### Module Breakdown |
| 44 | + |
| 45 | +#### 1. `@invoicekit/core` |
| 46 | + |
| 47 | +- **Validators**: |
| 48 | + - Uniform Business No (統一編號) validation (Logic 8-digit check). |
| 49 | + - Mobile Barcode (手機條碼) regex validation (`/^\/[0-9A-Z.+-]{7}$/`). |
| 50 | + - Donate Code (愛心碼) verification. |
| 51 | +- **Types**: |
| 52 | + - Shared interfaces for `InvoiceItem`, `Customer`, `VatType` (Taxable, Zero-tax). |
| 53 | +- **Utils**: |
| 54 | + - Random number generators for tracking checking. |
| 55 | + |
| 56 | +#### 2. `@invoicekit/mof` (Public Data) |
| 57 | + |
| 58 | +Direct integration with `api.einvoice.nat.gov.tw`. |
| 59 | + |
| 60 | +- **Features**: |
| 61 | + - `getWinningNumbers(term)`: Fetch winning lottery numbers. |
| 62 | + - `verifyMobileBarcode(code)`: Check if a user's phone barcode exists. |
| 63 | + - `getInvoiceDetail(...)`: Query specific invoice info (B2B mostly). |
| 64 | + |
| 65 | +#### 3. `@invoicekit/ecpay` (Issuance) |
| 66 | + |
| 67 | +Wrapper for ECPay's specific encryption/form-posting flow. |
| 68 | + |
| 69 | +- **Features**: |
| 70 | + - `issue(invoiceData)`: Create a new B2C invoice. |
| 71 | + - `void(invoiceNumber)`: Cancel an invoice. |
| 72 | + - `allowance(invoiceNumber)`: Issue a refund/allowance. |
| 73 | + |
| 74 | +## 4. Example Usage (Concept) |
| 75 | + |
| 76 | +```typescript |
| 77 | +// 1. Validation (Core) |
| 78 | +import { validateTaxId, validateMobileBarcode } from "@invoicekit/core"; |
| 79 | + |
| 80 | +if (!validateMobileBarcode("/AB12345")) { |
| 81 | + throw new Error("Invalid barcode"); |
| 82 | +} |
| 83 | + |
| 84 | +// 2. Fetching Winning Numbers (MOF) |
| 85 | +import { mof } from "@invoicekit/mof"; |
| 86 | +const numbers = await mof.getWinningNumbers("11210"); // Oct 2023 |
| 87 | + |
| 88 | +// 3. Issuing Invoice (ECPay Adapter) |
| 89 | +import { ECPayClient } from "@invoicekit/ecpay"; |
| 90 | + |
| 91 | +const client = new ECPayClient({ |
| 92 | + merchantId: "...", |
| 93 | + hashKey: "...", |
| 94 | + hashIv: "..." |
| 95 | +}); |
| 96 | + |
| 97 | +const result = await client.issue({ |
| 98 | + orderId: "ORD-001", |
| 99 | + amount: 1000, |
| 100 | + items: [{ name: "Tech Gadget", count: 1, price: 1000 }], |
| 101 | + carrier: { type: "mobile", id: "/AB12345" } |
| 102 | +}); |
| 103 | +``` |
| 104 | + |
| 105 | +## 5. Roadmap Recommendation |
| 106 | + |
| 107 | +1. **Phase 1**: Build `@invoicekit/core` with strict validation logic (Tax ID, Barcodes) as these are universal. |
| 108 | +2. **Phase 2**: Build `@invoicekit/mof` to query government open data (Winning numbers are a great "Hello World"). |
| 109 | +3. **Phase 3**: Implement `@invoicekit/ecpay` as it's the most requested feature for commercial use. |
| 110 | + |
| 111 | +This structure allows you to maintain the same "Clean, Modular, Type-Safe" philosophy as `linekit`. |
0 commit comments