Skip to content

API Document

simen edited this page Sep 28, 2022 · 44 revisions

1. Overview

node-ecpay-aio (NEA) 是綠界全方位金流(AIO)的 Node.js SDK。NEA 是根據綠界官方 API 規格書的全新實作並且支援 TypeScript,它並非官方 SDK 的 fork 改寫版本。

因綠界主要使用者皆在台灣,故 NEA 文件皆以中文書寫。


安裝

npm install --save node-ecpay-aio

APIs



2. 使用流程說說明

          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: const html = await payment.checkout()
        • 也可直接於後端請求建立綠界訂單: const paymentInfo = await payment.placeOrder()
    • query 可以執行讀取: const data = await query.read()
    • action 可以執行操作: const result = await action.execute()


如何閱讀本文件

  1. 建議先稍微讀過官方的 API 手冊。
  2. 參數物件會以 必填選填 兩部份區隔開。
  3. 因參數眾多,僅在需要之處以註解稍加說明。若對某參數不了解,請直接參考官方 API 手冊。
  4. 參數命名一律按官方的大寫駝峰式(Pascal Case)書寫。
  5. 參數 Schema 或參數間的相依條件已有防衛性驗證,違反規則即會拋錯,故 NEA 文件不會特別說明這些限制。
  6. 參數型別是嚴格的,字串就是字串,數字就是數字。官方的 SDK 會自動將字串轉數字,但 NEA 不會,因為這會造成型別混淆。你心裡只要記住幾乎 99% 的參數都是字串,僅有部分涉及「金額」、「次數」、「天數」的地方才會有數字出現。
  7. 關於可用參數及其型別、選項,TypeScript 會協助你。不過,到底要用 TS 還是 JS 來寫,由你自行決定。
  8. 空值與 undefined 不同。在官方手冊中提到的「空值」在 NEA 中一律是指空字串 '' 而不是 nullundefined。在 NEA,只要是 undefined 的參數,皆不會編入 x-www-form-urlencoded 的鍵值對字串中。如果你想要將屬性編入 post 字串,請給予該屬性空字串 '',而非給予 undefined。綠界的請求參數並不使用 null,故請勿使用 null 表示空值。


3. Merchant Class

代表綠界特店的 Class,它的實例帶有工廠方法 createPayment()createQuery() 以及 createAction() 可以產生特店的結帳、資料查詢與信用卡作業操作。特店是指「提供綠界金流付款服務給消費者付款交易的賣家系統」,一般來講也就是你的後端系統。


Syntax:

import { Merchant } from 'node-ecpay-aio';



3.1 new Merchant()

建立綠界特店的實例。建立時需給予組態 config 用來設定你的特店資訊。Merchant 的實例帶有工廠方法 createPayment()createQuery() 以及 createAction()


Syntax:

new Merchant(mode, config[, ecpayServiceUrls])

Arguments:

  1. mode (String): 'Test' | 'Production',各表示特店要使用綠界的測試環境或生產環境 API。

  2. 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://...'
    }
  3. ecpayServiceUrls (Object, optional): 改寫或新增綠界 API 的服務端點資料,一般不會用到此參數。為節省說明版面,此處暫省略說明。

Returns:

  • (Object): merchant 實例

Errors:

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',
});



3.2 .createPayment()

建立付款方式的工廠方法。建立時請注入要使用的 PaymentClass,並準備好每一種付款方式都要填寫的基本參數 baseParams,以及屬於個別付款方式的專屬參數 params


Syntax:

merchant.createPayment(PaymentClass, baseParams[, params]);

注意

建議不要省略 params,即使你並未使用 params 中的任何屬性,請令其為空物件 {} 而非 undefined,保持一致的呼叫風格。


Arguments:

  1. PaymentClass (Class): 各種付款方式的 Class,包含有

    • CreditOneTimePayment: 信用卡一次付清
    • CreditDividePayment: 信用卡分期付款
    • CreditPeriodPayment: 信用卡定期定額 (訂閱式收費)
    • WebATMPayment: WebATM 付款
    • ATMPayment: ATM 付款
    • CVSPayment: 超商代碼付款
    • BARCODEPayment: 超商條碼付款
    • AndroidPayPayment: Google Pay 付款。綠界 AIO 目前暫時停止此服務,目前產生 AndroidPayPayment 時會拋錯
  2. 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 設定過, 此處不需再設定, 除非你針對此單要顯示個別的付款結果網址
    }
  3. params (Object): 根據不同的 PaymentClass 付款方式,各自需要的獨特參數。分述於下方各種付款方式範例。

