Repository navigation
v3.5.21 PayUni V2 信用卡 3D:付款成功卻掉單(已扣款、訂單被逾期取消)
PayUni V2 信用卡 3D 驗證:付款成功卻掉單(issue #127)
影響對象:使用 PayUni V2 信用卡(payuni-credit / payuni-credit-installment / payuni-credit-subscription)且 3D 驗證為開啟(payuni_3d_auth,預設就是開啟)的站台。未設定 woocommerce_payuni-credit-v3_settings 即為 V2。
問題
送往 PayUni 的參數只帶 ReturnURL、沒帶 NotifyURL,網站能否知道交易成功 100% 綁在「PayUni 用顧客瀏覽器把人導回」這一步。顧客只要付完款關閉分頁(或 LINE / FB 內建瀏覽器導回失敗、行動網路中斷、按上一頁),網站就永遠收不到結果:
- 訂單停在「等待付款中」,數日後被「未付款訂單逾期取消」清掉
- 錢已經收了(PayUni 端已付款 → 已請款 → 已入帳)
- 顧客沒拿到商品/課程權限,發票也沒開
顧客重試時 PayUni 回 CREDIT04001 已存在相同商店訂單編號,舊版直接開新訂單重刷,等於放掉前一筆已成交的錢。
回報案例中有一筆 NT$16,800 的訂單確實被扣款,站上訂單卻遭自動取消。
修正
- 補送
NotifyURL(一般交易與 5 元綁卡兩條路徑),指向獨立端點wc-api/payuni_notify_card_bg。幕後通知由 PayUni 伺服器直送,不受顧客行為影響。 - 付款完成冪等保護:通知與導回兩邊都會進來,以「值為訂單自身 ID 的戳記」+ 資料庫原子鎖擋重複,避免重複開發票/重複寄信/重複發權限。戳記刻意不用「meta 有沒有值」判斷——
woomp_copy_order()與 WooCommerce Subscriptions 都會整包複製訂單 meta。 - 待付款補償對帳器:幕後通知仍可能漏收,送出後 180 / 900 / 2700 秒三階遞增反查,
TradeStatus=1且金額相符才補完訂單。僅自動補完pending;已取消/失敗的訂單查到已付款時只寫入告警備註,不改狀態(避免庫存已回補後自動完成造成超賣)。 CREDIT04001先反查再決定:確認前次交易已成功就補完原訂單,不再開新單重刷。- 連帶修掉:3D 情境下顧客關閉分頁時,5 元綁卡的退刷排程過去永遠不會被排,那 5 元實際上沒退。
緊急開關
上線後若 PayUni 對 NotifyURL 有非預期行為,可用 filter 單獨停送,不必回退整包(停送後回到舊行為,掉單風險回升但不會有重複通知):
add_filter( 'woomp_payuni_v2_enable_notify_url', '__return_false' );站方自檢
撈出「送出 3D 後石沉大海」的訂單:_payuni_is_3d_auth = yes、狀態為 pending / cancelled / failed,且訂單備註中沒有任何含 status: 的 PayUni 回應,再逐筆向 PayUni 反查(唯讀)。CloseStatus 是請款/關帳狀態,不能拿來判斷授權是否成功。
驗證與已知限制
整合測試 307 全數通過(前一版基線 253)。尚未於 PayUni sandbox 進行真實 3D 流程實測,以下四項有待正式環境確認:NotifyURL 帶 path segment 是否被接受、回應 "1" 後是否停止重送、幕後通知與瀏覽器導回的實際時間差、/trade/query 對 V2 交易的回傳欄位。
Closes #127