Skip to content

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

XenForo-Opay — OPay / 綠界 金流整合套件

XenForo 2.3 的 OPay 歐付寶(與 ECPay 綠界科技 共用同一 AIO API)官方金流整合套件,提供完整的「使用者升級 / 商品付款」流程,並在後台提供訂單管理、手動成立 / 取消 / 退款,以及即時向 OPay 查詢訂單狀態等管理功能。

  • 套件 ID:YUCTS/Opay
  • 適用版本:XenForo 2.3.0 以上
  • 開發者:YUCTS
  • 授權:MIT

目錄

  1. 功能特色
  2. 支援的付款方式
  3. 系統需求
  4. 安裝步驟
  5. 後台設定
  6. 後台訂單管理
  7. 付款流程說明
  8. 檔案結構
  9. 安全性說明
  10. 常見問題
  11. 疑難排解
  12. 版本歷史
  13. 回報問題與支援
  14. 授權

功能特色

  • 完全依照 XenForo 官方 Payment Provider 規範 撰寫,繼承 XF\Payment\AbstractProvider,可直接套用至:
    • 使用者升級(User Upgrade)
    • 任何實作 XF\Purchasable\AbstractPurchasable 的第三方付費商品
  • 同時支援 OPay 歐付寶ECPay 綠界科技(同一介面,僅 API 主機不同)。
  • 同時支援 SHA256(推薦)與 MD5 兩種 CheckMacValue 加密方式,可在付款設定檔中切換。
  • 後台「OPay 訂單管理」介面,可:
    • 依訂單編號、會員、狀態進行搜尋
    • 檢視單筆訂單詳情、原始回傳資料、相關交易記錄
    • 手動成立訂單(觸發 XenForo 的升級開通或商品交付流程)
    • 手動取消訂單
    • 向 OPay 申請退刷 / 退款(信用卡走 DoAction(R)、ATM/CVS 走 AioChargeback
    • 即時向 OPay 查詢訂單狀態QueryTradeInfo),並自動回填 TradeNo / 自動同步「已付款」狀態
  • 後台「連線測試」工具:以您的設定向 OPay 送出一筆刻意不存在的訂單編號,立即驗證 MerchantID / HashKey / HashIV / 加密類型 / API 端點是否全部正確,免去反覆送真實訂單測試。
  • 後台訂單檢視頁附「診斷資訊」區塊:顯示該筆交易實際使用的服務商、環境、加密類型、API 端點、對應廠商後台連結,疑難排解一目了然。
  • OPay 回傳明確失敗(RtnCode != 1)且 CheckMacValue 驗證通過時,自動把訂單標記為 failed,並寫入錯誤碼與訊息,後台不會卡在「待付款」。
  • 完整的 CheckMacValue 雙向驗證(採 hash_equals 常數時間比對,避免時序攻擊)。
  • 自訂資料表 xf_yucts_opay_transaction,與 XenForo 內建 xf_payment_provider_log 互相對應。
  • 內建每日 04:15 排程,自動清理過期的 pending / failed / cancelled 紀錄,paidrefunded 永久保留以利對帳。
  • 除錯模式:開啟後將所有 OPay 通訊內容寫入專屬檔案 internal_data/yucts_opay_debug.log不污染 XenForo 伺服器錯誤日誌。
  • 全繁體中文介面與用語。

支援的付款方式