Returns:

  • (Object): payment 實例

Errors:

Examples:

1. 信用卡一次付清

  • 付款模式: 立即付款(須導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

2. 信用卡分期付款

  • 付款模式: 立即付款(須導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

3. 信用卡定期定額

  • 付款模式: 立即付款(須導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

4. WebATM 付款

  • 付款模式: 立即付款(須導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

5. ATMPayment 付款

  • 付款模式: 延遲付款(可選擇是否導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

6. 超商代碼付款

  • 付款模式: 延遲付款(可選擇是否導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

7. 超商條碼付款

  • 付款模式: 延遲付款(可選擇是否導向綠界結帳頁)

  • 付款類別: 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(/* 可選填發票 */);

8. Android Pay (GooglePay)

  • 付款模式: 立即付款(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(/* 可選填發票 */);

9. 使用者自選付款方式

  • 付款模式: 立即付款/延遲付款(須導向綠界結帳頁;不支援 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();



3.3 .createQuery()

建立交易資料查詢的工廠方法。建立時請注入要使用的 QueryClass,並準備好每一種查詢要填寫的參數 params。建立的 QueryClass 實例具有 .read() 的非同步方法可以向綠界服務發起查詢請求。查詢結果的響應格式請見 Query Class: 5.1 .read() API 說明。Query 是冪等操作。


Syntax:

merchant.createQuery(QueryClass, params);

注意

建議不要省略 params,即使你並未使用 params 中的任何屬性,請令其為空物件 {} 而非 undefined


Arguments:

  1. QueryClass (Class): 各種查詢的 Class,包含有
    • TradeInfoQuery: 訂單資料查詢
    • PaymentInfoQuery: ATM/CVS/BARCODE 取號結果查詢
    • CreditCardPeriodInfoQuery: 信用卡定期定額訂單查詢
    • TradeV2Query: 查詢信用卡單筆明細紀錄
    • TradeNoAioQuery: 下載特店對帳媒體檔
    • FundingReconDetail: 下載信用卡撥款對帳資料檔
  2. params (Object): 根據不同的 QueryClass 查詢方式,各自所需的獨特參數。分述於下方各種查詢範例。

Returns:

  • (Object): Query 實例

Errors:

Examples:

1. 查詢訂單資料

  • 查詢類別: 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();

2. 查詢延遲付款取號結果

  • 查詢類別: 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();

3. 查詢信用卡定期定額訂單

  • 查詢類別: 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();

4. 查詢信用卡單筆明細紀錄

  • 查詢類別: 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();

5. 下載特店對帳媒體檔

  • 查詢類別: 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 檔)


6. 下載信用卡撥款對帳資料檔

  • 查詢類別: 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 檔)




3.4 .createAction()

建立操作的工廠方法。建立時請注入要使用的 ActionClass,並準備好每一種操作要填寫的參數 params。建立的 ActionClass 實例具有 .execute() 的非同步方法可以向綠界服務發起遠端操作請求。操作結果的響應格式請見 Action Class: 6.1 .execute() API 說明。Action 是非冪等操作。


Syntax:

merchant.createAction(ActionClass, params);

注意

建議不要省略 params,即使你並未使用 params 中的任何屬性,請令其為空物件 {} 而非 undefined


Arguments:

  1. ActionClass (Class): 各種操作的 Class,包含有

    • DoAction: 信用卡請退款作業
    • CreditCardPeriodAction: 信用卡定期定額訂單作業
  2. params (Object): 根據不同的 Action Class 操作方式,各自所需的獨特參數。分述於下方各種操作範例。

Returns:

  • (Object): action 實例

Errors:

Examples:

1. 信用卡關帳、刷退

  • 操作類別: 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() 說明。


2. 信用卡定期定額訂單作業

  • 操作類別: CreditCardPeriodAction

    const action = merchant.createAction(CreditCardPeriodAction, {
      // 皆為必填
      MerchantTradeNo: 'NEA12345678',
      Action: 'ReAuth', // 'ReAuth' | 'Cancel';
    });
    
    const result = await action.execute();
  • 響應資料格式請見 6.1 excute() 說明。



4. Payment Class

Payment Classes 分類如下:

  • 立即付款類

    • CreditOneTimePayment: 信用卡一次付清
    • CreditDividePayment: 信用卡分期付款
    • CreditPeriodPayment: 信用卡定期定額 (訂閱式收費)
    • WebATMPayment: WebATM 付款
    • AndroidPayPaymen: Google Pay 付款。綠界目前暫時停止此服務,目前產生 AndroidPayPayment 時會自動 throw Error。
  • 延遲付款類

    • ATMPayment: ATM 付款
    • CVSPayment: 超商代碼付款
    • BARCODEPayment: 超商條碼付款

4.1 .checkout()

所有的 Payment Classes 都有 .checkout() 的結帳方法。 如果需要開立電子發票,請於結帳時帶入發票參數 chekcout(invoice)。如不開立發票,直接執行checkout()即可。關於帶入的發票請見 9. 發票格式 說明。


Syntax:

payment.checkout([invoice]);

Arguments:

  1. invoice (Object, optional): 發票參數。結帳時填入可一併開立電子發票。

Returns:

  • (String): 傳給前端重導向至綠界結帳頁的 Post Form

Errors:

Examples:

  • 1. 不開立電子發票

    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>
  • 2. 要開立電子發票

    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>

4.2 .placeOrder()

只有延遲付款的 Payment Classes 才有 .placeOrder() 方法。 如果需要開立電子發票,請於結帳時帶入發票參數placeOrder(invoice)。如不開立發票,直接執行placeOrder()即可。


Syntax:

payment.placeOrder([invoice]);

Arguments:

  1. 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.',
      }

Errors:

Examples:

  • 1. 不開立電子發票

    const info = await payment.placeOrder();
  • 2. 開立電子發票

    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);


5. Query Class


交易資料查詢的 Query Classes,包含有:

  • TradeInfoQuery: 訂單資料查詢
  • PaymentInfoQuery: ATM/CVS/BARCODE 取號結果查詢
  • CreditCardPeriodInfoQuery: 信用卡定期定額訂單查詢
  • TradeV2Query: 查詢信用卡單筆明細紀錄
  • TradeNoAioQuery: 下載特店對帳媒體檔
  • FundingReconDetail: 下載信用卡撥款對帳資料檔

每個 QueryClass 實例具有 .read() 的非同步方法可以向綠界服務發起查詢請求,響應格式如下所列。


5.1 .read()

所有的 Query Classes 都有 .read() 的非同步讀取查詢資料方法。


Syntax:

query.read();

Arguments:

  1. none

Returns:

  • (Promise): promise

Errors:

Examples:

1. 查詢訂單

import { Merchant, TradeInfoQuery } from 'node-ecpay-aio';

const merchant = new Merchant('Test', { /* 略 */ });

const query = merchant.createQuery(TradeInfoQuery, {
  MerchantTradeNo: 'NEA12345678',
});

const data = await query.read(); // 響應格式列如下方

響應資料

  • (1) 信用卡一次付清與分期
    {
      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: '',
    }

  • (2) 信用卡定期定額訂單
    {
      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 格式
      // ...略
    }

  • (3) WebATM 訂單
    {
      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 格式
      // ...略
    }

  • (4) ATM 訂單
    {
      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 格式
      // ...略
    }

  • (5) 超商代碼訂單
    {
      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 格式
      // ...略
    }

  • (6) 超商條碼訂單
    {
      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 格式
      // ...略
    }

2. 查詢延遲付款取號結果

import { Merchant, PaymentInfoQuery } from 'node-ecpay-aio';

const merchant = new Merchant('Test', { /* 略 */ });

const query = merchant.createQuery(PaymentInfoQuery, {
  MerchantTradeNo: 'NEA12345678',
});

const data = await query.read();

響應資料

  • (1) 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',
    }

  • (2) 超商代碼
    {
      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.',
    }

  • (3) 超商條碼
    {
      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.',
    }

3. 查詢信用卡定期定額訂單

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',
    }

4. 查詢信用卡單筆明細紀錄

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"
          }
        ]
      },
    }


