taiwan-invoice-skill 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/assets/taiwan-invoice/SKILL.md +485 -0
- package/assets/taiwan-invoice/data/error-codes.csv +41 -0
- package/assets/taiwan-invoice/data/field-mappings.csv +27 -0
- package/assets/taiwan-invoice/data/operations.csv +11 -0
- package/assets/taiwan-invoice/data/providers.csv +4 -0
- package/assets/taiwan-invoice/data/reasoning.csv +32 -0
- package/assets/taiwan-invoice/data/tax-rules.csv +9 -0
- package/assets/taiwan-invoice/data/troubleshooting.csv +17 -0
- package/assets/taiwan-invoice/scripts/__pycache__/core.cpython-312.pyc +0 -0
- package/assets/taiwan-invoice/scripts/core.py +310 -0
- package/assets/taiwan-invoice/scripts/generate-invoice-service.py +642 -128
- package/assets/taiwan-invoice/scripts/persist.py +330 -0
- package/assets/taiwan-invoice/scripts/recommend.py +373 -0
- package/assets/taiwan-invoice/scripts/search.py +273 -0
- package/dist/index.js +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,6 +119,23 @@ taiwan-invoice init --global # 安裝到全域目錄
|
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
122
|
+
## 智能工具
|
|
123
|
+
|
|
124
|
+
安裝後包含以下 Python 工具(純 Python,無需外部依賴):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# BM25 搜索引擎 - 搜索錯誤碼、欄位映射、稅務規則
|
|
128
|
+
python scripts/search.py "10000016" --domain error
|
|
129
|
+
|
|
130
|
+
# 加值中心推薦系統 - 根據需求推薦服務商
|
|
131
|
+
python scripts/recommend.py "電商 高交易量 穩定"
|
|
132
|
+
|
|
133
|
+
# 代碼生成器 - 生成 TypeScript/Python 服務模組
|
|
134
|
+
python scripts/generate-invoice-service.py ECPay --output ts
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
122
139
|
## 授權
|
|
123
140
|
|
|
124
141
|
[MIT License](https://github.com/Moksa1123/taiwan-invoice/blob/main/LICENSE)
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: taiwan-invoice
|
|
3
|
+
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.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Taiwan E-Invoice Development Skill
|
|
8
|
+
|
|
9
|
+
> 此技能涵蓋台灣電子發票 API 整合開發,包含綠界 (ECPay)、速買配 (SmilePay)、光貿 (Amego) 三家服務商。
|
|
10
|
+
|
|
11
|
+
## 快速導覽
|
|
12
|
+
|
|
13
|
+
### 相關文件
|
|
14
|
+
使用此技能時,請參考專案中的 API 規格文件:
|
|
15
|
+
- `references/ECPAY_API_REFERENCE.md` - 綠界 API 規格
|
|
16
|
+
- `references/SMILEPAY_API_REFERENCE.md` - 速買配 API 規格
|
|
17
|
+
- `references/AMEGO_API_REFERENCE.md` - 光貿 API 規格
|
|
18
|
+
- [EXAMPLES.md](EXAMPLES.md) - 程式碼範例集
|
|
19
|
+
|
|
20
|
+
### 智能工具
|
|
21
|
+
- `scripts/search.py` - BM25 搜索引擎(查詢 API、錯誤碼、欄位映射)
|
|
22
|
+
- `scripts/recommend.py` - 加值中心推薦系統
|
|
23
|
+
- `scripts/generate-invoice-service.py` - 服務代碼生成器
|
|
24
|
+
- `scripts/persist.py` - 持久化配置工具(MASTER.md 生成)
|
|
25
|
+
- `data/` - CSV 數據檔(providers, operations, error-codes, field-mappings, tax-rules, troubleshooting, reasoning)
|
|
26
|
+
|
|
27
|
+
### 何時使用此技能
|
|
28
|
+
- 開發電子發票開立功能
|
|
29
|
+
- 整合台灣電子發票服務商 API
|
|
30
|
+
- 實作 B2C(二聯式)或 B2B(三聯式)發票
|
|
31
|
+
- 處理發票列印、作廢、折讓等功能
|
|
32
|
+
- 處理加密簽章(AES、MD5)
|
|
33
|
+
- 解決發票 API 整合問題
|
|
34
|
+
|
|
35
|
+
## 智能搜索與推薦
|
|
36
|
+
|
|
37
|
+
### 搜索引擎 (search.py)
|
|
38
|
+
|
|
39
|
+
使用 BM25 算法在資料庫中搜索相關資訊:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# 搜索加值中心
|
|
43
|
+
python scripts/search.py "ecpay" --domain provider
|
|
44
|
+
|
|
45
|
+
# 搜索錯誤碼
|
|
46
|
+
python scripts/search.py "10000016" --domain error
|
|
47
|
+
|
|
48
|
+
# 搜索欄位映射
|
|
49
|
+
python scripts/search.py "MerchantID" --domain field
|
|
50
|
+
|
|
51
|
+
# 搜索稅務規則
|
|
52
|
+
python scripts/search.py "B2B 稅額計算" --domain tax
|
|
53
|
+
|
|
54
|
+
# 搜索疑難排解
|
|
55
|
+
python scripts/search.py "列印空白" --domain troubleshoot
|
|
56
|
+
|
|
57
|
+
# JSON 輸出
|
|
58
|
+
python scripts/search.py "折讓" --format json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**搜索域:**
|
|
62
|
+
| 域 | 說明 | CSV 檔案 |
|
|
63
|
+
|-----|------|----------|
|
|
64
|
+
| `provider` | 加值中心比較 | providers.csv |
|
|
65
|
+
| `operation` | API 操作端點 | operations.csv |
|
|
66
|
+
| `error` | 錯誤碼查詢 | error-codes.csv |
|
|
67
|
+
| `field` | 欄位映射 | field-mappings.csv |
|
|
68
|
+
| `tax` | 稅務計算規則 | tax-rules.csv |
|
|
69
|
+
| `troubleshoot` | 疑難排解 | troubleshooting.csv |
|
|
70
|
+
| `reasoning` | 推薦決策規則 | reasoning.csv |
|
|
71
|
+
|
|
72
|
+
### 推薦系統 (recommend.py)
|
|
73
|
+
|
|
74
|
+
根據需求自動推薦最適合的加值中心:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 高交易量電商
|
|
78
|
+
python scripts/recommend.py "電商 高交易量 穩定"
|
|
79
|
+
# → 推薦 ECPay (市佔率高,穩定性佳)
|
|
80
|
+
|
|
81
|
+
# 快速整合需求
|
|
82
|
+
python scripts/recommend.py "簡單 快速 小型專案"
|
|
83
|
+
# → 推薦 SmilePay (整合最簡單)
|
|
84
|
+
|
|
85
|
+
# API 設計優先
|
|
86
|
+
python scripts/recommend.py "API 設計 MIG標準"
|
|
87
|
+
# → 推薦 Amego (MIG 4.0 最新標準)
|
|
88
|
+
|
|
89
|
+
# JSON 輸出
|
|
90
|
+
python scripts/recommend.py "穩定 文檔完整" --format json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**推薦關鍵字:**
|
|
94
|
+
- **ECPay**: 穩定、市佔、文檔、SDK、高交易量、電商
|
|
95
|
+
- **SmilePay**: 簡單、快速、小型、測試、無加密、便宜
|
|
96
|
+
- **Amego**: API、設計、新、MIG、標準
|
|
97
|
+
|
|
98
|
+
### 代碼生成器 (generate-invoice-service.py)
|
|
99
|
+
|
|
100
|
+
自動生成服務商專用代碼:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# 生成 TypeScript 服務
|
|
104
|
+
python scripts/generate-invoice-service.py ECPay --output ts
|
|
105
|
+
|
|
106
|
+
# 生成 Python 服務
|
|
107
|
+
python scripts/generate-invoice-service.py SmilePay --output py
|
|
108
|
+
|
|
109
|
+
# 輸出到檔案
|
|
110
|
+
python scripts/generate-invoice-service.py Amego --output ts > amego-service.ts
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 持久化配置 (persist.py)
|
|
114
|
+
|
|
115
|
+
將發票配置保存為 MASTER.md,供 AI 助手持續參考:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# 初始化配置
|
|
119
|
+
python scripts/persist.py init ECPay
|
|
120
|
+
python scripts/persist.py init SmilePay -p "MyProject"
|
|
121
|
+
|
|
122
|
+
# 顯示當前配置
|
|
123
|
+
python scripts/persist.py show
|
|
124
|
+
|
|
125
|
+
# 列出可用服務商
|
|
126
|
+
python scripts/persist.py list
|
|
127
|
+
|
|
128
|
+
# 強制覆蓋
|
|
129
|
+
python scripts/persist.py init Amego --force
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**生成結構:**
|
|
133
|
+
```
|
|
134
|
+
invoice-config/
|
|
135
|
+
└── MASTER.md # 專案發票配置
|
|
136
|
+
├── 基本資訊
|
|
137
|
+
├── 服務商配置
|
|
138
|
+
├── API 端點
|
|
139
|
+
├── 發票類型設定
|
|
140
|
+
├── 環境變數建議
|
|
141
|
+
└── 開發檢查清單
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 發票類型
|
|
147
|
+
|
|
148
|
+
### B2C 二聯式發票
|
|
149
|
+
- 買受人無統編
|
|
150
|
+
- `BuyerIdentifier` = `0000000000`
|
|
151
|
+
- 金額為**含稅價**
|
|
152
|
+
- 可使用載具或捐贈
|
|
153
|
+
- 示例:一般消費者購物
|
|
154
|
+
|
|
155
|
+
### B2B 三聯式發票
|
|
156
|
+
- 買受人有 8 碼統編
|
|
157
|
+
- `BuyerIdentifier` = 實際統編(需驗證格式)
|
|
158
|
+
- 金額為**未稅價**,需另計稅額
|
|
159
|
+
- **不可**使用載具或捐贈
|
|
160
|
+
- 示例:公司採購
|
|
161
|
+
|
|
162
|
+
## 各服務商特性比較
|
|
163
|
+
|
|
164
|
+
| 特性 | 綠界 ECPay | 速買配 SmilePay | 光貿 Amego |
|
|
165
|
+
|------|-----------|-----------------|------------|
|
|
166
|
+
| 測試/正式 URL | 不同 URL | 不同 URL | **相同 URL** |
|
|
167
|
+
| 認證方式 | AES 加密 + HashKey/HashIV | Grvc + Verify_key | MD5 簽章 + App Key |
|
|
168
|
+
| 列印方式 | POST 表單提交 | GET URL 參數 | API 取得 PDF URL |
|
|
169
|
+
| B2B 金額欄位 | SalesAmount (未稅) | UnitTAX=N | DetailVat=0 |
|
|
170
|
+
| 傳輸格式 | JSON (AES 加密) | URL Parameters | JSON (URL Encode) |
|
|
171
|
+
|
|
172
|
+
## 開發實作步驟
|
|
173
|
+
|
|
174
|
+
### 1. 服務實作架構
|
|
175
|
+
|
|
176
|
+
創建服務時遵循以下結構:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// lib/services/invoice-provider.ts - 介面定義
|
|
180
|
+
export interface InvoiceService {
|
|
181
|
+
issueInvoice(userId: string, data: InvoiceIssueData): Promise<InvoiceIssueResponse>
|
|
182
|
+
voidInvoice(userId: string, invoiceNumber: string, reason: string): Promise<InvoiceVoidResponse>
|
|
183
|
+
printInvoice(userId: string, invoiceNumber: string): Promise<InvoicePrintResponse>
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// lib/services/{provider}-invoice-service.ts - 各服務商實作
|
|
187
|
+
export class ECPayInvoiceService implements InvoiceService {
|
|
188
|
+
private async encryptData(data: any, hashKey: string, hashIV: string): Promise<string> {
|
|
189
|
+
// AES-128-CBC 加密實作
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async issueInvoice(userId: string, data: InvoiceIssueData) {
|
|
193
|
+
// 1. 取得使用者設定
|
|
194
|
+
// 2. 準備 API 資料
|
|
195
|
+
// 3. 加密簽章
|
|
196
|
+
// 4. 發送請求
|
|
197
|
+
// 5. 解密回應
|
|
198
|
+
// 6. 回傳標準格式
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 2. 金額計算邏輯
|
|
204
|
+
|
|
205
|
+
**含稅總額 → 未稅金額 + 稅額:**
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
function calculateInvoiceAmounts(totalAmount: number, isB2B: boolean) {
|
|
209
|
+
if (isB2B) {
|
|
210
|
+
// B2B: 需分拆稅額
|
|
211
|
+
const taxAmount = Math.round(totalAmount - (totalAmount / 1.05))
|
|
212
|
+
const salesAmount = totalAmount - taxAmount
|
|
213
|
+
return { salesAmount, taxAmount, totalAmount }
|
|
214
|
+
} else {
|
|
215
|
+
// B2C: 含稅總額
|
|
216
|
+
return { salesAmount: totalAmount, taxAmount: 0, totalAmount }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 範例
|
|
221
|
+
const amounts = calculateInvoiceAmounts(1050, true)
|
|
222
|
+
// { salesAmount: 1000, taxAmount: 50, totalAmount: 1050 }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. 加密實作
|
|
226
|
+
|
|
227
|
+
**綠界 (ECPay) - AES 加密:**
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import crypto from 'crypto'
|
|
231
|
+
|
|
232
|
+
function encryptECPay(data: object, hashKey: string, hashIV: string): string {
|
|
233
|
+
// 1. JSON 轉字串並 URL Encode
|
|
234
|
+
const jsonString = JSON.stringify(data)
|
|
235
|
+
const urlEncoded = encodeURIComponent(jsonString)
|
|
236
|
+
|
|
237
|
+
// 2. AES-128-CBC 加密
|
|
238
|
+
const cipher = crypto.createCipheriv('aes-128-cbc', hashKey, hashIV)
|
|
239
|
+
let encrypted = cipher.update(urlEncoded, 'utf8', 'base64')
|
|
240
|
+
encrypted += cipher.final('base64')
|
|
241
|
+
|
|
242
|
+
return encrypted
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function decryptECPay(encryptedData: string, hashKey: string, hashIV: string): object {
|
|
246
|
+
const decipher = crypto.createDecipheriv('aes-128-cbc', hashKey, hashIV)
|
|
247
|
+
let decrypted = decipher.update(encryptedData, 'base64', 'utf8')
|
|
248
|
+
decrypted += decipher.final('utf8')
|
|
249
|
+
|
|
250
|
+
const urlDecoded = decodeURIComponent(decrypted)
|
|
251
|
+
return JSON.parse(urlDecoded)
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**光貿 (Amego) - MD5 簽章:**
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
function generateAmegoSign(data: object, time: number, appKey: string): string {
|
|
259
|
+
const dataString = JSON.stringify(data)
|
|
260
|
+
const signString = dataString + time + appKey
|
|
261
|
+
return crypto.createHash('md5').update(signString).digest('hex')
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 4. 服務商綁定
|
|
266
|
+
|
|
267
|
+
**關鍵:開立發票時必須記錄使用的服務商,列印時才能正確調用**
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
// 開立時儲存服務商
|
|
271
|
+
await prisma.financialRecord.update({
|
|
272
|
+
where: { id: recordId },
|
|
273
|
+
data: {
|
|
274
|
+
invoiceNo: result.invoiceNumber,
|
|
275
|
+
invoiceProvider: actualProvider, // 'ECPAY' | 'SMILEPAY' | 'AMEGO'
|
|
276
|
+
invoiceRandomNum: result.randomNumber, // **重要**:列印時需要
|
|
277
|
+
invoiceDate: new Date(),
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// 列印時使用開立時的服務商
|
|
282
|
+
const service = record.invoiceProvider
|
|
283
|
+
? InvoiceServiceFactory.getService(record.invoiceProvider)
|
|
284
|
+
: await InvoiceServiceFactory.getServiceForUser(userId)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 5. 列印回應處理
|
|
288
|
+
|
|
289
|
+
前端需根據回應類型處理:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// 後端回應格式
|
|
293
|
+
interface InvoicePrintResponse {
|
|
294
|
+
success: boolean
|
|
295
|
+
type?: 'html' | 'redirect' | 'form'
|
|
296
|
+
htmlContent?: string // 綠界
|
|
297
|
+
printUrl?: string // 速買配/光貿
|
|
298
|
+
formUrl?: string
|
|
299
|
+
formParams?: Record<string, string>
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 前端處理範例
|
|
303
|
+
if (result.type === 'html') {
|
|
304
|
+
const win = window.open('', '_blank')
|
|
305
|
+
win.document.write(result.htmlContent)
|
|
306
|
+
} else if (result.type === 'redirect') {
|
|
307
|
+
window.open(result.url, '_blank')
|
|
308
|
+
} else if (result.type === 'form') {
|
|
309
|
+
// 動態建立表單提交
|
|
310
|
+
const form = document.createElement('form')
|
|
311
|
+
form.method = 'POST'
|
|
312
|
+
form.action = result.formUrl
|
|
313
|
+
form.target = '_blank'
|
|
314
|
+
// ... 添加參數
|
|
315
|
+
form.submit()
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## 常見問題排除
|
|
320
|
+
|
|
321
|
+
### 問題 1: 開立發票失敗,錯誤訊息不明確
|
|
322
|
+
|
|
323
|
+
**診斷步驟:**
|
|
324
|
+
1. 檢查 logger 輸出,查看 `raw` 欄位完整錯誤
|
|
325
|
+
2. 確認環境變數(測試/正式)是否正確
|
|
326
|
+
3. 驗證必填欄位是否完整
|
|
327
|
+
|
|
328
|
+
**綠界常見錯誤:**
|
|
329
|
+
- `10000006`: RelateNumber 重複 → 訂單編號已使用
|
|
330
|
+
- `10000016`: 金額計算錯誤 → 檢查 B2C/B2B 金額計算
|
|
331
|
+
- `10000019`: 打統編不可使用載具 → 移除 CarrierType
|
|
332
|
+
|
|
333
|
+
**速買配常見錯誤:**
|
|
334
|
+
- `-10066`: AllAmount 驗算錯誤 → 檢查是否傳入 TotalAmount
|
|
335
|
+
- `-10084`: orderid 格式錯誤 → 限制 30 字元
|
|
336
|
+
- `-10053`: 載具號碼錯誤 → 驗證手機條碼格式
|
|
337
|
+
|
|
338
|
+
**光貿常見錯誤:**
|
|
339
|
+
- `1002`: OrderId 已存在 → 使用唯一訂單編號
|
|
340
|
+
- `1007`: 金額計算錯誤 → 檢查 DetailVat 設定
|
|
341
|
+
- `1012`: 打統編發票不可使用載具或捐贈
|
|
342
|
+
|
|
343
|
+
### 問題 2: 列印時顯示「查詢不到該發票」
|
|
344
|
+
|
|
345
|
+
**解決方案:**
|
|
346
|
+
確認 `invoiceProvider` 欄位有正確儲存,列印時使用開立時的服務商。
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// 正確:使用發票記錄中的服務商
|
|
350
|
+
const service = record.invoiceProvider
|
|
351
|
+
? InvoiceServiceFactory.getService(record.invoiceProvider)
|
|
352
|
+
: await InvoiceServiceFactory.getServiceForUser(userId)
|
|
353
|
+
|
|
354
|
+
// 錯誤:使用使用者當前預設服務商
|
|
355
|
+
const service = await InvoiceServiceFactory.getServiceForUser(userId)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 問題 3: B2B 發票金額錯誤
|
|
359
|
+
|
|
360
|
+
**各服務商金額欄位:**
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
// 綠界 ECPay
|
|
364
|
+
const b2bData = {
|
|
365
|
+
SalesAmount: 1000, // 未稅銷售額
|
|
366
|
+
TaxAmount: 50, // 稅額
|
|
367
|
+
TotalAmount: 1050, // 總計
|
|
368
|
+
ItemPrice: 100, // 商品單價(未稅)
|
|
369
|
+
ItemAmount: 1000, // 商品小計(未稅)
|
|
370
|
+
ItemTax: 50 // 商品稅額
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 速買配 SmilePay
|
|
374
|
+
const b2bData = {
|
|
375
|
+
AllAmount: '1050', // 含稅總額
|
|
376
|
+
SalesAmount: '1000', // 未稅銷售額(選填,但建議填)
|
|
377
|
+
TaxAmount: '50', // 稅額(選填)
|
|
378
|
+
UnitTAX: 'N', // **重要**:單價未稅
|
|
379
|
+
UnitPrice: '100', // 商品單價(未稅)
|
|
380
|
+
Amount: '1000' // 商品小計(未稅)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// 光貿 Amego
|
|
384
|
+
const b2bData = {
|
|
385
|
+
DetailVat: 0, // **重要**:0=未稅
|
|
386
|
+
SalesAmount: 1000, // 未稅銷售額
|
|
387
|
+
TaxAmount: 50, // 稅額
|
|
388
|
+
TotalAmount: 1050, // 總計
|
|
389
|
+
ProductItem: [{
|
|
390
|
+
UnitPrice: 100, // 商品單價(未稅)
|
|
391
|
+
Amount: 1000 // 商品小計(未稅)
|
|
392
|
+
}]
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### 問題 4: 速買配列印空白
|
|
397
|
+
|
|
398
|
+
**原因:** 回傳 `method: 'GET'` 時錯誤使用 `type: 'form'`
|
|
399
|
+
|
|
400
|
+
**解決:**
|
|
401
|
+
```typescript
|
|
402
|
+
// 正確
|
|
403
|
+
if (printData.method === 'GET' && printData.url) {
|
|
404
|
+
return { type: 'redirect', url: printData.url }
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// 錯誤
|
|
408
|
+
return { type: 'form', url: printData.url, params: printData.params }
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### 問題 5: 時間戳記逾時
|
|
412
|
+
|
|
413
|
+
**綠界錯誤 10000005:** 時間戳記超過 10 分鐘
|
|
414
|
+
|
|
415
|
+
**解決:**
|
|
416
|
+
```typescript
|
|
417
|
+
// 確保使用當前時間戳
|
|
418
|
+
const timestamp = Math.floor(Date.now() / 1000)
|
|
419
|
+
|
|
420
|
+
// 光貿:誤差容許 ±60 秒
|
|
421
|
+
const time = Math.floor(Date.now() / 1000)
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## 測試帳號
|
|
425
|
+
|
|
426
|
+
### 綠界測試環境
|
|
427
|
+
```
|
|
428
|
+
MerchantID: 2000132
|
|
429
|
+
HashKey: ejCk326UnaZWKisg
|
|
430
|
+
HashIV: q9jcZX8Ib9LM8wYk
|
|
431
|
+
URL: https://einvoice-stage.ecpay.com.tw
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### 速買配測試環境
|
|
435
|
+
```
|
|
436
|
+
Grvc: SEI1000034
|
|
437
|
+
Verify_key: 9D73935693EE0237FABA6AB744E48661
|
|
438
|
+
測試統編: 80129529
|
|
439
|
+
URL: https://ssl.smse.com.tw/api_test/SPEinvoice_Storage.asp
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### 光貿測試環境
|
|
443
|
+
```
|
|
444
|
+
統編: 12345678
|
|
445
|
+
App Key: sHeq7t8G1wiQvhAuIM27
|
|
446
|
+
後台: https://invoice.amego.tw/
|
|
447
|
+
測試帳號: test@amego.tw
|
|
448
|
+
測試密碼: 12345678
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## 開發檢查清單
|
|
452
|
+
|
|
453
|
+
使用此清單確保實作完整:
|
|
454
|
+
|
|
455
|
+
- [ ] 實作 `InvoiceService` 介面
|
|
456
|
+
- [ ] 處理 B2C / B2B 金額計算差異
|
|
457
|
+
- [ ] 實作加密/簽章機制(AES 或 MD5)
|
|
458
|
+
- [ ] 儲存 `invoiceProvider` 欄位
|
|
459
|
+
- [ ] 儲存 `invoiceRandomNum`(列印時需要)
|
|
460
|
+
- [ ] 處理列印回應類型(html/redirect/form)
|
|
461
|
+
- [ ] 實作錯誤處理與 logger
|
|
462
|
+
- [ ] 測試環境驗證
|
|
463
|
+
- [ ] 處理載具與捐贈互斥邏輯
|
|
464
|
+
- [ ] 驗證統編格式(8 碼數字)
|
|
465
|
+
|
|
466
|
+
## 新增服務商步驟
|
|
467
|
+
|
|
468
|
+
1. 在 `lib/services/` 建立 `{provider}-invoice-service.ts`
|
|
469
|
+
2. 實作 `InvoiceService` 介面的所有方法
|
|
470
|
+
3. 在 `InvoiceServiceFactory` 註冊新服務商
|
|
471
|
+
4. 在 `prisma/schema.prisma` 的 `InvoiceProvider` enum 新增選項
|
|
472
|
+
5. 執行 `prisma migrate` 或 `prisma db push`
|
|
473
|
+
6. 更新前端設定頁面(`app/settings/invoice/page.tsx`)
|
|
474
|
+
7. 撰寫單元測試
|
|
475
|
+
|
|
476
|
+
## 參考資料
|
|
477
|
+
|
|
478
|
+
詳細 API 規格請查看 `references/` 目錄:
|
|
479
|
+
- [綠界 ECPay API 規格](./references/ECPAY_API_REFERENCE.md)
|
|
480
|
+
- [速買配 SmilePay API 規格](./references/SMILEPAY_API_REFERENCE.md)
|
|
481
|
+
- [光貿 Amego API 規格](./references/AMEGO_API_REFERENCE.md)
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
最後更新:2026/01/29
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
provider,code,message_zh,message_en,category,solution
|
|
2
|
+
ECPay,10000001,參數錯誤,Parameter error,通用,檢查必填欄位是否完整
|
|
3
|
+
ECPay,10000002,發票號碼重複,Duplicate invoice number,開立,使用不同的 RelateNumber
|
|
4
|
+
ECPay,10000003,特店編號錯誤,Invalid merchant ID,認證,確認 MerchantID 正確
|
|
5
|
+
ECPay,10000004,加密驗證失敗,Encryption verification failed,認證,檢查 HashKey/HashIV 和加密流程
|
|
6
|
+
ECPay,10000005,時間戳記逾時,Timestamp expired,認證,確保時間戳在 10 分鐘內
|
|
7
|
+
ECPay,10000006,RelateNumber 重複,Duplicate RelateNumber,開立,使用唯一的訂單編號
|
|
8
|
+
ECPay,10000007,發票不存在,Invoice not found,查詢,確認發票號碼正確
|
|
9
|
+
ECPay,10000008,發票已作廢,Invoice already voided,作廢,發票已被作廢無法重複操作
|
|
10
|
+
ECPay,10000009,發票已折讓,Invoice has allowance,作廢,需先作廢折讓才能作廢發票
|
|
11
|
+
ECPay,10000010,折讓金額超過發票金額,Allowance exceeds invoice amount,折讓,調整折讓金額
|
|
12
|
+
ECPay,10000011,買方統編格式錯誤,Invalid buyer identifier,開立,統編需為 8 碼數字
|
|
13
|
+
ECPay,10000016,金額計算錯誤,Amount calculation error,開立,檢查 SalesAmount + TaxAmount = TotalAmount
|
|
14
|
+
ECPay,10000018,載具與捐贈不可同時存在,Carrier and donation conflict,開立,二擇一
|
|
15
|
+
ECPay,10000019,打統編不可使用載具,B2B cannot use carrier,開立,移除載具設定
|
|
16
|
+
ECPay,10000020,打統編不可捐贈,B2B cannot donate,開立,設定 Donation=0
|
|
17
|
+
ECPay,6000015,買方識別碼資料不存在,Buyer identifier not found,開立,測試環境 B2B 需預先註冊統編
|
|
18
|
+
SmilePay,0,開立成功,Success,成功,
|
|
19
|
+
SmilePay,-1001,商家帳號缺少參數,Missing merchant parameters,認證,檢查 Grvc 和 Verify_key
|
|
20
|
+
SmilePay,-10011,查無商家帳號,Merchant not found,認證,確認帳號正確
|
|
21
|
+
SmilePay,-10012,尚未開放B2B功能,B2B not enabled,權限,聯繫速買配開通
|
|
22
|
+
SmilePay,-10013,尚未開放B2C功能,B2C not enabled,權限,確認使用測試環境 URL
|
|
23
|
+
SmilePay,-10033,B2C開立需再48hr內,B2C must issue within 48hr,開立,調整 InvoiceDate
|
|
24
|
+
SmilePay,-10034,B2B開立需再168hr內,B2B must issue within 168hr,開立,調整 InvoiceDate
|
|
25
|
+
SmilePay,-10066,商品總金額驗算錯誤,Amount calculation error,開立,確認 AllAmount = Sum(Amount)
|
|
26
|
+
SmilePay,-10071,無可用字軌,No available track,開立,聯繫速買配配置字軌
|
|
27
|
+
SmilePay,-10072,自訂發票編號重複,Duplicate data_id,開立,使用唯一的 data_id
|
|
28
|
+
SmilePay,-10084,自訂號碼格式錯誤,Invalid orderid format,開立,orderid 限 30 字元
|
|
29
|
+
SmilePay,-2008,發票目前狀態不允許執行該動作,Invalid invoice status,作廢,檢查發票狀態
|
|
30
|
+
Amego,0,成功,Success,成功,
|
|
31
|
+
Amego,1,參數錯誤,Parameter error,通用,檢查必填欄位
|
|
32
|
+
Amego,2,簽章驗證失敗,Signature verification failed,認證,檢查 MD5 簽章計算
|
|
33
|
+
Amego,3,時間戳記誤差過大,Timestamp error,認證,確保時間戳誤差在 ±60 秒內
|
|
34
|
+
Amego,4,統一編號不存在,Tax ID not found,認證,確認統編正確
|
|
35
|
+
Amego,5,訂單編號重複,Duplicate order ID,開立,使用唯一的 OrderId
|
|
36
|
+
Amego,100,發票號碼不存在,Invoice not found,查詢,確認發票號碼正確
|
|
37
|
+
Amego,101,發票已作廢,Invoice already voided,作廢,發票已被作廢
|
|
38
|
+
Amego,1002,OrderId 已存在,OrderId exists,開立,使用不同的訂單編號
|
|
39
|
+
Amego,1004,BuyerName 不可為空或無效值,Invalid BuyerName,開立,不可填 0/00/000/0000
|
|
40
|
+
Amego,1007,金額計算錯誤,Amount calculation error,開立,檢查金額計算邏輯
|
|
41
|
+
Amego,1012,打統編發票不可使用載具或捐贈,B2B cannot use carrier or donate,開立,移除載具和捐贈設定
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
field_name,description,ecpay_name,smilepay_name,amego_name,type,required_b2c,required_b2b,notes
|
|
2
|
+
merchant_id,商家代號,MerchantID,Grvc,invoice,String,Y,Y,ECPay 10碼 SmilePay 帳號 Amego 統編
|
|
3
|
+
order_id,訂單編號,RelateNumber,data_id,OrderId,String,Y,Y,不可重複 ECPay 50字 SmilePay 50字 Amego 40字
|
|
4
|
+
buyer_identifier,買方統編,CustomerIdentifier,Buyer_id,BuyerIdentifier,String,N,Y,8碼數字 無統編填空(ECPay/SmilePay)或0000000000(Amego)
|
|
5
|
+
buyer_name,買方名稱,CustomerName,Name/CompanyName,BuyerName,String,N,Y,B2C用Name B2B用CompanyName (SmilePay)
|
|
6
|
+
buyer_email,買方信箱,CustomerEmail,Email,BuyerEmailAddress,String,N,N,多組用分號區隔
|
|
7
|
+
buyer_phone,買方電話,CustomerPhone,Phone,BuyerTelephoneNumber,String,N,N,
|
|
8
|
+
buyer_address,買方地址,CustomerAddr,Address,BuyerAddress,String,N,N,
|
|
9
|
+
invoice_type,字軌類別,InvType,Intype,TaxType,String,Y,Y,ECPay: 07一般/08特種 SmilePay: 07/08 Amego: 1-4/9
|
|
10
|
+
tax_type,課稅別,TaxType,TaxType,TaxType,Number,Y,Y,1應稅 2零稅率 3免稅 9混合
|
|
11
|
+
sales_amount,銷售額,SalesAmount,AllAmount/SalesAmount,SalesAmount,Number,Y,Y,B2C含稅 B2B未稅
|
|
12
|
+
tax_amount,稅額,TaxAmount,TaxAmount,TaxAmount,Number,N,Y,B2C為0 B2B需計算
|
|
13
|
+
total_amount,總金額,TotalAmount,AllAmount,TotalAmount,Number,N,Y,SalesAmount + TaxAmount
|
|
14
|
+
carrier_type,載具類別,CarrierType,CarrierType,CarrierType,String,N,N,手機條碼: ECPay=3 SmilePay=3J0002 Amego=3J0002
|
|
15
|
+
carrier_id,載具編號,CarrierNum,CarrierID,CarrierId1,String,N,N,手機條碼以/開頭共8碼
|
|
16
|
+
donation,捐贈註記,Donation,DonateMark,NPOBAN,String,Y,N,ECPay/SmilePay: 0不捐1捐 Amego: 直接填愛心碼
|
|
17
|
+
love_code,愛心碼,LoveCode,LoveKey,NPOBAN,String,N,N,捐贈時必填 7碼
|
|
18
|
+
print,列印註記,Print,,,String,Y,N,ECPay專用 0不列印 1列印 B2B固定1
|
|
19
|
+
invoice_date,發票日期,InvCreateDate,InvoiceDate,InvoiceDate,String,N,N,ECPay可回溯6天 SmilePay B2C 48hr B2B 168hr
|
|
20
|
+
invoice_time,發票時間,,InvoiceTime,InvoiceTime,String,N,N,SmilePay/Amego專用 HH:MM:SS
|
|
21
|
+
item_name,商品名稱,ItemName,Description,Description,String,Y,Y,ECPay 100字 SmilePay 256字 Amego 256字
|
|
22
|
+
item_count,商品數量,ItemCount,Quantity,Quantity,Number,Y,Y,
|
|
23
|
+
item_price,商品單價,ItemPrice,UnitPrice,UnitPrice,Number,Y,Y,B2C含稅 B2B未稅
|
|
24
|
+
item_amount,商品小計,ItemAmount,Amount,Amount,Number,Y,Y,ItemCount * ItemPrice
|
|
25
|
+
item_unit,商品單位,ItemWord,Unit,Unit,String,N,N,6字以內
|
|
26
|
+
item_remark,商品備註,ItemRemark,Remark,Remark,String,N,N,40字以內
|
|
27
|
+
random_number,隨機碼,RandomNumber,RandomNumber,random_number,String,N,N,開立成功後回傳 列印時需要
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
operation,operation_zh,ecpay_b2c_endpoint,ecpay_b2b_endpoint,smilepay_endpoint,amego_endpoint,required_fields,notes
|
|
2
|
+
issue,開立發票,/B2CInvoice/Issue,/B2BInvoice/Issue,/SPEinvoice_Storage.asp,/json/f0401,"MerchantID,RelateNumber,Items,SalesAmount",B2C/B2B 端點不同(ECPay)
|
|
3
|
+
void,作廢發票,/B2CInvoice/Invalid,/B2BInvoice/Invalid,/SPEinvoice_Storage_Modify.asp?types=Cancel,/json/f0501,"InvoiceNo,InvoiceDate,Reason",SmilePay 需帶 CancelReason
|
|
4
|
+
allowance,開立折讓,/B2CInvoice/Allowance,/B2BInvoice/Allowance,/SPEinvoice_Storage_Allowance.asp,/json/g0401,"InvoiceNo,AllowanceAmount,Items",折讓金額不可超過發票金額
|
|
5
|
+
void_allowance,作廢折讓,/B2CInvoice/AllowanceInvalid,/B2BInvoice/AllowanceInvalid,/SPEinvoice_Storage_Modify.asp?types=CancelAllowance,/json/g0501,"AllowanceNo,Reason",
|
|
6
|
+
query,查詢發票,/B2CInvoice/GetIssue,,/SPEinvoice_Storage_Modify.asp,/json/invoice_query,RelateNumber|InvoiceNo,ECPay用RelateNumber 其他用InvoiceNo
|
|
7
|
+
print,列印發票,/Invoice/Print,/Invoice/Print,/SmilePayCarrier/InvoiceDetails.php,/json/invoice_file,"InvoiceNo,InvoiceDate",ECPay用POST表單 SmilePay用GET Amego回傳PDF URL
|
|
8
|
+
check_barcode,驗證手機條碼,/B2CInvoice/CheckBarcode,,,/json/barcode,CarrierNum|barCode,驗證載具是否有效
|
|
9
|
+
check_lovecode,驗證愛心碼,/B2CInvoice/CheckLoveCode,,,/json/barcode,LoveCode,驗證捐贈碼是否有效
|
|
10
|
+
notify,發票通知,/B2CInvoice/InvoiceNotify,,,/json/invoice_file,"InvoiceNo,Email",補寄發票通知
|
|
11
|
+
invoice_list,發票列表,,,,/json/invoice_list,"date_start,date_end",僅Amego支援
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
provider,display_name,auth_method,encryption,test_url,prod_url,test_merchant_id,test_hash_key,test_hash_iv,content_type,features,market_share,api_style
|
|
2
|
+
ECPay,綠界科技,AES-128-CBC,URL Encode + AES 加密,https://einvoice-stage.ecpay.com.tw,https://einvoice.ecpay.com.tw,2000132,ejCk326UnaZWKisg,q9jcZX8Ib9LM8wYk,application/json,完整文檔 | SDK 支援 | 高穩定性,高,RESTful JSON
|
|
3
|
+
SmilePay,速買配,URL Parameter,Verify_key 驗證,https://ssl.smse.com.tw/api_test,https://ssl.smse.com.tw/api,SEI1000034,9D73935693EE0237FABA6AB744E48661,,application/x-www-form-urlencoded,雙協定(GET/POST) | 簡單整合 | XML回應,中,Query String
|
|
4
|
+
Amego,光貿科技,MD5 Signature,JSON + MD5 簽章,https://invoice-api.amego.tw,https://invoice-api.amego.tw,12345678,sHeq7t8G1wiQvhAuIM27,,application/x-www-form-urlencoded,MIG 4.0 | 統編查詢 | PDF下載 | 測試正式共用URL,中,RESTful JSON
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
scenario,recommended_provider,confidence,reason,decision_rules,anti_patterns,use_cases
|
|
2
|
+
高交易量電商,ECPay,HIGH,市佔率最高 系統穩定性佳,volume>1000/day AND priority=stability,避免使用測試環境長期運行,大型電商平台 購物網站
|
|
3
|
+
穩定性優先,ECPay,HIGH,台灣電子發票市佔率領先,priority=stability OR risk_tolerance=low,避免頻繁切換服務商,金融相關 醫療系統
|
|
4
|
+
完整文檔需求,ECPay,HIGH,提供完整 API 文檔與 SDK,priority=documentation OR team_size>3,避免依賴社群資源,企業級開發 團隊協作
|
|
5
|
+
多語言SDK需求,ECPay,MEDIUM,官方SDK支援多種語言,language IN (java php dotnet) AND need_sdk=true,避免自行實作加密,Java/.NET專案
|
|
6
|
+
簡單整合需求,SmilePay,HIGH,整合流程最簡單 無需複雜加密,priority=speed OR deadline<7days,避免過度設計,MVP開發 快速上線
|
|
7
|
+
小型專案,SmilePay,HIGH,適合小型專案和個人開發者,team_size<=2 AND budget=low,避免過度工程化,個人專案 小型網站
|
|
8
|
+
快速上線,SmilePay,HIGH,最快速完成整合,deadline<14days AND complexity=low,避免完美主義,緊急專案 POC驗證
|
|
9
|
+
測試環境友善,SmilePay,MEDIUM,測試環境設定簡單,phase=development OR phase=testing,避免正式環境測試,開發階段 測試階段
|
|
10
|
+
低預算專案,SmilePay,MEDIUM,費用相對較低,budget=low AND volume<500/day,避免過度投資,新創公司 個人開發
|
|
11
|
+
API設計優先,Amego,HIGH,MIG 4.0 最新 API 標準,priority=api_design OR tech_stack=modern,避免使用舊版API,技術導向團隊
|
|
12
|
+
現代技術棧,Amego,HIGH,採用最新技術標準,framework IN (nextjs nuxt sveltekit),避免傳統架構,現代前端專案
|
|
13
|
+
RESTful需求,Amego,MEDIUM,API設計符合REST規範,priority=clean_code AND experience>3years,避免過度抽象,資深開發團隊
|
|
14
|
+
MIG標準合規,Amego,HIGH,完整支援MIG 4.0規範,compliance=mig40 OR government=true,避免自定義協議,政府專案 標準合規
|
|
15
|
+
B2B發票為主,ECPay,MEDIUM,B2B發票功能完整 經驗豐富,invoice_type=b2b AND volume>100/day,避免B2C邏輯套用B2B,企業對企業交易
|
|
16
|
+
B2C發票為主,ECPay,MEDIUM,B2C市佔最高 問題解決資源多,invoice_type=b2c AND support_need=high,避免忽視客服需求,一般消費者交易
|
|
17
|
+
B2C簡單整合,SmilePay,MEDIUM,B2C整合最簡單,invoice_type=b2c AND priority=speed,避免過度複雜化,簡單B2C場景
|
|
18
|
+
混合發票需求,ECPay,MEDIUM,同時支援B2B/B2C 切換彈性,invoice_type=mixed,避免硬編碼發票類型,B2B+B2C混合
|
|
19
|
+
載具功能需求,ECPay,MEDIUM,載具支援最完整,feature=carrier AND carrier_type IN (mobile barcode),避免忽略載具驗證,手機條碼整合
|
|
20
|
+
捐贈功能需求,ECPay,MEDIUM,捐贈功能完整,feature=donation,避免捐贈與載具混用,公益捐贈整合
|
|
21
|
+
列印功能需求,ECPay,MEDIUM,列印功能完整 多種格式,feature=print AND print_format IN (a4 thermal),避免忽略隨機碼,實體發票列印
|
|
22
|
+
作廢功能需求,ECPay,LOW,作廢流程標準化,feature=void,避免作廢後重開相同號碼,發票作廢處理
|
|
23
|
+
折讓功能需求,ECPay,LOW,折讓功能完整,feature=allowance,避免折讓超過原發票金額,退款折讓處理
|
|
24
|
+
無技術資源,SmilePay,HIGH,無需複雜加密 整合門檻最低,tech_resource=limited OR developer_count=1,避免選擇高複雜度方案,一人團隊 非技術背景
|
|
25
|
+
AES加密經驗,ECPay,MEDIUM,需要AES-128-CBC加密經驗,encryption_experience=aes,避免明文傳輸,有加密經驗團隊
|
|
26
|
+
MD5簽章經驗,Amego,MEDIUM,使用MD5簽章驗證,encryption_experience=md5,避免簽章順序錯誤,有MD5經驗團隊
|
|
27
|
+
Node.js專案,ECPay,MEDIUM,官方有Node.js範例,language=nodejs AND need_example=true,避免從零實作加密,Node.js開發
|
|
28
|
+
Python專案,ECPay,MEDIUM,社群Python範例豐富,language=python,避免依賴過時範例,Python開發
|
|
29
|
+
PHP專案,ECPay,HIGH,官方PHP SDK最完整,language=php AND need_sdk=true,避免版本不相容,PHP開發
|
|
30
|
+
新創公司,SmilePay,MEDIUM,快速上線 成本控制,company_type=startup AND phase=early,避免過度投資基礎建設,早期新創
|
|
31
|
+
企業級應用,ECPay,HIGH,穩定性和支援優先,company_type=enterprise,避免使用非主流方案,大型企業
|
|
32
|
+
政府專案,Amego,MEDIUM,MIG標準合規,project_type=government,避免非標準協議,政府標案
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
invoice_type,tax_type,tax_rate,sales_amount_formula,tax_amount_formula,total_amount_formula,item_price_type,validation_rule,example_total,example_sales,example_tax,notes
|
|
2
|
+
B2C,應稅,0.05,含稅總額,0,SalesAmount,含稅,"SalesAmount = TotalAmount, TaxAmount = 0",1050,1050,0,二聯式發票 稅額系統自動計算
|
|
3
|
+
B2B,應稅,0.05,"round(TotalAmount / 1.05)","round(TotalAmount - TotalAmount/1.05)",SalesAmount + TaxAmount,未稅,"SalesAmount + TaxAmount = TotalAmount",1050,1000,50,三聯式發票 需自行計算稅額
|
|
4
|
+
B2C,零稅率,0,含稅總額,0,SalesAmount,含稅,"TaxAmount = 0, 需填 ClearanceMark 和 ZeroTaxRateReason",1000,1000,0,外銷等零稅率情況
|
|
5
|
+
B2B,零稅率,0,未稅總額,0,SalesAmount,未稅,"TaxAmount = 0",1000,1000,0,
|
|
6
|
+
B2C,免稅,0,含稅總額,0,SalesAmount,含稅,"TaxAmount = 0",1000,1000,0,土地/農產品等免稅項目
|
|
7
|
+
B2B,免稅,0,未稅總額,0,SalesAmount,未稅,"TaxAmount = 0",1000,1000,0,
|
|
8
|
+
B2C,混合,0.05,應稅+免稅銷售額,僅應稅部分稅額,SalesAmount + FreeTaxSalesAmount + TaxAmount,含稅,需分別填 SalesAmount 和 FreeTaxSalesAmount,1050,950,50,混合應稅與免稅商品
|
|
9
|
+
B2B,特種稅率,0.25,未稅總額,"SalesAmount * TaxRate",SalesAmount + TaxAmount,未稅,"InvType=08, TaxType=4",1250,1000,250,特種飲食業 25% 稅率
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
issue,symptom,cause,solution,provider,category,severity
|
|
2
|
+
B2B發票開立失敗,回傳錯誤代碼 6000015,ECPay測試環境B2B需預先註冊統編,使用B2C API加統編 或在正式環境測試,ECPay,開立,HIGH
|
|
3
|
+
金額驗算錯誤,AllAmount與商品小計不符,AllAmount使用了錯誤的來源欄位,B2C用SalesAmount B2B用TotalAmount: AllAmount=TotalAmount||SalesAmount,SmilePay,開立,HIGH
|
|
4
|
+
orderid格式錯誤,回傳-10084錯誤,訂單編號超過30字元限制,orderid限30字元 data_id可50字元防重複,SmilePay,開立,MEDIUM
|
|
5
|
+
列印發票空白,彈窗開啟但內容空白,SmilePay用GET但系統用POST提交,判斷method 若為GET則用redirect開啟URL,SmilePay,列印,MEDIUM
|
|
6
|
+
B2C列印需隨機碼,列印失敗或顯示錯誤,未儲存開立時回傳的randomNumber,開立成功後儲存randomNumber到invoiceRandomNum欄位,SmilePay,列印,HIGH
|
|
7
|
+
必填欄位遺漏,開立失敗 參數錯誤,FreeTaxSalesAmount ZeroTaxSalesAmount TaxRate等未填,即使為0也必須填入 TaxRate填"0.05",Amego,開立,HIGH
|
|
8
|
+
隨機碼未儲存,列印時出錯,未儲存開立時回傳的random_number,開立成功後儲存randomNumber欄位,Amego,列印,HIGH
|
|
9
|
+
B2B金額計算錯誤,稅額不正確,未正確區分含稅/未稅價格,使用DetailVat區分: B2B=0未稅 B2C=1含稅,Amego,開立,HIGH
|
|
10
|
+
列印錯誤服務商,查詢不到發票,用其他服務商的API查光貿開的發票,開立時儲存invoiceProvider 列印時優先使用,All,列印,HIGH
|
|
11
|
+
加密驗證失敗,TransCode非1或code=2,HashKey/HashIV錯誤或加密流程問題,確認加密流程: URL Encode→AES-128-CBC(ECPay) 或 MD5簽章(Amego),ECPay/Amego,認證,HIGH
|
|
12
|
+
時間戳逾時,10分鐘或60秒誤差,伺服器時間與本地時間不同步,使用API查詢伺服器時間 或同步本地時間,ECPay/Amego,認證,MEDIUM
|
|
13
|
+
載具與捐贈衝突,不可同時存在,同時設定載具和捐贈,二擇一: 有載具則捐贈=0 有捐贈則載具為空,All,開立,MEDIUM
|
|
14
|
+
B2B不可使用載具,統編發票不可用載具,打統編發票設定了載具,B2B發票移除載具設定,All,開立,MEDIUM
|
|
15
|
+
B2B不可捐贈,統編發票不可捐贈,打統編發票設定了捐贈,B2B發票設定Donation=0,All,開立,MEDIUM
|
|
16
|
+
發票已作廢,無法重複作廢,發票狀態已是作廢,檢查發票狀態後再操作,All,作廢,LOW
|
|
17
|
+
折讓超過發票金額,折讓金額大於原發票,折讓總額累計超過發票金額,計算剩餘可折讓金額,All,折讓,MEDIUM
|
|
Binary file
|