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 中一律是指空字串 '' 而不是 null 或 undefined。在 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