5. 下載特店對帳媒體檔

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 檔案內


6. 下載信用卡撥款對帳資料檔

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 檔案內


6. Action Class

遠端操作作業的 Action Classes,包含有:

  • DoAction: 信用卡關帳、刷退、取消與放棄作業
  • CreditCardPeriodAction: 信用卡定期定額重新授權、取消授權

每個 ActionClass 實例具有 .execute() 的非同步方法可以向綠界服務發起操作請求,響應格式如下所列。


6.1 .execute()

所有的 Action Classes 都有 .execute() 的執行操作方法。


Syntax:

action.execute();

Arguments:

  1. none

Returns:

  • (Promise): promise

Errors:

Examples:

1. 信用卡關帳、刷退

  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: '關帳成功',
}

2. 信用卡重新授權、取消授權

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: '停用成功',
}


7. Error Classes


7.1 ValidationError

輸入參數驗證錯誤。


Format:

{
  name: 'ValidationError',
  message: 'foo can not be less than 6.'
}

7.2 PlaceOrderError

建立訂單發生錯誤。


Format:

{
  name: 'PlaceOrderError',
  message: 'Duplicated MerchantTradeNo, create order failed.',
}

7.3 QueryError

遠端查詢資料失敗。


Format:

{
  name: 'ECPayReturnedQueryError',
  code: 10200047,                           // 綠界傳回的錯誤碼, 即原始響應中的 RtnCode
  message: 'Cant not find the trade data.', // 綠界傳回的錯誤訊息, 即原始響應中的 RtnMsg
  response: '{ ... }'                       // 原始響應的 json string
}

