-
Notifications
You must be signed in to change notification settings - Fork 6
API Document
node-ecpay-aio (NEA) 是綠界全方位金流(AIO)的 Node.js SDK。NEA 是根據綠界官方 API 規格書的全新實作並且支援 TypeScript,它並非官方 SDK 的 fork 改寫版本。
因綠界主要使用者皆在台灣,故 NEA 文件皆以中文書寫。
npm install --save node-ecpay-aio
-
Merchant Class: new Merchant() / .createPayment() / .createQuery() / .createAction()
-
Payment Class: .checkout() / .placeOrder()
-
Query Class: .read()
-
Action Class: .execute()
-
Error Classes: ValidationError / PlaceOrderError / QueryError / ActionError / CheckMacValueError
-
Utilities: isValidReceivedCheckMacValue / getCurrentTaipeiTimeString
Step 1 | Step 2 | Step 3
+------------+
.createPayment() | |--> await payment.checkout()
+---------------------->| payment |
| | |--> await payment.placeOrder()
| +------------+
|
+------------+ +------------+
| | .createQuery() | |
new Merchant() --->| merchant |---------------->| query |--> await query.read()
| | | |
+------------+ +------------+
|
| +------------+
| | |
+---------------------->| action |--> await action.execute()
.createAction() | |
+------------+
-
Step 1: 建立特店(
merchant
) -
Step 2: 可以再用特店建立
- 付款方式:
payment
- 查詢:
query
- 操作:
action
- 付款方式:
-
Step 3:
- payment 可以執行結帳
- 如果是立即付款
- 一定要取得在前端重導向至綠界結帳頁面的 html:
const html = await payment.checkout()
- 一定要取得在前端重導向至綠界結帳頁面的 html:
- 如果是延遲付款
- 可以取得在前端重導向至綠界結帳頁面的 html:
const html = await payment.checkout()
- 也可直接於後端請求建立綠界訂單:
const paymentInfo = await payment.placeOrder()
- 可以取得在前端重導向至綠界結帳頁面的 html:
- 如果是立即付款
- query 可以執行讀取:
const data = await query.read()
- action 可以執行操作:
const result = await action.execute()
- payment 可以執行結帳
如何閱讀本文件
- 建議先稍微讀過官方的 API 手冊。
- 參數物件會以 必填 與 選填 兩部份區隔開。
- 因參數眾多,僅在需要之處以註解稍加說明。若對某參數不了解,請直接參考官方 API 手冊。
- 參數命名一律按官方的大寫駝峰式(Pascal Case)書寫。
- 參數 Schema 或參數間的相依條件已有防衛性驗證,違反規則即會拋錯,故 NEA 文件不會特別說明這些限制。
- 參數型別是嚴格的,字串就是字串,數字就是數字。官方的 SDK 會自動將字串轉數字,但 NEA 不會,因為這會造成型別混淆。你心裡只要記住幾乎 99% 的參數都是字串,僅有部分涉及「金額」、「次數」、「天數」的地方才會有數字出現。
- 關於可用參數及其型別、選項,TypeScript 會協助你。不過,到底要用 TS 還是 JS 來寫,由你自行決定。
- 空值與 undefined 不同。在官方手冊中提到的「空值」在 NEA 中一律是指空字串
''
而不是null
或undefined
。在 NEA,只要是undefined
的參數,皆不會編入 x-www-form-urlencoded 的鍵值對字串中。如果你想要將屬性編入 post 字串,請給予該屬性空字串''
,而非給予undefined
。綠界的請求參數並不使用null
,故請勿使用null
表示空值。
代表綠界特店的 Class,它的實例帶有工廠方法 createPayment()
、createQuery()
以及 createAction()
可以產生特店的結帳、資料查詢與信用卡作業操作。特店是指「提供綠界金流付款服務給消費者付款交易的賣家系統」,一般來講也就是你的後端系統。
Syntax:
import { Merchant } from 'node-ecpay-aio';
建立綠界特店的實例。建立時需給予組態 config
用來設定你的特店資訊。Merchant 的實例帶有工廠方法 createPayment()
、createQuery()
以及 createAction()
。
Syntax:
new Merchant(mode, config[, ecpayServiceUrls])
Arguments:
-
mode
(String):'Test' | 'Production'
,各表示特店要使用綠界的測試環境或生產環境 API。 -
config
(Object): 特店的組態參數如下{ // 必填 MerchantID: '2000132', HashKey: '5294y06JbISpM5x9', HashIV: 'v77hoKGq4kWxNNIS', ReturnURL: 'https://yourservice.com/foo/bar', // 選填 PlatformID: '', // 只有平台商需填此編號, 我們大部分都不是 PeriodReturnURL: 'https://...', OrderResultURL: 'https://...' , ClientBackURL: 'https://...', PaymentInfoURL: 'https://...', ClientRedirectURL: 'https://...' }
-
ecpayServiceUrls
(Object, optional): 改寫或新增綠界 API 的服務端點資料,一般不會用到此參數。為節省說明版面,此處暫省略說明。
Returns:
- (Object): merchant 實例
Errors:
- (ValidationError):
ValidationError
實例
Examples:
import { Merchant } from 'node-ecpay-aio';
const merchant = new Merchant('Test', {
MerchantID: '2000132',
HashKey: '5294y06JbISpM5x9',
HashIV: 'v77hoKGq4kWxNNIS',
ReturnURL: 'https://api.test.com/our/hook1',
PaymentInfoURL: 'https://api.test.com/our/hook2',
});
建立付款方式的工廠方法。建立時請注入要使用的 PaymentClass,並準備好每一種付款方式都要填寫的基本參數 baseParams
,以及屬於個別付款方式的專屬參數 params
。
Syntax:
merchant.createPayment(PaymentClass, baseParams[, params]);
注意
建議不要省略
params
,即使你並未使用params
中的任何屬性,請令其為空物件{}
而非undefined
,保持一致的呼叫風格。
Arguments:
-
PaymentClass
(Class): 各種付款方式的 Class,包含有-
CreditOneTimePayment
: 信用卡一次付清 -
CreditDividePayment
: 信用卡分期付款 -
CreditPeriodPayment
: 信用卡定期定額 (訂閱式收費) -
WebATMPayment
: WebATM 付款 -
ATMPayment
: ATM 付款 -
CVSPayment
: 超商代碼付款 -
BARCODEPayment
: 超商條碼付款 -
AndroidPayPayment
: Google Pay 付款。綠界 AIO 目前暫時停止此服務,目前產生AndroidPayPayment
時會拋錯
-
-
baseParams
(Object): 所有付款方式都需要填的基本參數{ // 必填 MerchantTradeNo: 'NEA12345678', // 廠商自己的訂單編號, 只接受大小寫英數字組合, min: 4, max: 20 MerchantTradeDate: '2022/04/25 18:26:12', TotalAmount: 500, TradeDesc: '交易描述', ItemName: '商品名稱', // 以下選填 Remark: '備註', NeedExtraPaidInfo: 'Y', // 'N': 不要, 'Y': 要 StoreID: '', ItemURL: 'https://...', CustomField1: '自訂欄位1', CustomField2: '自訂欄位2', CustomField3: '自訂欄位3', CustomField4: '自訂欄位4', ReturnURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook ClientBackURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的返回網址 OrderResultURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要顯示個別的付款結果網址 }
-
params
(Object): 根據不同的 PaymentClass 付款方式,各自需要的獨特參數。分述於下方各種付款方式範例。
Returns:
- (Object): payment 實例
Errors:
- (ValidationError):
ValidationError
實例
Examples:
-
付款模式: 立即付款(須導向綠界結帳頁)
-
付款類別:
CreditOneTimePayment
import { Merchant, CreditOneTimePayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { MerchantTradeNo: 'NEA12345678', MerchantTradeDate: '2021/04/17 10:55:26', TotalAmount: 1000, TradeDesc: '交易描述', ItemName: '商品名稱', // ReturnURL: undefined, // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook // ClientBackURL: undefined, // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的轉導網址 // OrderResultURL: undefined, // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的轉導網址 }; const params: CreditOneTimePaymentParams = { // 皆為選填 BindingCard: 1, // 記憶信用卡: 1 (記) | 0 (不記) MerchantMemberID: '2000132u001', // 記憶卡片需加註識別碼: MerchantId+廠商會員編號 Language: 'ENG', // 語系: undefined(繁中) | 'ENG' | 'KOR' | 'JPN' | 'CHI' Redeem: 'Y', // 紅利折抵: undefined(不用) | 'Y' (使用) UnionPay: 2, // [需申請] 銀聯卡: 0 (可用, default) | 1 (導至銀聯網) | 2 (不可用) }; const payment = merchant.createPayment( CreditOneTimePayment, baseParams, params ); const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */);
-
付款模式: 立即付款(須導向綠界結帳頁)
-
付款類別:
CreditDividePayment
import { Merchant, CreditDividePayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: CreditDividePaymentParams = { // 必填 CreditInstallment: '3', // 分期數: '3' | '6' | '12' | '18' | '24' | '30N'(圓夢彈性分期) // 選填 BindingCard: 0, MerchantMemberID: undefined, // 寫 undefined 只是表示有此參數可設定, 實際上不賦值就不用寫此屬性 Language: undefined, // 同上 Redeem: undefined, // 同上 UnionPay: undefined, // 同上 }; const payment = merchant.createPayment( CreditDividePayment, baseParams, params ); const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */);
-
付款模式: 立即付款(須導向綠界結帳頁)
-
付款類別:
CreditPeriodPayment
import { Merchant, CreditPeriodPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: CreditPeriodPaymentParams = { // 必填 PeriodAmount: 500, // 週期授權金額, 須與 baseParams.TotalAmount 相等, 否則拋錯 PeriodType: 'M', // 'D'(日) | 'M'(月) | 'Y'(年) Frequency: 1, // 多久執行一次, min: 1, max: 365(天) | 12(月) | 1(年) ExecTimes: 10, // 執行次數, min: 1, max: 999(天) | 99(月) | 9(年) // 選填 BindingCard: 0, MerchantMemberID: undefined, Language: undefined, Redeem: undefined, UnionPay: 2, PeriodReturnURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook }; const payment = merchant.createPayment( CreditPeriodPayment, baseParams, params ); const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */);
-
付款模式: 立即付款(須導向綠界結帳頁)
-
付款類別:
WebATMPayment
import { Merchant, WebATMPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: WebATMPaymentParams = { /* 無參數, 請保持空物件*/ }; const payment = merchant.createPayment(WebATMPayment, baseParams, params); const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */);
-
付款模式: 延遲付款(可選擇是否導向綠界結帳頁)
-
付款類別:
ATMPayment
import { Merchant, ATMPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: ATMPaymentParams = { // 皆選填 ExpireDate: 7, PaymentInfoURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook ClientRedirectURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook }; const payment = merchant.createPayment(ATMPayment, baseParams, params); // pick one // (1) 取得前端瀏覽器重新導向的 Post Form const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */); // 或 (2) 於後端直接建立訂單, paymentInfo 為取號結果 const paymentInfo = await payment.placeOrder(/* 可選填發票 */);
-
付款模式: 延遲付款(可選擇是否導向綠界結帳頁)
-
付款類別:
CVSPayment
import { Merchant, CVSPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: CVSPaymentParams = { // 皆選填 StoreExpireDate: 7, Desc_1: 'POS 機顯示條目 1', Desc_2: 'POS 機顯示條目 2', Desc_3: 'POS 機顯示條目 3', Desc_4: 'POS 機顯示條目 4', PaymentInfoURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook ClientRedirectURL: 'https://...', // 若在 merchant 設定過, 此處不需再設定, 除非你針對此單要用個別的 hook }; const payment = merchant.createPayment(CVSPayment, baseParams, params); // pick one // (1) 取得前端瀏覽器重新導向的 Post Form const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */); // 或 (2) 於後端直接建立訂單, paymentInfo 為取號結果 const paymentInfo = await payment.placeOrder(/* 可選填發票 */);
-
付款模式: 延遲付款(可選擇是否導向綠界結帳頁)
-
付款類別:
BARCODEPayment
import { Merchant, BARCODEPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: BARCODEPaymentParams = { // 皆為可選 StoreExpireDate: 7, PaymentInfoURL: 'https://...', // 不必特別設定, 因未設定會自動吃 merchant config 的值 ClientRedirectURL: 'https://...', // 不必特別設定, 因未設定會自動吃 merchant config 的值 Desc_1: 'POS 機顯示條目 1', Desc_2: 'POS 機顯示條目 2', Desc_3: 'POS 機顯示條目 3', Desc_4: 'POS 機顯示條目 4', }; const payment = merchant.createPayment(BARCODEPayment, baseParams, params); // pick one // (1) 取得前端瀏覽器重新導向的 Post Form const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */); // 或 (2) 於後端直接建立訂單, paymentInfo 為取號結果 const paymentInfo = await payment.placeOrder(/* 可選填發票 */);
-
付款模式: 立即付款(AIO 目前已停止本服務)
-
付款類別:
AndroidPayPayment
import { Merchant, AndroidPayPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: AndroidPayPaymentParams = { /* 綠界當前不提供此服務, 無參數, 請保持空物件 */ }; const payment = merchant.createPayment(AndroidPayPayment, baseParams, params); const htmlRedirectPostForm = await payment.checkout(/* 可選填發票 */);
-
付款模式: 立即付款/延遲付款(須導向綠界結帳頁;不支援
placeOrder()
) -
付款類別:
ALLPayment
import { Merchant, ALLPayment } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const baseParams: BasePaymentParams = { /* 略 */ }; const params: ALLPaymentParams = { // 選填 IgnorePayment: ['WebATM', 'ATM'], // 陣列可填 'Credit', 'WebATM', 'ATM', 'CVS', 'BARCODE', 'AndroidPay' // 表示不提供這些付款方式給消費者選擇 // 其餘參數: 根據可用的付款方式, 將所有 params 結合起來在此設定 // 個別設定請參考前述 1~8 之設定 BindingCard: 0, MerchantMemberID: undefined, Language: undefined, Redeem: undefined, UnionPay: 2, // ... 略 }; const payment = merchant.createPayment(ALLPayment, baseParams, params); const htmlRedirectPostForm = await payment.checkout();
建立交易資料查詢的工廠方法。建立時請注入要使用的 QueryClass,並準備好每一種查詢要填寫的參數 params
。建立的 QueryClass 實例具有 .read()
的非同步方法可以向綠界服務發起查詢請求。查詢結果的響應格式請見 Query Class: 5.1 .read() API 說明。Query 是冪等操作。
Syntax:
merchant.createQuery(QueryClass, params);
注意
建議不要省略
params
,即使你並未使用params
中的任何屬性,請令其為空物件{}
而非undefined
。
Arguments:
-
QueryClass
(Class): 各種查詢的 Class,包含有-
TradeInfoQuery
: 訂單資料查詢 -
PaymentInfoQuery
: ATM/CVS/BARCODE 取號結果查詢 -
CreditCardPeriodInfoQuery
: 信用卡定期定額訂單查詢 -
TradeV2Query
: 查詢信用卡單筆明細紀錄 -
TradeNoAioQuery
: 下載特店對帳媒體檔 -
FundingReconDetail
: 下載信用卡撥款對帳資料檔
-
-
params
(Object): 根據不同的 QueryClass 查詢方式,各自所需的獨特參數。分述於下方各種查詢範例。
Returns:
- (Object): Query 實例
Errors:
- (ValidationError):
ValidationError
實例
Examples:
-
查詢類別:
TradeInfoQuery
import { Merchant, TradeInfoQuery } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(TradeInfoQuery, { MerchantTradeNo: 'NEA12345678', }); const data = await query.read();
-
查詢類別:
PaymentInfoQuery
-
注意: 無法查詢「信用卡」、「ATM」立即付款的資訊(
PaymentInfoQuery
只適用查詢延遲付款訂單)import { Merchant, PaymentInfoQuery } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(PaymentInfoQuery, { MerchantTradeNo: 'NEA12345678', }); const data = await query.read();
-
查詢類別:
CreditCardPeriodInfoQuery
-
注意: 無法查詢信用卡「一次付清」、「分期」付款資訊
import { Merchant, CreditCardPeriodInfoQuery } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(CreditCardPeriodInfoQuery, { MerchantTradeNo: 'NEA12345678', }); const data = await query.read();
-
查詢類別:
TradeV2Query
import { Merchant, TradeV2Query } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(TradeV2Query, { CreditRefundId: 10123456, // baseParams.NeedExtraPaidInfo = 'Y' 時取得詳情中的 gwsr 值即是此 Id CreditAmount: 500, CreditCheckCode: 59997889, // 商家檢查碼, 後台 > 信用卡收單 > 信用卡授權資訊可查到 }); const data = await query.read();
-
查詢類別:
TradeNoAioQuery
import { Merchant, TradeNoAioQuery } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(TradeNoAioQuery, { // 必填 DateType: '2', // '2'(付款日) | '4'(撥款日) | '6'(訂單日) BeginDate: '2022-04-25', EndDate: '2022-04-26', MediaFormated: '1', // '0'(舊格式) | '1'(新格式) // 選填 PaymentType: '01', // '01'(信用卡) | '02'(WebATM) | '03'(ATM) | '04'(CVS) | // '05'(BARCODE) | '10'(全家立即儲) | '11'(圓夢彈性分期); PlatformStatus: undefined, // undefined(全部) | '1'(一般) | '2'(平台) PaymentStatus: '0', // undefined(全部) | '0'(未付款) | '1'(已付款) | '2'(訂單失敗) AllocateStatus: undefined, // undefined(全部) | '0'(未撥款) | '1'(已撥款) CharSet: '1', // undefeind(Server預設) | '1'(Big5) | '2'(utf8); }); const data = await query.read(); // csv檔
-
Response data: 純文字 (.csv 檔)
-
查詢類別:
FundingReconDetail
import { Merchant, FundingReconDetail } from 'node-ecpay-aio'; const merchant = new Merchant('Test', { /* 略 */ }); const query = merchant.createQuery(FundingReconDetail, { // 必填 PayDateType: 'fund', // 'fund'(依結算日) | 'close'(依關帳日) | 'enter'(依撥款日) StartDate: '2022-04-25', EndDate: '2022-04-26', MediaFormated: '1', // '0'(舊格式) | '1'(新格式) // 選填 CharSet: '1', // undefeind(Server預設) | '1'(Big5) | '2'(utf8); }); const data = await query.read(); // csv檔
-
Response data: 純文字 (.csv 檔)
建立操作的工廠方法。建立時請注入要使用的 ActionClass,並準備好每一種操作要填寫的參數 params
。建立的 ActionClass 實例具有 .execute()
的非同步方法可以向綠界服務發起遠端操作請求。操作結果的響應格式請見 Action Class: 6.1 .execute() API 說明。Action 是非冪等操作。
Syntax:
merchant.createAction(ActionClass, params);
注意
建議不要省略
params
,即使你並未使用params
中的任何屬性,請令其為空物件{}
而非undefined
。
Arguments:
-
ActionClass
(Class): 各種操作的 Class,包含有-
DoAction
: 信用卡請退款作業 -
CreditCardPeriodAction
: 信用卡定期定額訂單作業
-
-
params
(Object): 根據不同的 Action Class 操作方式,各自所需的獨特參數。分述於下方各種操作範例。
Returns:
- (Object): action 實例
Errors:
- (ValidationError):
ValidationError
實例
Examples:
-
操作類別:
DoAction
const action = merchant.createAction(DoAction, { // 皆為必填 MerchantTradeNo: 'NEA12345678', TradeNo: '8811223388121'. Action: 'C' , // 'C'(關帳) | 'R'(退刷) | 'E'(取消) | 'N'(放棄) TotalAmount: 500 }); const result = await action.execute();
-
響應資料格式請見 6.1 excute() 說明。
-
操作類別:
CreditCardPeriodAction
const action = merchant.createAction(CreditCardPeriodAction, { // 皆為必填 MerchantTradeNo: 'NEA12345678', Action: 'ReAuth', // 'ReAuth' | 'Cancel'; }); const result = await action.execute();
-
響應資料格式請見 6.1 excute() 說明。
Payment Classes 分類如下:
-
立即付款類
-
CreditOneTimePayment
: 信用卡一次付清 -
CreditDividePayment
: 信用卡分期付款 -
CreditPeriodPayment
: 信用卡定期定額 (訂閱式收費) -
WebATMPayment
: WebATM 付款 -
AndroidPayPaymen
: Google Pay 付款。綠界目前暫時停止此服務,目前產生 AndroidPayPayment 時會自動 throw Error。
-
-
延遲付款類
-
ATMPayment
: ATM 付款 -
CVSPayment
: 超商代碼付款 -
BARCODEPayment
: 超商條碼付款
-
所有的 Payment Classes 都有 .checkout()
的結帳方法。
如果需要開立電子發票,請於結帳時帶入發票參數 chekcout(invoice)
。如不開立發票,直接執行checkout()
即可。關於帶入的發票請見 9. 發票格式 說明。
Syntax:
payment.checkout([invoice]);
Arguments:
-
invoice
(Object, optional): 發票參數。結帳時填入可一併開立電子發票。
Returns:
- (String): 傳給前端重導向至綠界結帳頁的 Post Form
Errors:
- (ValidationError):
ValidationError
實例
Examples:
-
const htmlRedirectPostForm = await payment.checkout();
-
Result (htmlRedirectPostForm)
<form id="_form_aio_checkout" action="https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5" method="post" > <input type="hidden" name="CheckMacValue" id="CheckMacValue" value="2C6E582088B63CE828D27CE7E89FE0BA840F2599F10002A6AC0213DFD147C116" />...略...<input type="hidden" name="TradeDesc" id="TradeDesc" value="node-ecpay-aio testing order for CreditOneTimePayment" /> <script type="text/javascript"> document.getElementById('_form_aio_checkout').submit(); </script> </form>
-
-
const invoice: InvoiceParams = { RelateNumber: 'foo-rl-no', TaxType: '1', Donation: '0', Print: '0', InvoiceItemName: 'item1|item2', InvoiceItemCount: '2|5', InvoiceItemWord: '台|張', InvoiceItemPrice: '100|50', InvoiceRemark: '測試發票備註', CustomerPhone: '0911111111', }; const htmlRedirectPostForm = await payment.checkout(invoice);
-
Result (htmlRedirectPostForm)
<form id="_form_aio_checkout" action="https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5" method="post" > <input type="hidden" name="CarruerType" id="CarruerType" value="" /><input type="hidden" name="CheckMacValue" id="CheckMacValue" value="3185EDD19B600CA2780AD3DE387DB09434A84AE0BE37B64EB36C428D3BA40264" />...略...<input type="hidden" name="TotalAmount" id="TotalAmount" value="999" /><input type="hidden" name="TradeDesc" id="TradeDesc" value="node-ecpay-aio testing order for CreditOneTimePayment" /> <script type="text/javascript"> document.getElementById('_form_aio_checkout').submit(); </script> </form>
-
只有延遲付款的 Payment Classes 才有 .placeOrder()
方法。 如果需要開立電子發票,請於結帳時帶入發票參數placeOrder(invoice)
。如不開立發票,直接執行placeOrder()
即可。
Syntax:
payment.placeOrder([invoice]);
Arguments:
-
invoice
(Object, optional): 發票參數。結帳時填入可一併開立電子發票。
Returns:
- (Object): 延遲付款訂單的取號結果。
- ATM
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'NEA12345678', CustomField1: '', CustomField2: '', CustomField3: 'N22042600020', CustomField4: 'ATM', TradeNo: '2204261421418645', TradeDate: '2022/04/26 14:21:51', TradeAmt: 409, PaymentType: 'ATM_LAND', ExpireDate: '2022/04/29', BankCode: '005', vAccount: '5219111913209840', RtnCode: 2, RtnMsg: 'Get VirtualAccount Succeeded', }
- 超商代碼 (CVS)
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '7c80cdef716c4a2998d', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261439048696', TradeDate: '2022/04/26 14:39:30', TradeAmt: 200, PaymentType: 'CVS_CVS', ExpireDate: '2022/05/03 14:39:30', PaymentNo: 'LLL22116735498', PaymentURL: 'https://payment-stage.ecpay.com.tw/PaymentRule/CVSBarCode?PaymentNo=LLL22116735498', RtnCode: 10100073, RtnMsg: 'Get CVS Code Succeeded.', }
- 超商條碼 (BARCODE)
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'CK20220426401292', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261401048597', TradeDate: '2022/04/26 14:02:17', TradeAmt: 1500, PaymentType: 'BARCODE_BARCODE', ExpireDate: '2022/05/03 14:39:30', Barcode1: '1105036EA', Barcode2: '3453011539919569', Barcode3: '042677000001500', RtnCode: 10100073, RtnMsg: 'Get CVS Code Succeeded.', }
- ATM
Errors:
- (PlaceOrderError):
PlaceOrderError
實例 - (CheckMacValueError):
CheckMacValueError
實例
Examples:
-
const info = await payment.placeOrder();
-
const invoice: InvoiceParams = { RelateNumber: 'foo-rl-no', TaxType: '1', Donation: '0', Print: '0', InvoiceItemName: 'item1|item2', InvoiceItemCount: '2|5', InvoiceItemWord: '台|張', InvoiceItemPrice: '100|50', InvoiceRemark: '測試發票備註', CustomerPhone: '0911111111', }; const info = await payment.placeOrder(invoice);
交易資料查詢的 Query Classes,包含有:
-
TradeInfoQuery
: 訂單資料查詢 -
PaymentInfoQuery
: ATM/CVS/BARCODE 取號結果查詢 -
CreditCardPeriodInfoQuery
: 信用卡定期定額訂單查詢 -
TradeV2Query
: 查詢信用卡單筆明細紀錄 -
TradeNoAioQuery
: 下載特店對帳媒體檔 -
FundingReconDetail
: 下載信用卡撥款對帳資料檔
每個 QueryClass 實例具有 .read()
的非同步方法可以向綠界服務發起查詢請求,響應格式如下所列。
所有的 Query Classes 都有 .read()
的非同步讀取查詢資料方法。
Syntax:
query.read();
Arguments:
- none
Returns:
- (Promise): promise
Errors:
- (QueryError):
QueryError
實例 - (CheckMacValueError):
CheckMacValueError
實例
Examples:
import { Merchant, TradeInfoQuery } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(TradeInfoQuery, {
MerchantTradeNo: 'NEA12345678',
});
const data = await query.read(); // 響應格式列如下方
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'NEA12345678', ItemName: '手機/平板 鋁合金桌面支架 | 人體工 學追劇必備#', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261428508660', TradeDate: '2022/04/26 14:28:50', TradeAmt: 1440, TradeStatus: '1', HandlingCharge: 29, PaymentDate: '2022/04/26 14:29:15', PaymentType: 'Credit_CreditCard', PaymentTypeChargeFee: 29, // 以下欄位只有當結帳時 baseParams.NeedExtraPaidInfo 設 'Y' 才有 // 故不一定會在響應資料中出現 // 以下欄位和信用卡交易方式有關 process_date: '2022/04/27 17:19:44', amount: 1440, auth_code: '777777', gwsr: 11718189, eci: 0, card4no: '2222', card6no: '431195', // 以下欄位和此交易方式無關 ATMAccBank: '', ATMAccNo: '', WebATMBankName: '', WebATMAccBank: '', WebATMAccNo: '', PayFrom: '', PaymentNo: '', red_dan: '', red_de_amt: '', red_ok_amt: '', red_yet: '', staed: '', stage: '', stast: '', // 以下官方已棄用 AlipayID: '', AlipayTradeNo: '', TenpayTradeNo: '', }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '20211026001969730', ItemName: '鋁合金桌面支架', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2110261713558708', TradeDate: '2021/10/26 17:13:55', TradeAmt: 200, TradeStatus: '1', HandlingCharge: 5, PaymentDate: '2021/10/26 17:14:27', PaymentType: 'Credit_CreditCard', PaymentTypeChargeFee: 5, PeriodType: 'D', Frequency: 91, ExecTimes: 999, TotalSuccessTimes: 3, PeriodAmount: 200, TotalSuccessAmount: 600, // 以下欄位和信用卡交易方式有關 process_date: '2021/10/26 17:14:27', amount: 200, auth_code: '777777', gwsr: 11718189, card4no: '2222', card6no: '431195', eci: '', // 當非數字時,保持空值(空字串) // 其餘欄位和此交易方式無關, 也不一定會出現 // 所有欄位請參考上方完整的 response data 格式 // ...略 }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '20220426133333', ItemName: '湊町十六-打go嚴選-【黑水】雙鬥茶 200 元 x 2#運費 137 元 x 1', CustomField1: '商家統一編號:83269087', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261333378539', TradeDate: '2022/04/26 13:33:37', TradeAmt: '537', TradeStatus: '1', HandlingCharge: '10', PaymentDate: '2022/04/26 13:33:45', PaymentType: 'WebATM_TAISHIN', PaymentTypeChargeFee: '10', WebATMBankName: '', WebATMAccBank: '812', WebATMAccNo: '15646', // 其餘欄位和此交易方式無關, 也不一定會出現 // 所有欄位請參考上方完整的 response data 格式 // ...略 }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'N22042600020513', ItemName: '日本金鳥-吊掛式蚊香盤一般尺寸 173 元 X1#雙龍牌 日式兒童前開式雨衣-XS/S/M/L 136 元 X1', CustomField1: '', CustomField2: '', CustomField3: 'N22042600020', CustomField4: 'ATM', TradeNo: '2204261421418645', TradeDate: '2022/04/26 14:21:41', TradeAmt: 409, TradeStatus: '0', HandlingCharge: '10', PaymentDate: '', PaymentType: 'ATM_LAND', PaymentTypeChargeFee: 10, ATMAccBank: '', ATMAccNo: '', // 其餘欄位和此交易方式無關, 也不一定會出現 // 所有欄位請參考上方完整的 response data 格式 // ...略 }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '2204220310222', ItemName: '顥陽蘭坊 5000 TWD x 1', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261439048696', TradeDate: '2022/04/26 14:39:04', TradeAmt: 200, TradeStatus: '1', HandlingCharge: '0', PaymentNo: 'LLL22112732600', PaymentDate: '2022/04/22 14:11:30', PaymentType: 'CVS_CVS', PayFrom: 'ibon', PaymentTypeChargeFee: 0, // 其餘欄位和此交易方式無關, 也不一定會出現 // 所有欄位請參考上方完整的 response data 格式 // ...略 }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '2204220310222', ItemName: '顥陽蘭坊 5000 TWD x 1', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261439048696', TradeDate: '2022/04/26 14:39:04', TradeAmt: 200, TradeStatus: '1', HandlingCharge: 0, PaymentNo: 'LLL22112732600', PaymentDate: '2022/04/22 14:11:30', PaymentType: 'BARCODE_BARCODE', PayFrom: 'family', PaymentTypeChargeFee: 0, // 其餘欄位和此交易方式無關, 也不一定會出現 // 所有欄位請參考上方完整的 response data 格式 // ...略 }
import { Merchant, PaymentInfoQuery } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(PaymentInfoQuery, {
MerchantTradeNo: 'NEA12345678',
});
const data = await query.read();
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'NEA12345678', CustomField1: '', CustomField2: '', CustomField3: 'N22042600020', CustomField4: 'ATM', TradeNo: '2204261421418645', TradeDate: '2022/04/26 14:21:51', TradeAmt: 409, PaymentType: 'ATM_LAND', ExpireDate: '2022/04/29', BankCode: '005', vAccount: '5219111913209840', RtnCode: 2, RtnMsg: 'Get VirtualAccount Succeeded', }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: '7c80cdef716c4a2998d', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261439048696', TradeDate: '2022/04/26 14:39:30', TradeAmt: 200, PaymentType: 'CVS_CVS', ExpireDate: '2022/05/03 14:39:30', PaymentNo: 'LLL22116735498', PaymentURL: 'https://payment-stage.ecpay.com.tw/PaymentRule/CVSBarCodePaymentNo=LLL22116735498', RtnCode: 10100073, RtnMsg: 'Get CVS Code Succeeded.', }
-
{ CheckMacValue: 'ABCD...', MerchantID: '2000132', StoreID: '', MerchantTradeNo: 'CK20220426401292', CustomField1: '', CustomField2: '', CustomField3: '', CustomField4: '', TradeNo: '2204261401048597', TradeDate: '2022/04/26 14:02:17', TradeAmt: 1500, PaymentType: 'BARCODE_BARCODE', ExpireDate: '2022/05/03 14:39:30', Barcode1: '1105036EA', Barcode2: '3453011539919569', Barcode3: '042677000001500', RtnCode: 10100073, RtnMsg: 'Get CVS Code Succeeded.', }
import { Merchant, CreditCardPeriodInfoQuery } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(CreditCardPeriodInfoQuery, {
MerchantTradeNo: 'NEA12345678',
});
const data = await query.read();
-
{ MerchantID: '2000132', MerchantTradeNo: 'a2394da5fa5c4ef6b0b', TradeNo: '2204260959138173', PeriodType: 'M', Frequency: 1, ExecTimes: 12, TotalSuccessTimes: 1, PeriodAmount: 100, TotalSuccessAmount: 100, RtnCode: 1, ExecStatus: '1', ExecLog: [ { RtnCode: 1, RtnMsg: '成功.', TradeNo: '2204260959138173', amount: 100, auth_code: '777777', gwsr: 11955800, process_date: '2022/04/26 10:00:22', }, ], process_date: '2022/04/26 10:00:22', amount: 100, auth_code: '777777', gwsr: 11955800, card4no: '4444', card6no: '431195', }
import { Merchant, TradeV2Query } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(TradeV2Query, {
CreditRefundId: 10123456, // baseParams.NeedExtraPaidInfo = 'Y' 時取得詳情中的 gwsr 值即是此 Id
CreditAmount: 500,
CreditCheckCode: 59997889, // 商家檢查碼, 後台 > 信用卡收單 > 信用卡授權資訊可查到
});
const data = await query.read();
-
{ RtnMsg: "", RtnValue: { TradeID: '0015625112', amount: 100, clsamt: 100, authtime: "2016/5/12 下午 07:09:17", status: "已關帳" close_data: [ { status: "已關帳", sno: "2782343", amount: 100, datetime: "2016/5/12 下午 08:00:00" } ] }, }
import { Merchant, TradeNoAioQuery } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(TradeNoAioQuery, {
// 必填
DateType: '2', // '2'(付款日) | '4'(撥款日) | '6'(訂單日)
BeginDate: '2022-04-25',
EndDate: '2022-04-26',
MediaFormated: '1', // '0'(舊格式) | '1'(新格式)
// 選填
PaymentType: '01', // '01'(信用卡) | '02'(WebATM) | '03'(ATM) | '04'(CVS) |
// '05'(BARCODE) | '10'(全家立即儲) | '11'(圓夢彈性分期);
PlatformStatus: undefined, // undefined(全部) | '1'(一般) | '2'(平台)
PaymentStatus: '0', // undefined(全部) | '0'(未付款) | '1'(已付款) | '2'(訂單失敗)
AllocateStatus: undefined, // undefined(全部) | '0'(未撥款) | '1'(已撥款)
CharSet: '1', // undefeind(Server預設) | '1'(Big5) | '2'(utf8);
});
const data = await query.read(); // csv檔
- 純文字 (.csv 檔)
- 錯誤訊息綠界置於 cvs 檔案內
import { Merchant, FundingReconDetail } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const query = merchant.createQuery(FundingReconDetail, {
// 必填
PayDateType: 'fund', // 'fund'(依結算日) | 'close'(依關帳日) | 'enter'(依撥款日)
StartDate: '2022-04-25',
EndDate: '2022-04-26',
MediaFormated: '1', // '0'(舊格式) | '1'(新格式)
// 選填
CharSet: '1', // undefeind(Server預設) | '1'(Big5) | '2'(utf8);
});
const data = await query.read(); // csv檔
- 純文字 (.csv 檔)
- 錯誤訊息綠界置於 cvs 檔案內
遠端操作作業的 Action Classes,包含有:
-
DoAction
: 信用卡關帳、刷退、取消與放棄作業 -
CreditCardPeriodAction
: 信用卡定期定額重新授權、取消授權
每個 ActionClass 實例具有 .execute()
的非同步方法可以向綠界服務發起操作請求,響應格式如下所列。
所有的 Action Classes 都有 .execute()
的執行操作方法。
Syntax:
action.execute();
Arguments:
- none
Returns:
- (Promise): promise
Errors:
- (ActionError):
ActionError
實例 - (CheckMacValueError):
CheckMacValueError
實例
Examples:
import { Merchant, DoAction } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const action = merchant.createAction(DoAction, {
// 皆為必填
MerchantTradeNo: 'NEA12345678',
TradeNo: '8811223388121'.
Action: 'C' , // 'C'(關帳) | 'R'(退刷) | 'E'(取消) | 'N'(放棄)
TotalAmount: 500
});
const reuslt = await action.execute();
{
MerchantID: '2000132',
MerchantTradeNo: '20211026001969730',
TradeNo: '20120315174058256423',
RtnCode: 1,
RtnMsg: '關帳成功',
}
import { Merchant, CreditCardPeriodAction } from 'node-ecpay-aio';
const merchant = new Merchant('Test', { /* 略 */ });
const action = merchant.createAction(CreditCardPeriodAction, {
// 皆為必填
MerchantTradeNo: 'NEA12345678',
Action: 'Cancel', // 'ReAuth'(重新授權) | 'Cancel'(取消授權)
});
const reuslt = await action.execute();
{
CheckMacValue: 'ABC...',
MerchantID: '2000132',
MerchantTradeNo: '20211026001969730',
RtnCode: 1,
RtnMsg: '停用成功',
}
輸入參數驗證錯誤。
Format:
{
name: 'ValidationError',
message: 'foo can not be less than 6.'
}
建立訂單發生錯誤。
Format:
{
name: 'PlaceOrderError',
message: 'Duplicated MerchantTradeNo, create order failed.',
}
遠端查詢資料失敗。
Format:
{
name: 'ECPayReturnedQueryError',
code: 10200047, // 綠界傳回的錯誤碼, 即原始響應中的 RtnCode
message: 'Cant not find the trade data.', // 綠界傳回的錯誤訊息, 即原始響應中的 RtnMsg
response: '{ ... }' // 原始響應的 json string
}
遠端操作執行失敗。
Format:
{
name: 'ECPayReturnedActionError',
code: 100006, // 綠界傳回的錯誤碼, 即原始響應中的 RtnCode
message: '該訂單狀態為停用中', // 綠界傳回的錯誤訊息, 即原始響應中的 RtnMsg
response: '{ ... }' // 原始響應的 json string
}
收到的響應其校驗碼驗證失敗。
Format:
{
name: 'CheckMacValueError',
message: 'Invalid CheckMacValue. MerchantTradeNo: NEA87654321.',
response: '{ ... }' // 原始響應的 json string
}
用於檢驗響應資料物件中的 CheckMacValue
值是否正確。如果響應資料中並未帶有 CheckMacValue
欄位,函數執行時將會拋出錯誤。NEA 提供的查詢 API 會自動檢驗響應的校驗碼是否正確,故此函數的主要用途是給開發者在實作 ReturnURL
, PeriodReturnURL
, PaymentInfoURL
等 webhooks 時檢驗收到的資料使用。
Syntax:
isValidReceivedCheckMacValue(data, hashKey, hashIV);
Arguments:
-
data
(Object): 帶有CheckMacValue
欄位的資料物件。 -
hashKey
(String): 綠界配發給特店的檢驗碼。 -
hashIV
(String): 綠界配發給特店的檢驗碼。
Returns:
- (Boolean):
true
檢驗符合,false
檢驗不符
Errors:
- (CheckMacValueError):
CheckMacValueError
實例
Examples:
import { isValidReceivedCheckMacValue } from 'node-ecpay-aio';
const reponsedDataToCheck = {
CheckMacValue: 'ABCD...',
// ... 其它欄位
};
try {
const isValid = isValidReceivedCheckMacValue(reponsedDataToCheck, 'your_hashkey', 'your_hashiv');
console.log(isValid); // true
} catch (err) {
console.log(err);
// { name: 'CheckMacValueError', message: 'No CheckMacValue field within data.' }
}
由於部署環境可能位在世界任意時區,本函數會將部署時區的當地時間轉換為台灣當前時間。假如你的訂單編號欲使用台灣時間流水號,例如 '20220517105526763'
(台灣時間 2022/05/17 10:55:26.763),這正是此函數的用途。
Syntax:
getCurrentTaipeiTimeString([config]);
Arguments:
-
config
(Object, optional): 設定物件。
-
timestamp
(Number, optional): UNIX timestamp milliseconds -
format
(String, optional):'Datetime'
|'Date'
|'Serial'
-
'Datetime'
(default): 函數將傳出'2022/05/17 10:55:26'
日期時分秒格式之字串 -
'Date'
: 函數將傳出'2022/05/17'
日期格式之字串 -
'Serial'
: 函數將傳出'20220517105526763'
時間流水號(至毫秒)格式之字串
-
Returns:
- (String): 根據
'format'
設定所傳出的台北時間字串
Examples:
import { isValidReceivedCheckMacValue } from 'node-ecpay-aio';
console.log(getCurrentTaipeiTimeString()); // '2022/05/17 15:39:18'
console.log(getCurrentTaipeiTimeString({ format: 'Date' })); // '2022/05/17'
console.log(getCurrentTaipeiTimeString({ format: 'Serial' })); // '20220517153918562'
console.log(getCurrentTaipeiTimeString({ timestamp: 1652693484763 })); // '2022/05/16 17:31:24'
console.log(
getCurrentTaipeiTimeString({
timestamp: 1652693484763,
format: 'Date',
})
); // '2022/05/16'
console.log(
getCurrentTaipeiTimeString({
timestamp: 1652693484763,
format: 'Serial',
})
); // '20220516173124763'
-
關於發票格式詳細說明與限制,請參閱綠界官方 AIO 技術文件說明,下方盡可能摘要重點。
-
NEA 會驗證發票參數格式與相依條件,若設定有誤則會拋出
ValidationError
錯誤。 -
對大部分商家來講,開立發票多是應稅 (
TaxType: '1'
)且一般稅額 (InvType: '07'
)。如果你的發票是混合型或有特殊行業別的稅額,請另外申請電子發票服務,AIO 提供的發票功能只能滿足一般商業交易場景。const invoice = { // 必填 TaxType: '1', // '1': 應稅, '2': 零税, '3': 免稅, '9': 混合 Print: '1', // '1': 列印, '0': 不印, 有統編時只能選列印, 捐贈時只能選不印, Donation: '0', // '0': 不捐贈, '1': 捐贈, 當有統編時不能填捐贈 RelateNumber: 'suggest-unique-id', // 長度最大30字元 InvoiceItemName: '品名1|品名2', // 多商品以 | 隔開, 中間無空格 InvoiceItemCount: '2|5', // 商品數量, 多商品以 | 隔開 InvoiceItemWord: '台|張', // 單位 InvoiceItemPrice: '100|50', // 單價(預設含稅) // 必填, 二擇一, 發票開立與中獎通知用 CustomerPhone: '0912345678', // 聯絡電話, 必需要為手機號碼 CustomerEmail: 'nea@example.com', // 電子信箱 // 選填 InvoiceItemTaxType: '1|1', // '1': 應稅, '2': 零税, '3': 免稅 InvoiceRemark: '備註欄文字', // 選填: 載具與捐贈 LoveCode: '123456', // 受贈單位碼, 當選擇捐贈時, 此欄必填 ClearanceMark: '1', // '1': 非經海關, '2': 經海關, TaxType若為'2', 此欄必填 CarruerType: '', // '': 無載具, '1': 特店載具, '2': 自然人憑證, '3': 手機條碼; // 若有設統編或發票要列印時, CarruerType 只能設定為無載具 CarruerNum: '', // 無載具: '', 特店載具: '統編+RelateNumber(此欄由綠界設定)' // 自然人憑證: 'AB12345...', 手機條碼: '/Yabc123' // 選填: 統編與客戶資料 CustomerID: 'NEA_U_0000000001', // 自訂的客戶編號, 最長20字元 CustomerIdentifier: '12345678', // 統編 CustomerName: 'NEA神秘開發公司', // 客戶名稱, 若設定要印發票證明則必填 CustomerAddr: '宇宙市太陽區地球路1號', // 客戶地址, 若設定要印發票證明則必填 // 選填: 其它 DelayDay: 0, // 預設0為立即開立, 最大可設到15天後自動開立 InvType: '07', // AIO 固定為 '07': 一般稅額, 若有其他稅額需求須申請電子發票服務 };
Examples:
-
買受人是一般消費者
const invoice = { TaxType: '1', // '1': 應稅 Print: '0', // '0': 不印 Donation: '0', // '0': 不捐贈 RelateNumber: '850b7a66-d575-11ec', InvoiceItemName: '超有感內衣|超無感內褲', InvoiceItemCount: '2|3', InvoiceItemWord: '件|件', InvoiceItemPrice: '100|50', // 預設都是含稅價 CustomerPhone: '0912345678', // 手機和 Eamil 須二擇一 // CustomerEmail: 'customer@example.com' };
-
買受人是有統編的營業人
const invoice = { TaxType: '1', // '1': 應稅 Print: '1', // '1': 只能選列印 Donation: '0', // '0': 只能選不捐贈 RelateNumber: '53ddd781-518e-456f', InvoiceItemName: '塑膠袋', InvoiceItemCount: '10', InvoiceItemWord: '包', InvoiceItemPrice: '15', // 預設都是含稅價 CustomerEmail: 'customer@example.com', // 手機和 Eamil 須二擇一 // CustomerPhone: '0912345678', CustomerIdentifier: '12345678', // 統編 CustomerName: 'NEA神秘開發公司', CustomerAddr: '宇宙市太陽區地球路1號', DelayDay: 3, // 收到款項後 3 天自動開立 };
import {
Merchant,
CreditOneTimePayment,
ATMPayment,
TradeInfoQuery,
CreditCardPeriodAction,
} from 'node-ecpay-aio';
// Step 1: 建立特店
const merchant = new Merchant('Test', {
// 生產環境請記得將 'Test' 改成 'Production'
MerchantID: 'your-merchant-id',
HashKey: 'your-merchant-hashkey',
HashIV: 'your-merchant-hashiv',
ReturnURL: 'https://api.test.com/your/hook',
});
// [使用情境一] Step 2: 特店建立 payment => Step 3: 前端重導至綠界結帳
const payment = merchant.createPayment(CreditOneTimePayment, {});
const htmlRedirectPostForm = await payment.checkout({
// 結帳時給予發票資訊即表示要開立發票
RelateNumber: 'rl-123456',
TaxType: '1',
Donation: '0',
Print: '0',
InvoiceItemName: '鉛筆|橡皮擦',
InvoiceItemCount: '10|2',
InvoiceItemWord: '支|顆',
InvoiceItemPrice: '12|18',
DelayDay: 0,
});
// [使用情境二] Step 2: 特店建立 payment => Step 3: 後端直接建立訂單(僅適用延遲付款)
const payment = merchant.createPayment(ATMPayment, {});
const paymentInfo = await payment.placeOrder({
// 結帳時給予發票資訊即表示要開立發票
RelateNumber: 'rl-123456',
TaxType: '1',
Donation: '0',
Print: '0',
InvoiceItemName: '鉛筆|橡皮擦',
InvoiceItemCount: '10|2',
InvoiceItemWord: '支|顆',
InvoiceItemPrice: '12|18',
DelayDay: 0,
});
// [使用情境三] Step 2: 特店建立 query => Step 3: 執行查詢
const tradeInfoQuery = merchant.createQuery(TradeInfoQuery, {
MerchantTradeNo: 'NEA12345678',
});
const tradeInfo = await tradeInfoQuery.read();
// [使用情境四] Step 2: 特店建立 action => Step 3: 執行操作
const reAuthAction = merchant.createAction(CreditCardPeriodAction, {
MerchantTradeNo: 'foo-trade-no';
Action: 'ReAuth'
});
const reAuthResult = await reAuthAction.execute();