Repository navigation
v3.5.20 綠界物流:COD 改單後靜默不代收、前台看不到宅配托運單號
本版修正兩個綠界物流的問題,其中 #132 會直接造成商家金錢損失。
一、貨到付款改單後重建物流單,代收貨款靜默消失(#132)
貨寄出、買家到店取走,但綠界沒有代收貨款,而後台從頭到尾沒有任何提示或警告,商家通常要到對帳才發現。
客戶實際回報的案例,同一筆訂單改單後重開物流單,綠界後台匯出的紀錄:
| 第一張 | 第二張(改單後) | |
|---|---|---|
| 綠界物流編號 | 49811043 | 49814128 |
| 訂單金額 | 689 | 680 |
| 純配送/貨到付款 | 貨到付款 | 純配送 |
| 物流代收款項 | 689 | 0 |
| 物流狀態 | 訂單超過驗收期限 | 買家已到店取貨 |
WooCommerce 訂單本身的付款方式自始至終都是「貨到付款」。
根因:代收判斷被鎖在第一張物流單,且欄位沒有預設值
if (count($shipping_list) == 0) { // ← 只有第一張物流單才會進來
if ($order->get_payment_method() == 'cod') {
$args['IsCollection'] = 'Y';
...
}
}
if ($collection == true) { // ← 只有選「代收貨款」動作才補回來
$args['IsCollection'] = 'Y';
...
}第二次建立時 count($shipping_list) 已不是 0,整段自動判斷被跳過。若管理員選的是一般的「取得新的綠界物流編號」($collection 為預設 false),IsCollection 從頭到尾沒有被設定,而 $args 初始陣列也不含這個 key —— 欄位完全不在送往綠界的 payload 裡。
綠界官方文件(developers.ecpay.com.tw/8809.md)載明 IsCollection 為選填、未帶時預設 N,所以綠界以純配送建單,不報錯、不警告。後台兩個動作的名稱(「取得新的綠界物流編號」/「…(代收貨款)」)差異不明顯,很容易選錯。
欄位缺席還有一個連帶症狀:程式後續讀取未定義的 $args['IsCollection'] 寫入訂單 meta,PHP 8 噴 Undefined array key warning 並存入 null,後台 meta box 的代收欄因此恆顯示 No —— 這是商家唯一能看到的線索,但幾乎沒人會注意。
修正內容
$args初始陣列明確帶入IsCollection = 'N'、CollectionAmount = 0,杜絕欄位缺席- 代收判斷改為
true === $collection || 'cod' === 付款方式,不再受「是否為第一張物流單」影響 - 已有物流單又建立代收單時,寫入訂單備註「此訂單已有物流單,本次再次建立代收貨款物流單,請確認代收金額是否重複。」
取捨說明:原本的 count == 0 護欄用意應是「補寄第二箱時不重複代收」。改動後這個情境會變成第二箱也帶代收,故補上訂單備註提醒。之所以選擇這個方向 —— 靜默不代收是純損失且到對帳才知道,重複代收商家當場看得到備註、也能處理。
二、多件包裹取號時第一、二張都代收全額(附帶發現)
if ($i > 01) { // 01 是八進位字面值,實際等於 1no_count >= 3 的多件包裹取號時,第 1、2 張都會帶全額 CollectionAmount,與 specs/ecpay-shipping.feature 的「僅第一張為代收貨款」不符。這是與 #132 相反方向的錢的問題。已改為 $i > 0。
三、客戶在訂單查詢頁看不到物流單號(#133)
前台「我的帳戶 → 檢視訂單」中,「綠界物流資訊/物流單號」的標題出得來、單號欄位空白,但同一筆訂單在後台看得到單號。
根因:宅配托運單號在 BookingNote,前台只讀超商欄位
不是 meta key 不符,也與 HPOS 無關(前台已使用 $order->get_meta())。
綠界宅配(黑貓/郵局)的托運單號存在 BookingNote,超商取貨才是 PaymentNo + ValidationNo。前台只處理超商那兩個欄位,而且用 isset() 判斷 —— 宅配時這兩個 key 一定存在、值為空字串,isset() 仍為 true,於是陣列被塞進一個只有空白的字串,count() > 0 成立,標題與表格照印而儲存格空白。
後台訂單列表與 meta box 都有 BookingNote 分支,唯獨前台沒有,前後台因此表現不一致。
修正內容
改前 ┌──────────┐ 改後 ┌─────────────┐
│ 物流單號 │ │ 物流單號 │
├──────────┤ ├─────────────┤
│ │ ← 空白 │ 90012345678 │ ← BookingNote
└──────────┘ └─────────────┘
isset()改為! empty(),空字串不再視為有值- 新增
BookingNote分支顯示宅配托運單號 - 超商 B2C 只有
PaymentNo時以trim()去掉尾隨空白 - 三個欄位皆空時略過整筆,不再出現「孤零零的標題配空白格」
刻意不加「退回顯示 AllPayLogisticsID」的 fallback:該編號是綠界內部交易編號,客戶拿它到超商或黑貓查不到,顯示出來只是把空白換成噪音。
驗證
新增 11 個 PHPUnit 整合測試:
tests/phpunit/integration/EcpayShippingCollectionTest.php(6 個,含 #132 迴歸與八進位迴歸)tests/phpunit/integration/PublicOrderShippingNumberTest.php(5 個,含 #133 迴歸、B2C 尾隨空白、全空不輸出)
與既有 EcpayCallbackTest / EcpayRefundTest / ShippingMethodTest 一起執行:OK (37 tests, 115 assertions)。
紅燈驗證:把兩個修補檔還原成修復前版本重跑,7/11 個新測試如預期失敗,確認測試確實鎖住這兩個 bug 而非空測。phpcs 對照修改前 baseline 無新增違規。
升級後注意
- 貨到付款訂單重建物流單時,無論選哪一個後台動作都會代收貨款。若原本習慣用「取得新的綠界物流編號」來刻意建立不代收的補寄單,改版後需留意新增的訂單備註並自行確認金額
- 前台原本空白的物流單號欄位,宅配訂單會開始顯示托運單號;尚未取得單號的訂單則整塊不顯示(原本會顯示空白表格)
- 其他物流商(藍新、速買配、立吉富)已檢查,無相同 pattern,行為不變