7.4 ActionError

遠端操作執行失敗。


Format:

{
  name: 'ECPayReturnedActionError',
  code: 100006,               // 綠界傳回的錯誤碼, 即原始響應中的 RtnCode
  message: '該訂單狀態為停用中', // 綠界傳回的錯誤訊息, 即原始響應中的 RtnMsg
  response: '{ ... }'         // 原始響應的 json string
}

7.5 CheckMacValueError

收到的響應其校驗碼驗證失敗。


Format:

{
  name: 'CheckMacValueError',
  message: 'Invalid CheckMacValue. MerchantTradeNo: NEA87654321.',
  response: '{ ... }' // 原始響應的 json string
}


8. 輔助函式

8.1 isValidReceivedCheckMacValue()

用於檢驗響應資料物件中的 CheckMacValue 值是否正確。如果響應資料中並未帶有 CheckMacValue 欄位,函數執行時將會拋出錯誤。NEA 提供的查詢 API 會自動檢驗響應的校驗碼是否正確,故此函數的主要用途是給開發者在實作 ReturnURL, PeriodReturnURL, PaymentInfoURL 等 webhooks 時檢驗收到的資料使用。


Syntax:

isValidReceivedCheckMacValue(data, hashKey, hashIV);

Arguments:

  1. data (Object): 帶有 CheckMacValue 欄位的資料物件。
  2. hashKey (String): 綠界配發給特店的檢驗碼。
  3. hashIV (String): 綠界配發給特店的檢驗碼。

Returns:

  • (Boolean): true 檢驗符合, false 檢驗不符

Errors:

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.' }
}

8.2 getCurrentTaipeiTimeString()

由於部署環境可能位在世界任意時區,本函數會將部署時區的當地時間轉換為台灣當前時間。假如你的訂單編號欲使用台灣時間流水號,例如 '20220517105526763' (台灣時間 2022/05/17 10:55:26.763),這正是此函數的用途。


Syntax:

getCurrentTaipeiTimeString([config]);

Arguments:

  1. 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'


9. 發票格式

  • 關於發票格式詳細說明與限制,請參閱綠界官方 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:

  1. 買受人是一般消費者

    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'
    };
  2. 買受人是有統編的營業人

    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 天自動開立
    };

10. 範例

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();
Clone this wiki locally