taiwan-payment-skill 1.0.2 → 1.0.3
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/assets/taiwan-payment/EXAMPLES.md +1425 -1425
- package/assets/taiwan-payment/SKILL.md +857 -857
- package/assets/taiwan-payment/references/ecpay-payment-api.md +880 -880
- package/assets/taiwan-payment/references/newebpay-payment-api.md +677 -677
- package/assets/taiwan-payment/references/payuni-payment-api.md +997 -997
- package/assets/templates/base/quick-reference.md +60 -345
- package/assets/templates/base/skill-content.md +248 -738
- package/assets/templates/platforms/agent.json +26 -0
- package/assets/templates/platforms/claude.json +26 -26
- package/assets/templates/platforms/codebuddy.json +25 -25
- package/assets/templates/platforms/codex.json +26 -25
- package/assets/templates/platforms/continue.json +25 -25
- package/assets/templates/platforms/copilot.json +25 -25
- package/assets/templates/platforms/cursor.json +26 -25
- package/assets/templates/platforms/gemini.json +25 -25
- package/assets/templates/platforms/kiro.json +25 -25
- package/assets/templates/platforms/opencode.json +25 -25
- package/assets/templates/platforms/qoder.json +25 -25
- package/assets/templates/platforms/roocode.json +25 -25
- package/assets/templates/platforms/trae.json +25 -25
- package/assets/templates/platforms/windsurf.json +25 -25
- package/dist/index.js +127 -29
- package/package.json +1 -1
|
@@ -1,370 +1,85 @@
|
|
|
1
|
-
|
|
1
|
+
## When to Apply
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Reference these guidelines when:
|
|
4
|
+
- Developing Taiwan E-Invoice issuance functionality
|
|
5
|
+
- Integrating ECPay, SmilePay, or Amego APIs
|
|
6
|
+
- Implementing B2C or B2B invoice logic
|
|
7
|
+
- Handling invoice printing, void, and allowance
|
|
8
|
+
- Troubleshooting invoice API integration issues
|
|
4
9
|
|
|
5
|
-
##
|
|
10
|
+
## Provider Quick Reference
|
|
6
11
|
|
|
7
|
-
|
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
| **最佳用途** | 高交易量電商 | 多元支付需求 | 新創 API 開發 |
|
|
12
|
+
| Priority | Task | Impact | Provider |
|
|
13
|
+
|----------|------|--------|----------|
|
|
14
|
+
| 1 | Amount Calculation | CRITICAL | All |
|
|
15
|
+
| 2 | Encryption/Signature | CRITICAL | All |
|
|
16
|
+
| 3 | B2B vs B2C Logic | HIGH | All |
|
|
17
|
+
| 4 | Print Response Handling | HIGH | All |
|
|
18
|
+
| 5 | Provider Binding | MEDIUM | All |
|
|
19
|
+
| 6 | Error Handling | MEDIUM | All |
|
|
20
|
+
| 7 | Carrier/Donation | LOW | B2C only |
|
|
17
21
|
|
|
18
|
-
##
|
|
22
|
+
## Quick Reference
|
|
19
23
|
|
|
20
|
-
###
|
|
24
|
+
### 1. Amount Calculation (CRITICAL)
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
- `b2c-tax-inclusive` - B2C uses tax-inclusive total
|
|
27
|
+
- `b2b-split-tax` - B2B requires pre-tax + tax split
|
|
28
|
+
- `round-tax` - Round tax: `Math.round(total - (total / 1.05))`
|
|
29
|
+
- `salesamount` - ECPay/Amego: Use SalesAmount for pre-tax
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
function generateECPayCheckMac(params: Record<string, any>, hashKey: string, hashIV: string): string {
|
|
27
|
-
const { CheckMacValue, ...cleanParams } = params
|
|
28
|
-
const sortedKeys = Object.keys(cleanParams).sort()
|
|
29
|
-
const paramString = sortedKeys.map(k => `${k}=${cleanParams[k]}`).join('&')
|
|
30
|
-
const rawString = `HashKey=${hashKey}&${paramString}&HashIV=${hashIV}`
|
|
31
|
-
const encoded = encodeURIComponent(rawString).toLowerCase()
|
|
32
|
-
return crypto.createHash('sha256').update(encoded).digest('hex').toUpperCase()
|
|
33
|
-
}
|
|
31
|
+
### 2. Encryption/Signature (CRITICAL)
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
MerchantTradeDate: new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14),
|
|
40
|
-
PaymentType: 'aio',
|
|
41
|
-
TotalAmount: 1000,
|
|
42
|
-
TradeDesc: '商品描述',
|
|
43
|
-
ItemName: '商品名稱',
|
|
44
|
-
ReturnURL: 'https://yourdomain.com/api/payment/callback',
|
|
45
|
-
ChoosePayment: 'Credit',
|
|
46
|
-
EncryptType: 1
|
|
47
|
-
}
|
|
48
|
-
orderParams.CheckMacValue = generateECPayCheckMac(orderParams, hashKey, hashIV)
|
|
33
|
+
- `ecpay-aes` - ECPay: AES-128-CBC with HashKey/HashIV
|
|
34
|
+
- `smilepay-verify` - SmilePay: Grvc + Verify_key params
|
|
35
|
+
- `amego-md5` - Amego: MD5(data + time + appKey)
|
|
36
|
+
- `url-encode` - Always URL encode before encryption
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
```
|
|
38
|
+
### 3. B2B vs B2C Logic (HIGH)
|
|
52
39
|
|
|
53
|
-
|
|
40
|
+
- `buyer-id-b2c` - B2C: BuyerIdentifier = "0000000000"
|
|
41
|
+
- `buyer-id-b2b` - B2B: BuyerIdentifier = actual 8-digit tax ID
|
|
42
|
+
- `no-carrier-b2b` - B2B: Cannot use carrier or donation
|
|
43
|
+
- `validate-taxid` - Validate 8-digit tax ID format
|
|
54
44
|
|
|
55
|
-
|
|
56
|
-
import crypto from 'crypto'
|
|
45
|
+
### 4. Print Response Handling (HIGH)
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
cipher.setAutoPadding(true)
|
|
63
|
-
let encrypted = cipher.update(queryString, 'utf8', 'hex')
|
|
64
|
-
encrypted += cipher.final('hex')
|
|
47
|
+
- `ecpay-html` - ECPay: Returns HTML, use window.document.write
|
|
48
|
+
- `smilepay-redirect` - SmilePay: Returns URL, use window.open
|
|
49
|
+
- `amego-pdf` - Amego: Returns PDF URL, use window.open
|
|
50
|
+
- `form-submit` - Some APIs require form POST submission
|
|
65
51
|
|
|
66
|
-
|
|
67
|
-
.createHash('sha256')
|
|
68
|
-
.update(`HashKey=${hashKey}&${encrypted}&HashIV=${hashIV}`)
|
|
69
|
-
.digest('hex')
|
|
70
|
-
.toUpperCase()
|
|
52
|
+
### 5. Provider Binding (MEDIUM)
|
|
71
53
|
|
|
72
|
-
|
|
73
|
-
|
|
54
|
+
- `save-provider` - Save invoiceProvider when issuing
|
|
55
|
+
- `save-random` - Save invoiceRandomNum for printing
|
|
56
|
+
- `match-provider` - Use issuing provider for print/void
|
|
74
57
|
|
|
75
|
-
|
|
76
|
-
const orderData = {
|
|
77
|
-
MerchantID: 'YOUR_MERCHANT_ID',
|
|
78
|
-
RespondType: 'JSON',
|
|
79
|
-
TimeStamp: Math.floor(Date.now() / 1000).toString(),
|
|
80
|
-
Version: '2.0',
|
|
81
|
-
MerchantOrderNo: 'ORD' + Date.now(),
|
|
82
|
-
Amt: 1000,
|
|
83
|
-
ItemDesc: '商品描述',
|
|
84
|
-
Email: 'customer@example.com',
|
|
85
|
-
NotifyURL: 'https://yourdomain.com/api/payment/callback',
|
|
86
|
-
ReturnURL: 'https://yourdomain.com/payment/result'
|
|
87
|
-
}
|
|
58
|
+
### 6. Error Handling (MEDIUM)
|
|
88
59
|
|
|
89
|
-
|
|
60
|
+
- `log-raw-response` - Log complete raw response for debugging
|
|
61
|
+
- `ecpay-codes` - ECPay: Check RtnCode and RtnMsg
|
|
62
|
+
- `smilepay-codes` - SmilePay: Check Status field
|
|
63
|
+
- `amego-codes` - Amego: Check Code and Message
|
|
90
64
|
|
|
91
|
-
|
|
92
|
-
// Body: MerchantID, TradeInfo, TradeSha, Version
|
|
93
|
-
```
|
|
65
|
+
### 7. Carrier/Donation (B2C only)
|
|
94
66
|
|
|
95
|
-
|
|
67
|
+
- `carrier-mobile` - Mobile barcode: /XXXXXXX format
|
|
68
|
+
- `carrier-npc` - Natural person certificate
|
|
69
|
+
- `donation-code` - Donation: 3-7 digit love code
|
|
70
|
+
- `mutual-exclusive` - Carrier and donation are mutually exclusive
|
|
96
71
|
|
|
97
|
-
|
|
98
|
-
import crypto from 'crypto'
|
|
72
|
+
## Test Credentials
|
|
99
73
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
encrypted += cipher.final('hex')
|
|
106
|
-
const authTag = cipher.getAuthTag().toString('hex')
|
|
107
|
-
const encryptInfo = encrypted + authTag
|
|
74
|
+
| Provider | Key Info |
|
|
75
|
+
|----------|----------|
|
|
76
|
+
| ECPay | MerchantID: 2000132, Stage URL |
|
|
77
|
+
| SmilePay | Grvc: SEI1000034, Test Tax ID: 80129529 |
|
|
78
|
+
| Amego | Tax ID: 12345678, test@amego.tw |
|
|
108
79
|
|
|
109
|
-
|
|
110
|
-
.createHash('sha256')
|
|
111
|
-
.update(`HashKey=${hashKey}&${encryptInfo}&HashIV=${hashIV}`)
|
|
112
|
-
.digest('hex')
|
|
113
|
-
.toUpperCase()
|
|
80
|
+
## How to Use
|
|
114
81
|
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// 2. 建立訂單參數
|
|
119
|
-
const orderData = {
|
|
120
|
-
MerchantID: 'YOUR_MERCHANT_ID',
|
|
121
|
-
MerchantTradeNo: 'ORD' + Date.now(),
|
|
122
|
-
MerchantTradeDate: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
|
123
|
-
TotalAmount: 1000,
|
|
124
|
-
TradeDesc: '商品描述',
|
|
125
|
-
ItemName: '商品名稱',
|
|
126
|
-
NotifyURL: 'https://yourdomain.com/api/payment/callback',
|
|
127
|
-
ReturnURL: 'https://yourdomain.com/payment/result'
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const encrypted = encryptPAYUNi(orderData, hashKey, hashIV)
|
|
131
|
-
|
|
132
|
-
// 3. POST 到 https://sandbox-api.payuni.com.tw/api/upp
|
|
133
|
-
// Body: MerchantID, EncryptInfo, HashInfo
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## 付款方式對照表
|
|
137
|
-
|
|
138
|
-
| 付款方式 | ECPay | NewebPay | PAYUNi | 備註 |
|
|
139
|
-
|---------|-------|----------|--------|------|
|
|
140
|
-
| 信用卡一次付清 | `Credit` | `CREDIT` | `credit` | 最常用 |
|
|
141
|
-
| 信用卡分期 | `Credit` + InstallmentFlag | `CREDIT` + InstFlag | `credit` + Installment | 需最低 1000 元 |
|
|
142
|
-
| 信用卡定期 | `Credit` + PeriodType | `CREDIT` + PeriodType | `credit` + Period | 訂閱制 |
|
|
143
|
-
| ATM 虛擬帳號 | `ATM` | `VACC=1` | `atm` | 1-3 天 |
|
|
144
|
-
| 網路 ATM | `WebATM` | `WEBATM=1` | `webatm` | 即時 |
|
|
145
|
-
| 超商代碼 | `CVS` | `CVS=1` | `cvs` | 30-20,000 |
|
|
146
|
-
| 超商條碼 | `BARCODE` | `BARCODE=1` | `barcode` | 20-40,000 |
|
|
147
|
-
| Apple Pay | `ApplePay` | `APPLEPAY=1` | `applepay` | 需申請 |
|
|
148
|
-
| Google Pay | `GooglePay` | `GOOGLEPAY=1` | `googlepay` | 需申請 |
|
|
149
|
-
| LINE Pay | `LINEPAY` | `LINEPAY=1` | ❌ | NewebPay 最佳 |
|
|
150
|
-
| 台灣 Pay | `TWQR` | `P2G=1` | `taiwanpay` | 最高 49,999 |
|
|
151
|
-
| BNPL 無卡分期 | `BNPL` | ❌ | ❌ | ECPay 獨家 |
|
|
152
|
-
| AFTEE 先享後付 | ❌ | ❌ | `aftee` | PAYUNi 獨家 |
|
|
153
|
-
|
|
154
|
-
## 錯誤碼快速查找
|
|
155
|
-
|
|
156
|
-
### ECPay 常見錯誤
|
|
157
|
-
|
|
158
|
-
| 錯誤碼 | 說明 | 解決方案 |
|
|
159
|
-
|-------|------|---------|
|
|
160
|
-
| `10100058` | CheckMacValue 錯誤 | 檢查參數排序、URL Encode |
|
|
161
|
-
| `10100003` | 訂單編號重複 | 使用唯一的 MerchantTradeNo |
|
|
162
|
-
| `10100047` | 金額不符 | 檢查 TotalAmount 是否正整數 |
|
|
163
|
-
| `10100073` | 商品名稱錯誤 | ItemName 不可為空 |
|
|
164
|
-
| `10200095` | 付款逾時 | 重新建立訂單 |
|
|
165
|
-
|
|
166
|
-
### NewebPay 常見錯誤
|
|
167
|
-
|
|
168
|
-
| 錯誤碼 | 說明 | 解決方案 |
|
|
169
|
-
|-------|------|---------|
|
|
170
|
-
| `TRA10001` | 交易失敗 | 檢查加密參數 |
|
|
171
|
-
| `TRA10002` | CheckValue 錯誤 | 檢查 TradeSha 計算 |
|
|
172
|
-
| `TRA10003` | 訂單不存在 | 檢查 MerchantOrderNo |
|
|
173
|
-
| `TRA10004` | 金額錯誤 | 檢查 Amt 是否正整數 |
|
|
174
|
-
| `TRA10005` | 商店代號錯誤 | 檢查 MerchantID |
|
|
175
|
-
|
|
176
|
-
### PAYUNi 常見錯誤
|
|
177
|
-
|
|
178
|
-
| 錯誤碼 | 說明 | 解決方案 |
|
|
179
|
-
|-------|------|---------|
|
|
180
|
-
| `ER0001` | 參數錯誤 | 檢查必填欄位 |
|
|
181
|
-
| `ER0002` | 簽章錯誤 | 檢查 HashInfo 計算 |
|
|
182
|
-
| `ER0003` | 訂單重複 | 使用唯一訂單號 |
|
|
183
|
-
| `ER0004` | 金額錯誤 | 檢查 TotalAmount |
|
|
184
|
-
| `ER0005` | 商店不存在 | 檢查 MerchantID |
|
|
185
|
-
|
|
186
|
-
## 測試資料快速複製
|
|
187
|
-
|
|
188
|
-
### ECPay 測試環境
|
|
189
|
-
```
|
|
190
|
-
MerchantID: 3002607
|
|
191
|
-
HashKey: pwFHCqoQZGmho4w6
|
|
192
|
-
HashIV: EkRm7iFT261dpevs
|
|
193
|
-
測試 URL: https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5
|
|
194
|
-
測試卡號: 4311-9522-2222-2222
|
|
195
|
-
有效期: 任意未來月年 (如 12/28)
|
|
196
|
-
CVV: 任意 3 碼 (如 123)
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### NewebPay 測試環境
|
|
200
|
-
```
|
|
201
|
-
測試 URL: https://ccore.newebpay.com/MPG/mpg_gateway
|
|
202
|
-
測試卡號: 4000-2211-1111-1111
|
|
203
|
-
有效期: 任意未來月年 (如 12/28)
|
|
204
|
-
CVV: 任意 3 碼 (如 123)
|
|
205
|
-
後台: https://cwww.newebpay.com/
|
|
206
|
-
注意: 需先申請測試帳號
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### PAYUNi 測試環境
|
|
210
|
-
```
|
|
211
|
-
測試 URL: https://sandbox-api.payuni.com.tw/api/upp
|
|
212
|
-
後台: https://sandbox.payuni.com.tw/
|
|
213
|
-
注意: 需先申請測試帳號
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## 欄位對照表
|
|
217
|
-
|
|
218
|
-
| 用途 | ECPay | NewebPay | PAYUNi |
|
|
219
|
-
|-----|-------|----------|--------|
|
|
220
|
-
| 商店代號 | `MerchantID` | `MerchantID` | `MerchantID` |
|
|
221
|
-
| 訂單編號 | `MerchantTradeNo` | `MerchantOrderNo` | `MerchantTradeNo` |
|
|
222
|
-
| 訂單日期 | `MerchantTradeDate` | `TimeStamp` | `MerchantTradeDate` |
|
|
223
|
-
| 訂單金額 | `TotalAmount` | `Amt` | `TotalAmount` |
|
|
224
|
-
| 商品名稱 | `ItemName` | `ItemDesc` | `ItemName` |
|
|
225
|
-
| 商品描述 | `TradeDesc` | `ItemDesc` | `TradeDesc` |
|
|
226
|
-
| 付款通知 URL | `ReturnURL` | `NotifyURL` | `NotifyURL` |
|
|
227
|
-
| 完成導向 URL | `OrderResultURL` | `ReturnURL` | `ReturnURL` |
|
|
228
|
-
| 付款方式 | `ChoosePayment` | 多個開關 | `PaymentType` |
|
|
229
|
-
| 簽章 | `CheckMacValue` | `TradeSha` | `HashInfo` |
|
|
230
|
-
| 加密資料 | - | `TradeInfo` | `EncryptInfo` |
|
|
231
|
-
|
|
232
|
-
## 回呼驗證範例
|
|
233
|
-
|
|
234
|
-
### ECPay 回呼驗證
|
|
235
|
-
```typescript
|
|
236
|
-
export async function POST(request: Request) {
|
|
237
|
-
const formData = await request.formData()
|
|
238
|
-
const params = Object.fromEntries(formData)
|
|
239
|
-
|
|
240
|
-
// 驗證簽章
|
|
241
|
-
const receivedMac = params.CheckMacValue
|
|
242
|
-
const calculatedMac = generateECPayCheckMac(params, hashKey, hashIV)
|
|
243
|
-
|
|
244
|
-
if (receivedMac !== calculatedMac) {
|
|
245
|
-
return new Response('0|CheckMacValue Error')
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// 更新訂單
|
|
249
|
-
// ...
|
|
250
|
-
|
|
251
|
-
return new Response('1|OK')
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### NewebPay 回呼驗證
|
|
256
|
-
```typescript
|
|
257
|
-
export async function POST(request: Request) {
|
|
258
|
-
const formData = await request.formData()
|
|
259
|
-
const tradeInfo = formData.get('TradeInfo') as string
|
|
260
|
-
const tradeSha = formData.get('TradeSha') as string
|
|
261
|
-
|
|
262
|
-
// 驗證 TradeSha
|
|
263
|
-
const calculatedSha = crypto
|
|
264
|
-
.createHash('sha256')
|
|
265
|
-
.update(`HashKey=${hashKey}&${tradeInfo}&HashIV=${hashIV}`)
|
|
266
|
-
.digest('hex')
|
|
267
|
-
.toUpperCase()
|
|
268
|
-
|
|
269
|
-
if (tradeSha !== calculatedSha) {
|
|
270
|
-
return Response.json({ Status: 'ERROR', Message: 'CheckValue Error' })
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// 解密 TradeInfo
|
|
274
|
-
const decrypted = decryptNewebPay(tradeInfo, hashKey, hashIV)
|
|
275
|
-
|
|
276
|
-
// 更新訂單
|
|
277
|
-
// ...
|
|
278
|
-
|
|
279
|
-
return Response.json({ Status: 'SUCCESS' })
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### PAYUNi 回呼驗證
|
|
284
|
-
```typescript
|
|
285
|
-
export async function POST(request: Request) {
|
|
286
|
-
const body = await request.json()
|
|
287
|
-
const { EncryptInfo, HashInfo } = body
|
|
288
|
-
|
|
289
|
-
// 驗證 HashInfo
|
|
290
|
-
const calculatedHash = crypto
|
|
291
|
-
.createHash('sha256')
|
|
292
|
-
.update(`HashKey=${hashKey}&${EncryptInfo}&HashIV=${hashIV}`)
|
|
293
|
-
.digest('hex')
|
|
294
|
-
.toUpperCase()
|
|
295
|
-
|
|
296
|
-
if (HashInfo !== calculatedHash) {
|
|
297
|
-
return Response.json({ Status: 'ERROR', Message: 'Hash Error' })
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// 解密 EncryptInfo
|
|
301
|
-
const decrypted = decryptPAYUNi(EncryptInfo, hashKey, hashIV)
|
|
302
|
-
|
|
303
|
-
// 更新訂單
|
|
304
|
-
// ...
|
|
305
|
-
|
|
306
|
-
return Response.json({ Status: 'SUCCESS' })
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
## 智能工具快速使用
|
|
311
|
-
|
|
312
|
-
```bash
|
|
313
|
-
# 搜索錯誤碼
|
|
314
|
-
python scripts/search.py "10100058" --domain error
|
|
315
|
-
|
|
316
|
-
# 推薦服務商
|
|
317
|
-
python scripts/recommend.py "電商 高交易量"
|
|
318
|
-
|
|
319
|
-
# 測試連線
|
|
320
|
-
python scripts/test_payment.py ecpay
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
## 前端表單提交範例
|
|
324
|
-
|
|
325
|
-
```typescript
|
|
326
|
-
// 通用表單提交函數
|
|
327
|
-
function submitPaymentForm(action: string, params: Record<string, string>) {
|
|
328
|
-
const form = document.createElement('form')
|
|
329
|
-
form.method = 'POST'
|
|
330
|
-
form.action = action
|
|
331
|
-
form.target = '_self'
|
|
332
|
-
|
|
333
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
334
|
-
const input = document.createElement('input')
|
|
335
|
-
input.type = 'hidden'
|
|
336
|
-
input.name = key
|
|
337
|
-
input.value = value
|
|
338
|
-
form.appendChild(input)
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
document.body.appendChild(form)
|
|
342
|
-
form.submit()
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// ECPay 使用
|
|
346
|
-
submitPaymentForm('https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5', orderParams)
|
|
347
|
-
|
|
348
|
-
// NewebPay 使用
|
|
349
|
-
submitPaymentForm('https://ccore.newebpay.com/MPG/mpg_gateway', {
|
|
350
|
-
MerchantID: merchantID,
|
|
351
|
-
TradeInfo: encrypted.TradeInfo,
|
|
352
|
-
TradeSha: encrypted.TradeSha,
|
|
353
|
-
Version: '2.0'
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
// PAYUNi 使用 (JSON POST,不用表單)
|
|
357
|
-
fetch('https://sandbox-api.payuni.com.tw/api/upp', {
|
|
358
|
-
method: 'POST',
|
|
359
|
-
headers: { 'Content-Type': 'application/json' },
|
|
360
|
-
body: JSON.stringify({
|
|
361
|
-
MerchantID: merchantID,
|
|
362
|
-
EncryptInfo: encrypted.EncryptInfo,
|
|
363
|
-
HashInfo: encrypted.HashInfo
|
|
364
|
-
})
|
|
365
|
-
})
|
|
366
|
-
```
|
|
82
|
+
See the full skill documentation for detailed API references and code examples.
|
|
367
83
|
|
|
368
84
|
---
|
|
369
85
|
|
|
370
|
-
最後更新:2026/01/29
|