付款方式 OPay 代號 後台手動退款
信用卡 Credit 退刷(DoAction(R)
網路 ATM WebATM 廠商通知退款(AioChargeback
ATM 虛擬帳號 ATM 廠商通知退款(AioChargeback
超商代碼 CVS 廠商通知退款(AioChargeback

註:本版本不支援信用卡定期定額(Recurring)。若您僅以 XenForo 內建「使用者升級」做單次或可重複續購之升級,本套件已可完整支援。


系統需求

  • XenForo 2.3.0 以上
  • PHP 7.4 以上(建議 8.0+)
  • 必要 PHP 擴充:curl, mbstring, hash, json
  • 一組有效的 OPay 或綠界 ECPay 特店帳號(含 MerchantID / HashKey / HashIV

安裝步驟

方式一:以 ZIP 安裝

  1. 下載本倉庫的 ZIP(或 Release 包)。
  2. 將壓縮包中的 src/ 目錄解壓上傳至您 XenForo 站點的根目錄,會自動合併至既有的 src/addons/ 結構。最終路徑必須為:
    <您的 XF 根目錄>/src/addons/YUCTS/Opay/addon.json
    
  3. 進入 XenForo 後台:附加元件 → 安裝可用的附加元件,找到「OPay 歐付寶 (台灣金流)」並按下安裝。

方式二:以 Git 部署

cd /path/to/your-xenforo/src/addons
mkdir -p YUCTS
cd YUCTS
git clone https://github.com/PomeloSky/XenForo-Opay.git Opay
# 注意:此倉庫 src/addons/YUCTS/Opay 才是 addon 本體

或更乾淨的作法:

git clone https://github.com/PomeloSky/XenForo-Opay.git /tmp/xf-opay
cp -r /tmp/xf-opay/src/addons/YUCTS /path/to/your-xenforo/src/addons/

後台設定

1. 申請或登入 OPay / 綠界後台

取得三個關鍵憑證:

  • 特店編號 MerchantID
  • HashKey
  • HashIV

測試環境請使用 OPay / 綠界提供的測試專用憑證;上線前請務必切換為正式環境並填入正式憑證。

2. 建立付款設定檔

進入 後台 → 設定 → 付款方式 → 新增付款設定檔,選擇「OPay 歐付寶 (台灣金流)」,依序填寫:

設定 說明
顯示標題 例如「信用卡 / ATM / 超商付款」
特店編號 (MerchantID) OPay/綠界提供(系統會自動 trim 前後空白)
HashKey / HashIV OPay/綠界提供(系統會自動 trim 前後空白)
服務商 OPay 或 ECPay(決定 API 主機)
環境 上線前請以 Stage 測試環境完成端對端驗證
CheckMacValue 加密方式 預設 SHA256(2017 年起所有新 OPay 帳號的標準)。若您是早期 OPay 帳號收到 CheckMacValue 不符錯誤,再切到 MD5 試試。
允許的付款方式 至少勾選 1 項。建議直接全選四種讓 OPay 顯示收銀台選單;僅勾 1 項則直接導向該付款方式
ATM 繳費期限(天) 1~60,預設 3
超商代碼繳費期限(分鐘) 60 ~ 43200(30 天),預設 10080(7 天)

3. 將付款設定檔指派給使用者升級

後台 → 使用者 → 使用者升級,在升級項目中勾選剛才建立的 OPay 付款設定檔。

4. (可選)調整全域選項

後台 → 設定 → 選項 → OPay 歐付寶

  • 交易記錄保留天數:超過此天數的 pending / failed / cancelled 紀錄會在每日 04:15 自動清除(最少 7 天)。
  • 啟用除錯模式:將每一次與 OPay 的請求、回應內容寫入 internal_data/yucts_opay_debug.log,可用於診斷 CheckMacValue 不符等問題;上線後請關閉。
    • 日誌不會寫入 XenForo「伺服器錯誤日誌」,僅寫入專屬檔案,避免污染錯誤頁面。

後台訂單管理

進入 後台 → OPay 歐付寶,可看到三個子頁面:

訂單管理 /admin.php?opay/orders/

動作 說明
訂單列表 可依「商店訂單編號」、「會員」、「狀態」搜尋並分頁。
檢視訂單 顯示完整訂單欄位、診斷資訊區(本筆交易實際使用的服務商/環境/加密類型/API 端點/廠商後台連結)、最近一次 OPay 回傳資料、與該訂單相關的 XF 付款日誌。
編輯 可寫入後台備註(不影響 OPay 訂單本身)。
手動成立訂單 將狀態強制設為「已付款」,並透過 XF 標準流程觸發升級開通 / 商品交付。只能對 pendingfailed 狀態執行
手動取消訂單 將狀態改為「已取消」,並寫入交易記錄。只能對 pendingfailed 狀態執行
申請退款 對信用卡呼叫 DoAction(Action=R)、對 ATM/CVS 呼叫 AioChargeback
查詢 OPay 即時打 QueryTradeInfo,回傳結果會寫入 extra_info.last_query;若 OPay 已返回 TradeNo 但本機尚未保存會自動補上;若 OPay 已標記已付款但本機仍 pending(S2S callback 漏接)會自動同步狀態。

交易記錄 /admin.php?opay/logs/

顯示 xf_payment_provider_log 中所有 provider_id = 'opay' 的紀錄,包括 OPay 主動 callback、後台手動操作。

連線測試 /admin.php?opay/test/

最有用的排錯工具。選擇一個 OPay 付款設定檔,按下「送出測試查詢」:

  • 後端自動產生一個刻意不存在的 MerchantTradeNoPING + 11 hex
  • 以您設定的 HashKey/HashIV/加密類型,向 OPay 送出 QueryTradeInfo/V5
  • 顯示原始回應與 CheckMacValue 雙向驗證結果

正常結果TradeStatus=10200047(查無此訂單)+ CheckMacValue 驗證通過 → 表示您的整合設定 完全正確失敗結果:「CheckMacValue 驗證失敗」或「找不到特店」→ 直接告訴您 MerchantID / HashKey / HashIV / 加密類型 哪裡有錯,免去反覆送真實訂單測試。

所有後台操作的共通性

  1. 同步寫入 xf_payment_provider_log(與 xf_yucts_opay_transaction.extra_info
  2. 帶上「執行者使用者名稱」與「備註」欄位
  3. yuctsOpayManage 管理員權限保護

付款流程說明

[使用者]                [XenForo]                [OPay]
  │
  │ 1. 在 /account/upgrades 按下「購買」(AJAX POST)
  │ ───────────────────────►│
  │                          │ 2. PurchaseController → initiatePayment()
  │                          │    寫入 OpayTransaction (status=pending)
  │                          │    回傳 Redirect → /opay-checkout/{key}/
  │ ◄───────────────────────│
  │
  │ 3. XF AJAX 收到 Redirect → 整頁跳轉到 /opay-checkout/{key}/
  │ ───────────────────────►│
  │                          │ 4. Pub\Controller\Checkout::actionIndex
  │                          │    重建 Purchase → buildCheckoutFormData
  │                          │    回傳極簡 HTML (跳過 PAGE_CONTAINER) +
  │                          │    auto-submit form
  │ ◄───────────────────────│
  │
  │ 5. 表單 POST 到 OPay 收銀台
  │ ──────────────────────────────────────────────►│
  │                                                  │ 使用者完成付款
  │                                                  │
  │                                                  │ 6a. server-to-server
  │                          │ ◄────────────────────│     ReturnURL POST 至
  │                          │    payment_callback.php  (CheckMacValue 驗證)
  │                          │    → completeTransaction → 升級開通
  │                          │    回應 1|OK ───────►│
  │                                                  │
  │                                                  │ 6b. 瀏覽器跨站 POST
  │ ◄──────────────────────────────────────────────│     OrderResultURL
  │                                                       (/opay-return/{key})
  │ 7. 瀏覽器在 /opay-return/{key}/ (公開頁,無需登入)
  │    回傳 HTML 含 meta refresh + JS 同源 GET 跳轉
  │ ───────────────────────►│
  │                          │ → /account/upgrade-purchase (同源 GET,
  │                          │    cookies 帶得出 → 使用者保持登入)
  │ ◄───────────────────────│
  ▼

為什麼要有 /opay-checkout/{key}//opay-return/{key}/ 這兩個中介頁?

  1. /opay-checkout/{key}/ — XF 內建 /account/upgrades 的「購買」按鈕是 AJAX 提交並期待 JSON 回應。如果 initiatePayment 直接回傳含 OPay 表單的 View,AJAX 處理器只會把它當 overlay 處理,自動 submit 永遠不會觸發整頁跳轉。改成回傳 Redirect 後,XF AJAX 會整頁跳轉到這個中介 URL,該頁再用純 HTML form auto-submit 到 OPay。

  2. /opay-return/{key}/ — OPay 在使用者付款完成後,是用 跨站 POST 302 把瀏覽器導向 OrderResultURL。瀏覽器套用 SameSite=Lax 政策時,不會送出 XF 的 session cookie,使用者會被當成未登入。若直接指向 /account/upgrade-purchase 就會看到「請先登入」即使使用者原本就有登入。本套件改把 OrderResultURL 指向「不需要登入」的公開頁 /opay-return/{key}/,該頁回應一張極簡 HTML 用 JS / meta refresh 跳回 /account/upgrade-purchase;此次跳轉為同源 GET,cookies 會正常送出,使用者保持登入狀態。

安全要點

  • 在第 6a 步(S2S callback)收到回傳時,第一件事就是 CheckMacValue 驗證(採 hash_equals 常數時間比對)。驗證失敗將直接以 HTTP 400 拒絕並寫入交易記錄。
  • 金額另以 validateCost()xf_purchase_request.cost_amount 比對,避免攻擊者以小額付款開通大額升級。
  • validateTransaction() 確保同一筆 OPay TradeNo 不會被處理兩次。
  • /opay-return/{key}/ 只負責跳轉,不更新付款狀態;實際結果以 S2S callback 為準。

檔案結構

src/addons/YUCTS/Opay/
├── addon.json
├── Setup.php                     # 安裝 / 解除安裝 / 升級
├── Admin/
│   └── Controller/
│       └── Order.php             # 後台訂單管理控制器
├── Cron/
│   └── Cleanup.php               # 每日清理舊記錄
├── Entity/
│   └── OpayTransaction.php       # ORM Entity
├── Finder/
│   └── OpayTransaction.php
├── Install/
│   └── Data/
│       └── MySql.php             # 資料表 schema 定義
├── Payment/
│   └── Opay.php                  # XF 付款服務提供者本體
├── Pub/
│   ├── Controller/
│   │   ├── Checkout.php          # /opay-checkout/{key}/ 中介頁
│   │   └── Result.php            # /opay-return/{key}/  公開回傳頁
│   └── View/
│       └── Payment/
│           ├── Initiate.php       # 自訂 View:純 HTML auto-submit 至 OPay
│           └── Result.php         # 自訂 View:純 HTML 同源 JS 跳回 XF
├── Repository/
│   └── OpayTransaction.php
├── Util/
│   └── DebugLog.php              # internal_data/yucts_opay_debug.log 寫入
├── Vendor/
│   ├── Sdk.php                   # OPay AIO API 輕量封裝
│   └── SdkException.php
├── _data/
│   ├── admin_navigation.xml
│   ├── admin_permission.xml
│   ├── cron.xml
│   ├── option_groups.xml
│   ├── options.xml
│   ├── phrases.xml
│   ├── routes.xml
│   └── templates.xml
└── hashes.json                   # 套件健康檢查用 SHA-256 清單

倉庫根目錄另附 build/generate-hashes.php:當您修改任何 addon 內檔案後,需要在 commit 前重新產生 hashes.json,否則 XenForo 安裝畫面會跳出「此插件的 hashes.json 文件丟失」或「健康檢查未通過」的警告。

php build/generate-hashes.php

該腳本完全比照 XenForo 內建 \XF\Service\AddOn\HashGeneratorService 的演算法(SHA-256,計算前先移除 \r),輸出與官方一致。

資料表

  • xf_yucts_opay_transaction — 本套件建立。
  • xf_payment_provider — 由 Setup::installStep2() 註冊 ('opay', 'YUCTS\Opay:Opay', 'YUCTS/Opay')
  • xf_payment_provider_log — XenForo 內建,本套件以 provider_id = 'opay' 寫入。

安全性說明

本套件設計時遵循以下原則:

  1. CheckMacValue 雙向驗證:所有對 OPay 發出與從 OPay 接收的請求,都會以 SHA256 / MD5(依設定)計算並驗證 CheckMacValue。回傳驗證採用 hash_equals() 進行常數時間比對,避免時序攻擊。
  2. 金額驗證:回呼處理時除 CheckMacValue 外,另以 validateCost()TradeAmtxf_purchase_request.cost_amount 做整數比對。
  3. 防止重複處理:以 XF 內建 validateTransaction() 機制(依 xf_payment_provider_logtransaction_id + provider_id)防止同一筆 OPay TradeNo 被處理兩次。
  4. 管理介面權限:所有後台動作(檢視、編輯、手動成立 / 取消 / 退款 / 查詢、連線測試)皆強制 assertAdminPermission('yuctsOpayManage')
  5. 表單 CSRF:所有 XF 後台 POST 動作均由 <xf:form> 自動帶上 CSRF token。唯一例外是 /opay-return/{key}/,明確 override checkCsrfIfNeeded() 允許 OPay 跨站 POST;此頁不執行任何寫入「使用者升級狀態」的動作,僅依 OPay 回報 RtnCode 並驗證 CheckMacValue 後標記訂單 failed,實際付款結果仍以 S2S callback 為準。
  6. HTTPS 強制:對 OPay API 的 cURL 呼叫啟用 CURLOPT_SSL_VERIFYPEERCURLOPT_SSL_VERIFYHOST=2
  7. SQL 注入防護:所有資料庫操作均透過 XF Entity / Finder / Schema Manager(參數化查詢)執行。
  8. HashKey / HashIV 防呆:在 verifyConfig 與 SDK 兩端皆呼叫 trim(),避免使用者貼上憑證時夾帶前/後空白導致 CheckMacValue 永遠對不上。
  9. 敏感資料:寫入交易日誌、extra_info 前會主動移除 CheckMacValue 等驗證字段;除錯日誌中 HashKey / HashIV 僅以「前 2 + 中間遮罩 + 後 2 + 長度」呈現。
  10. 除錯日誌獨立檔案:開啟除錯模式後資料寫入 internal_data/yucts_opay_debug.log不會塞進 XF 「伺服器錯誤日誌」造成管理員誤判為錯誤。內部目錄 internal_data/ 應已被 XenForo 預設 .htaccess 拒絕外部直接存取。
  11. 解除安裝清理:移除套件時,會同步刪除所屬資料表與 xf_payment_profile 中以 opay 為 provider 的紀錄,避免後台殘留無效項目。

建議:上線前請先於測試環境完整跑過一輪「下單 → ATM 取號 → 繳費 → 後台手動成立 → 退款」流程。


常見問題

Q1. OPay 與 ECPay 綠界差別? A:兩者共用同一 AIO API(甚至參數名稱、CheckMacValue 算法、回傳格式都完全相同),只是 API 主機網址不同。本套件以單一付款設定即可切換,請依您實際申請的服務商選擇。

Q2. 為什麼回呼後使用者沒有自動升級? A:請依序檢查:

  1. 連線測試先過:後台 → OPay → 連線測試,確認顯示「通過」+ TradeStatus=10200047。若失敗,先解決連線層問題。
  2. 後台 → OPay 歐付寶 → 訂單管理 → 點開該筆訂單。檢視頁的「診斷資訊」區會明確列出此筆交易實際使用的 API 端點與廠商後台連結,請確認與您要查的 OPay 後台是同一個。
  3. 若訂單狀態為 pending,按「查詢 OPay 訂單狀態」即時打 QueryTradeInfo;若回應 TradeStatus=1(已付款)系統會自動同步狀態並開通升級。若回應 TradeStatus=0 + 有 TradeNo,表示 OPay 端有單但使用者未完成付款;若 TradeStatus=10200047,表示 OPay 端沒收到此單(請啟用除錯模式查 internal_data/yucts_opay_debug.log 看 OPay 的拒收原因,例如 RtnCode=10100300 IgnorePayment Error)。
  4. 後台 → OPay 歐付寶 → 交易記錄,看有無 CheckMacValue verify fail 之類錯誤;通常是 HashKey/HashIV 錯誤或正式 / 測試環境憑證錯置。

Q3. 可以對 ATM/CVS 退款嗎? A:可以,但走的是「廠商通知 OPay 退款」(AioChargeback),款項自您的 OPay 餘額退回,不會自動回到買家帳戶——需您另行匯款給買家。信用卡退刷則由 OPay 直接退回原卡。

Q4. 為何不支援定期定額? A:XenForo 內建 User Upgrade 已可由使用者重複續購,且 OPay 定期定額有金額固定的限制,與 XF Recurring 規格契合度低,因此本版本暫不實作。如有需求歡迎於 GitHub 發 Issue 討論。

Q5. 我該選 SHA256 還是 MD5 加密類型? A:強烈推薦 SHA256。OPay 自 2017 年起,所有新申請的特店帳號都預設使用 SHA256,OPay 後台並無「切換 MD5/SHA256」的選項。僅有極少數 2017 年以前申請、且從未升級過的舊特店帳號需要選 MD5。若您不確定,先用 SHA256 試「連線測試」,若顯示「通過」就保持 SHA256;若顯示「CheckMacValue 驗證失敗」再切到 MD5 試。

Q6. 為什麼除錯日誌寫到專屬檔案而不是 XF 伺服器錯誤日誌? A:先前版本曾把每次 OPay 通訊都用 \XF::logError() 寫入「伺服器錯誤日誌」,每筆都顯示為 ErrorException,會讓管理員以為發生致命錯誤。新版改寫入 internal_data/yucts_opay_debug.log,既能保留診斷資料又不污染錯誤日誌。internal_data/ 已被 XenForo 預設 .htaccess 拒絕外部存取。


疑難排解

安裝後付款選單看不到 OPay

  • 確認 src/addons/YUCTS/Opay/addon.json 存在且未損毀。
  • 後台「附加元件」中本套件狀態須為 已啟用
  • 嘗試後台 → 工具 → 重建 → 重建主要快取。

「OPay 付款服務商未正確安裝」

  • 進入後台「附加元件」,對本套件按下「升級」即會重新註冊 xf_payment_provider

Callback 回傳 400 / CheckMacValue verify fail

  • 檢查 HashKey / HashIV 是否與目前環境(Stage / Production)相符。
  • 檢查您的 web server 是否在中間有對請求做任何 URL Rewrite / Body 改寫(如 mod_security 移除 +)。
  • 後台 → 設定 → 選項 → OPay 歐付寶 → 啟用除錯模式;重新測試後檢查 internal_data/yucts_opay_debug.log,內含完整的請求 / 回應 raw 資料。

使用者完成付款回站後顯示「請先登入」

  • 此情形多半發生在使用者瀏覽器套用 SameSite=Lax 政策時,OPay 跨站 POST 不會帶出 XF session cookie。
  • 本套件 v1.0.0 起預設將 OrderResultURL 指向公開的 /opay-return/{key}/,由該頁以同源 GET 跳轉回 /account/upgrade-purchase,已可避免此問題。
  • 若您升級自更舊版本,請:
    1. 後台 → 工具 → 重建 → 重建路由
    2. 在 OPay / ECPay 後台「結帳網址」設定中,確認沒有自行覆蓋 OrderResultURL。

連線測試 (admin → OPay → 連線測試) 通過,但實際購買時 OPay 仍不建立訂單

這是最關鍵也最常見的情境:本套件「連線測試」可通過(CheckMacValue 演算法、HashKey/HashIV、加密類型、API 端點全部驗證 OK),但使用者點購買 → OPay 短暫顯示頁面 → 沒看到付款表單 → 跳回站內,OPay 後台也查不到訂單(TradeStatus=10200047)。

這代表 SDK 與基本身分驗證沒問題,OPay 是在「checkout 階段」拒收,常見原因:

  1. 信用卡功能尚未在 OPay 帳號上啟用 — 多數新申請的 OPay 特店帳號只有 ATM / CVS 預設可用,信用卡需另外向 OPay 申請。如果您的「允許的付款方式」只勾了「信用卡」,OPay 會拒收。

    • 驗證方式:到後台 → 設定 → 付款方式 → 編輯該 OPay 設定檔 → 勾選 ATM 與 CVS → 儲存 → 重新測試購買,OPay 應該會顯示收銀台選單(ALL 模式)
    • 若 ATM / CVS 可以正常進入付款頁、只有信用卡進不去,就是信用卡未啟用,請聯絡 OPay 客服開通
  2. 回傳 URL 沒有在 OPay 廠商後台白名單中 — 部分嚴格設定的特店帳號會限制 ReturnURL / OrderResultURL 必須事先註冊

    • 解法:登入 OPay 廠商後台 → 「系統介接設定」或「回傳網址設定」→ 把您網站的網域(如 https://yourdomain.com)加入白名單
  3. 特店帳號仍在「資料審核」階段 — 即便能成功收到 QueryTradeInfo 回應,正式環境的 AioCheckOut 必須等到帳號完成所有合約 / 簽證才會開放

    • 解法:登入 OPay 廠商後台檢查帳號狀態,必要時聯絡 OPay 客服
  4. 正式環境用測試卡 — OPay 正式環境只接受真實的信用卡;用測試卡(如 4311-9522-2222-2222)會被銀行端拒絕,OPay 不會建立訂單。請用真實信用卡刷小額(例如 1 元)測試

請依下列順序排查

  1. 後台 → OPay → 連線測試 → 確認通過 (✅ 您已通過)
  2. 修改付款設定檔的「允許的付款方式」→ 勾選所有四種(信用卡 + WebATM + ATM + CVS)→ 儲存
  3. 重新進入 /account/upgrades 點購買 → 觀察 OPay 收銀台是否出現選單
  4. 分別選 ATM 或 CVS 試試取號(這兩種通常預設啟用且不需真實付款即可確認流程)
  5. 若 ATM/CVS 可取號但信用卡仍跳回,致電 OPay 客服 02-2655-1775,告知:

    「我已完成 API 串接(使用 QueryTradeInfo 可正常驗證 CheckMacValue),但實際送出 AioCheckOut Credit 訂單後 OPay 端不建立訂單,請問是否帳號的信用卡功能尚未啟用?」

OPay / ECPay 廠商後台找不到測試訂單,但本套件的「訂單管理」卻有記錄

這是測試時最常見的「自以為失敗」狀況。請依下列流程排查:

  1. 後台是否真的查無? 進入後台 → OPay 歐付寶 → 訂單管理 → 點開該筆訂單 → 點「向 OPay 申請查詢 OPay 訂單狀態」(actionQuery)。
    • 若回應 TradeStatus=10200047 (查無此訂單):表示 OPay 端真的沒有此單,本套件送出時即被拒。請啟用除錯模式重新測試一次,並提供 internal_data/yucts_opay_debug.log
    • 若回應 TradeStatus=0 (尚未付款) 且 TradeNo 有值:表示 OPay 端有此單只是使用者尚未完成付款。OPay 廠商後台預設可能僅顯示「已付款」訂單,請:
      • 切換訂單狀態篩選為「全部」或「未付款」
      • 或直接以 OPay 回傳的 TradeNo 在 OPay 後台搜尋
      • 或以「商店訂單編號」(我們的 YS......) 搜尋
  2. 後台連結是否正確? 訂單檢視頁右下的「診斷資訊」區會直接列出該筆交易實際使用的 API 端點與對應的廠商後台連結 (OPay 用 vendor.opay.tw、ECPay 用 vendor.ecpay.com.tw)。請確認您登入的是同一個。
  3. 正式環境的信用卡測試: 若您在正式環境用「測試卡號」付款,OPay 會拒絕該筆交易,後台不會收到任何記錄。OPay 測試卡號只能在 Stage 測試環境使用。

使用者本來就有同款升級時卡在「無效的付款請求」

  • 本套件 v1.0.0 起,若 canPurchase() 因「使用者已擁有」而擋下,會自動 fallback 以 getPurchaseObject() 重建 Purchase,讓使用者完成付款(XF 對重複升級多半是冪等延長到期日)。
  • 若您仍卡住,請啟用除錯模式並檢查 internal_data/yucts_opay_debug.log

版本歷史

1.0.0(2026-05-25)

核心

  • 完整實作 XenForo 2.3 \XF\Payment\AbstractProvider,含 initiatePayment / setupCallback / validate* / getPaymentResult / completeTransaction
  • 同時支援 OPay 歐付寶(payment.opay.tw)與 ECPay 綠界(payment.ecpay.com.tw),可一鍵切換。
  • 支援 SHA256(預設)與 MD5 兩種 CheckMacValue 加密類型。
  • 支援信用卡 / WebATM / ATM / CVS 四種付款方式;自動依勾選數量決定 ChoosePayment (單選 → 直接該方式;多選 → ALL + 正確的 IgnorePayment)。

後台

  • 訂單管理:搜尋、檢視(含診斷資訊區塊)、編輯備註、手動成立、手動取消、退款、即時 QueryTradeInfo 查詢、查詢結果自動回填 TradeNo 與已付款狀態。
  • 交易記錄頁。
  • 連線測試頁(送出測試 QueryTradeInfo 驗證設定完全正確)。
  • 全繁體中文介面,含 OPay 回應欄位中英對照與 TradeStatus 代碼自動翻譯。
  • 每日 04:15 排程自動清理過期 pending / failed / cancelled 紀錄。

設計

  • AJAX 攔截處理:initiatePayment 回傳 Redirect 到 /opay-checkout/{key}/ 中介頁,由該頁吐出純 HTML auto-submit 表單到 OPay,避免被 XF AJAX 處理器當成 overlay 卡住。
  • 跨站 cookie 處理:OrderResultURL 指向公開的 /opay-return/{key}/,該頁不要求 cookie / 登入,並以同源 GET 跳轉回 /account/upgrade-purchase,避免 SameSite=Lax 政策導致使用者「付款後變未登入」。
  • OPay 失敗自動標記:當 OPay 透過 OrderResultURL 回報 RtnCode != 1 且 CheckMacValue 驗證通過,自動把訂單標記為 failed 並寫入錯誤碼。
  • canPurchase() fallback:若使用者已擁有同款升級導致 canPurchase 失敗,自動改以 getPurchaseObject() 重建 Purchase,讓使用者完成付款。

安全

  • CheckMacValue 雙向驗證(採 hash_equals 常數時間比對)。
  • HashKey / HashIV 兩端 trim,避免使用者貼上時夾帶空白導致永遠對不上。
  • 金額用 validateCost()xf_purchase_request.cost_amount 整數比對。
  • validateTransaction() 防止同筆 OPay TradeNo 被處理兩次。
  • 所有後台操作受 yuctsOpayManage 管理員權限保護。
  • Pub\Controller\Result 明確 override checkCsrfIfNeeded() 允許 OPay 跨站 POST,不影響其它 XF 路由的 CSRF 保護。

除錯

  • 開啟除錯模式時所有 OPay 通訊寫入 internal_data/yucts_opay_debug.log不污染「伺服器錯誤日誌」)。
  • CheckMacValue 計算過程的 raw 字串長度、HashKey/HashIV 遮罩、最終 hash 都會記入除錯日誌。

已知歷史 bug 與修正

  • IgnorePayment 不可塞入 OPay 不認得的方法名(如 BARCODE / ApplePay / TWQR,這些是新版 ECPay 才有),否則 OPay 會回 RtnCode=10100300 IgnorePayment Error. 並拒收訂單。修正後 IgnorePayment 僅在本套件提供的 4 種付款方式之間取差集。
  • Phrase 標題只能含一個 .;模板 ?: 表達式必須在 {{ }} 雙花括號內;filter 名稱是 to_upper 而非 upper

回報問題與支援

  • 主要支援平台:YUCTS 論壇 https://forum.yucts.com
  • 程式問題請於 GitHub Issues 提出。
  • 提報問題時請盡可能提供:
    • XenForo 版本
    • PHP 版本
    • 本套件版本
    • 是否為 OPay / ECPay、Stage / Production
    • 後台 → OPay → 交易記錄 中的對應錯誤訊息(請先去除 MerchantID / HashKey / HashIV 等敏感欄位)

授權

本專案以 MIT License 授權釋出。

OPay AIO API 的歸屬及商標權屬於歐付寶第三方支付股份有限公司。ECPay 綠界 AIO API 的歸屬及商標權屬於綠界科技股份有限公司。本套件僅為與其官方 API 介接之第三方整合工具,與兩家公司無從屬關係。

About

XenForo 2.3 OPay (歐付寶) / ECPay (綠界) AIO 金流整合套件。支援信用卡 / WebATM / ATM / CVS,含完整後台訂單管理 (檢視 / 搜尋 / 手動成立 / 取消 / 退款 / 即時查詢)。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages