WooCommerce 串接綠界金流的實作要點與常見坑
發布
WooCommerce 預設不支援台灣本地金流,綠界(ECPay)是最常見的補位選擇。這篇文章不是「如何安裝模組」教學,而是寫給要自己開發或驗收串接品質的人:錢的流程哪裡會出錯、怎麼設計才不會錯。以下通則適用於自寫外掛與審視現成模組。
全流程鳥瞰
綠界的主流程(以全方位金流 AioCheckOut 為例,規格見綠界官方技術文件):
- 消費者在 WooCommerce 結帳,網站建立訂單(狀態:待付款)
- 網站把訂單資料+檢查碼 POST 到綠界,消費者被導到綠界付款頁
- 消費者完成付款
- 綠界以背景通知(ReturnURL)通知你的伺服器付款結果
- 綠界把消費者導回你指定的頁面(OrderResultURL/ClientBackURL)
- 網站依背景通知更新訂單狀態,觸發後續(出貨、開通、寄信)
第 4 步與第 5 步的區別是整個串接最重要的觀念:導回是給人看的,背景通知才是給帳算的。
先畫訂單狀態機
寫任何程式之前,先把狀態與轉移規則畫出來。WooCommerce 的預設狀態對應綠界流程大致是:
pending(待付款)
├─ 收到背景通知:付款成功 → processing(處理中)→ completed(已完成)
├─ 收到背景通知:付款失敗 → failed(失敗)
├─ 逾時未付(ATM/超商代碼過期)→ cancelled(取消)
processing / completed
└─ 退款成立 → refunded(已退款)
規則寫清楚的價值在邊界情況:已完成的訂單又收到一次成功通知怎麼辦?失敗的訂單收到成功通知怎麼辦?(可能發生:消費者第一次刷失敗、重試成功。)狀態機說「failed 可以轉 processing」,程式就照做;狀態機沒說的轉移,一律記錄並告警,不要默默處理。
背景通知的三道防線
ReturnURL 端點是駭客與意外的正面戰場,三道防線缺一不可:
防線一:檢查碼(CheckMacValue)驗證
綠界的每一筆通知都帶檢查碼,用你的 HashKey/HashIV 依規格重算比對。驗證失敗就回應失敗並記錄,不處理任何業務邏輯——這擋掉偽造通知。實作時注意編碼細節:參數排序、URL encode 的字元對應表要完全照官方規格,這是最多人卡住的地方。
防線二:金額比對
通知裡的交易金額,必須回頭與你資料庫裡那筆訂單的應付金額比對。跳過這一步的系統,攻擊者可以用 1 元的真實付款換走 1 萬元的商品——通知是真的、檢查碼是對的,錯的是金額沒人看。
防線三:冪等處理
綠界在沒收到你的成功回應時會重送通知;網路異常時同一筆通知可能到達多次。處理邏輯必須冪等:同一筆交易編號的成功通知,第二次以後只回應成功、不重複執行業務(不重複出貨、不重複開通、不重複寄信)。實作上以交易編號做唯一鍵,先查後寫。
三道防線的共同原則:背景通知處理器只信自己資料庫+密碼學驗證,不信任何請求內容的表面資訊。
退款與對帳
- 退款:信用卡可走 API 退款(依綠界規格),ATM/超商代碼付款則需另行匯款處理——退款流程設計時要分付款方式寫規則,不要假設都能原路退回。
- 對帳:每月以綠界後台的撥款明細對你資料庫的訂單紀錄,核對筆數與金額。對帳不是出事才做的事,是每月例行——手續費計算、退款沖銷都在這裡浮現。
- 法規面:數位商品的七天猶豫期適用例外需在結帳流程明確告知並取得同意,這是台灣消保法的合規要求,退款規則要與它一致。
付款方式矩陣:行為差異決定程式分支
「串綠界」不是一種行為,是好幾種。各付款方式的流程差異直接對應到程式要處理的分支:
| 付款方式 | 結果何時確定 | 特殊處理 |
|---|---|---|
| 信用卡 | 即時(消費者在綠界頁完成) | 3D 驗證流程中斷的懸置訂單要有逾時回收 |
| ATM 轉帳 | 非即時(取號後等待入帳,可能數天) | 先收「取號成功」通知、再收「入帳」通知,兩段狀態要分開記 |
| 超商代碼 | 非即時(繳費期限內任一時點) | 同上,且要處理過期未繳的取消流程 |
| 超商條碼 | 非即時 | 同上 |
| 分期付款 | 即時 | 對帳時金額為含分期手續費的總額,撥款另計 |
非即時付款是狀態機複雜度的主要來源:訂單會停在「取號成功、等待付款」的中間態,庫存要不要保留、保留多久、過期怎麼釋放,都是商業決策先行、程式實作跟上的題目——這些問題沒有標準答案,但沒被問過的專案一定出事。
上線前檢查清單
主流程通了不等於能上線。切正式環境前逐項打勾:
- ☐ 商店代號、HashKey、HashIV 已換成正式環境值(測試值上線是事故排行榜第一名)
- ☐ ReturnURL 是 HTTPS 且外網可達(本機測試的網址常被忘在設定裡)
- ☐ 三道防線各有至少一條自動化測試(偽造通知、金額不符、重複通知)
- ☐ 非即時付款的過期處理已驗證(把繳費期限設短實測一輪)
- ☐ 退款流程演練過一次真實金額(小額實付實退,含對帳確認)
- ☐ 綠界後台的通知網址、金額上限、付款方式開關與程式端一致
- ☐ 錯誤情況有告警:檢查碼驗證失敗、金額不符、未知狀態轉移都要進通知管道,不能只寫 log
測試策略:沙盒的能與不能
綠界測試環境能驗證的:主流程通不通、各付款方式的頁面流程、檢查碼實作對不對。
測不了的,用自動化測試補:
- 重複通知:對 ReturnURL 端點連打兩次相同通知,驗證第二次不重複出貨
- 金額竄改:發送金額不符的合法格式通知,驗證被拒絕
- 亂序到達:失敗通知晚於成功通知到達的處理
- 逾時與重試:端點回應超時後的行為
這些測試寫成自動化測試套件,每次改動金流相關程式前全數通過再部署——金流程式的修改成本不在寫,在「證明沒改壞」。
常見坑清單
- 把導回頁當付款依據:消費者關掉導回頁、網路斷線,都會讓導回不發生;業務邏輯只能掛在背景通知上。
- 重複通知造成重複出貨:見防線三。實務上最常見的事故,沒有之一。
- 金額不比對:見防線二。
- 測試環境金鑰上正式站:商店代號、HashKey、HashIV 三組值的環境切換要進部署檢查清單。
- 中文編碼:商品名稱含中文時的 URL encode 問題,檢查碼會過不了;用官方 SDK 或對照官方字元表。
- 回應格式不對:ReturnURL 收到通知後必須回應綠界規定的字串,回錯格式綠界會視為失敗而重送——你的 log 就會看到「同一筆通知每隔幾分鐘來一次」。
訂單成立之後:與內部流程的整合模式
金流串好只是收到錢,多數專案真正的價值在「收到錢之後自動發生的事」。三種常見整合模式,複雜度遞增:
- 通知型:付款成功後發訊息到內部管道(Email、LINE Notify 替代方案、Slack),出貨仍由人執行。實作成本最低,適合日單量十位數以內的規模。
- 開通型:數位商品(課程、會員、下載)付款後自動開通權限。關鍵設計是把「開通」寫成冪等的獨立函式——背景通知、後台手動補單、客服處理爭議三個入口都呼叫同一支,行為才會一致。
- 同步型:訂單資料自動寫入既有的 ERP、進銷存或會計系統。這一層的成本常被低估:欄位對應、雙邊資料衝突的處理規則、對方系統改版的維護責任,都要在報價階段談清楚。
模式的選擇依據不是技術,是單量與錯誤成本:日單量個位數時,人工出貨比任何自動化都便宜;錯誤成本高(超賣、重複開通會賠錢)時,自動化的測試投資才回得了本。
對帳的每月節奏
對帳寫過一次流程,之後每月照表操課,約半小時:
- 下載綠界後台當月撥款明細
- 與資料庫訂單比對筆數與總額(寫一支比對腳本,一次投資)
- 差異逐筆追:通常是退款沖銷、手續費、或跨月入帳的時間差
- 差異歸零後歸檔,留下當月對帳紀錄
「每月半小時」的前提是前面的工程都做對;反過來說,如果每月對帳都要花一天追差異,那是系統在告訴你背景通知的處理有洞——把對帳耗時當成串接品質的長期監測指標,很準。
需要幫手的話
上述工程屬於報價量級三的客製開發範圍。本工作室的 WordPress 網站建置服務含綠界串接與上述測試策略的實作;在自架與平台方案之間還沒定案的,先讀〈自架 WordPress vs Wix、Shopify〉再決定要不要走到這一步。
本文常見問題
- 一定要客製開發嗎?市面上不是有現成的綠界模組?
- 不一定,先試現成模組。綠界官方與社群都有 WooCommerce 模組,標準的信用卡收款流程多半夠用;需要客製的時機是:模組不支援你要的付款方式組合、對帳格式要配你的內部流程、或訂單成立後要觸發自家系統的後續動作。
- 串接大概要多少開發時間?
- 標準信用卡流程以週為單位;含多種付款方式、退款自動化與對帳客製的完整串接以月為單位。時間主要花在異常路徑的處理與測試,不是主流程——主流程一天就能通,讓它「怎麼壞都不會錯帳」才是工程。
- 測試環境的卡號哪裡來?
- 綠界提供測試環境專用的商店代號與測試卡號,在官方技術文件的測試資訊頁可以查到;正式環境切換時記得換掉商店代號、HashKey 與 HashIV 三組值,這是上線檢查清單的第一條。