專案

一般

配置概況

動作

Bug #1394

進行中

[HQ/Branch Bug] 同門牌成員停止充電遭拒但 LIFF 誤顯示成功

是由 陳國瑋6 天 前加入. 於 5 天 前更新.

狀態:
In Progress
優先權:
High
被分派者:
-
開始日期:
2026-07-28
完成日期:
預估工時:

概述

h2. 問題現象

CT3 現場 CP001-002 發生以下情況:

  • User 1 開始充電。
  • 同門牌的 User 2 從 LINE LIFF 點擊停止充電。
  • LIFF 顯示停止成功,但設備未斷電,充電持續進行。

h2. 現場調查結果(2026-07-28)

  • User 1 與 User 2 的 unit_no 相同。
  • 兩人使用不同 IdTag,但 IdTag 的 parent_id_tag 相同。
  • 兩人都已經由 e_connector_user 綁定 CP001-002。
  • User 1 啟動的 transaction 17 於 15:28:27 進入 ACTIVE。
  • User 2 在 15:29:05、15:29:29、15:29:49、15:29:56、15:33:51 共發出五次停止請求。
  • Branch 五次皆記錄 transaction ownership mismatch
  • 失敗請求沒有建立 STOP 類型的 e_remote_transaction_log,charge_point 端也完全沒有收到 transaction 17 的 RemoteStopTransaction
  • 15:38:18 檢查時 transaction 17 仍為 ACTIVE、CP001-002 仍為 CHARGING。
  • User 1 在 15:20:54 曾成功停止上一筆 transaction 16,設備正常斷閘並送出 StopTransaction,因此可排除 CP 停止功能或 OCPP 通訊故障。

h2. 根因一:Branch 目前只允許交易本人停止

RemoteChargingSupport.remoteStopWithTransaction() 會把 transaction IdTag 解析成 owner user ID,並與請求的 user ID 做 exact match。

目前不會因為以下條件而允許停止:

  • 同一 unit_no
  • 同一 parent_id_tag
  • 兩人皆綁定同一 Connector

特殊系統 operator 除外。

相關程式:

java/ems_branch/src/main/java/com/sylksoft/ems/branch/service/charging/RemoteChargingSupport.java

h2. 根因二:HQ 把 Branch 業務失敗覆寫成成功

Branch 停止 API 以 HTTP 200 回傳 business response;授權失敗時 response 內容為 isSuccess=false

HQ 的 ConnectorBranchApiHandler.handleStopCharging()

先以 BranchApiResponse.isSuccess() 判斷 HTTP 呼叫是否成功。

HTTP 200 時取得 Branch response。

隨後無條件呼叫 resp.markSuccess("停止充電(Branch API)成功")

原本的 isSuccess=false、errorCode 與 message 因此被清除。

LIFF 本身已會在 isSuccess=false 時顯示錯誤;但收到 HQ 覆寫後的 true,所以顯示「充電已停止」。

相關程式:

  • java/ems_hq/src/main/java/com/sylksoft/ems/hq/api/connector/ConnectorBranchApiHandler.java
  • java/ems_hq/src/main/java/com/sylksoft/ems/hq/service/BranchApiService.java
  • react/web/app/charger/hooks/use-connectors.ts

h2. 版本沿革

  • 2025-08 初版只檢查 transaction IdTag 是否屬於任一住戶,未核對請求者;行為過度寬鬆,並非明確的同門牌授權。
  • 2026-01-08 充電流程重構後改成 exact transaction owner 才能停止。
  • 2026-01-23 HQ RespBase 重構加入上述 markSuccess(),形成 HTTP 成功覆寫業務失敗的問題。

h2. 必須先確認的業務規則

請確認同門牌/同一 IdTag family 的成員是否應可互相停止充電:

  • 若「可以」:Branch 應驗證同門牌或同一 IdTag family,並同時確認請求者具有該 Connector 操作權。
  • 若「不可以」:LIFF 必須針對非 transaction owner 停用停止按鈕,並顯示「僅啟動充電者可停止」等明確訊息。

無論採哪一種規則,HQ 覆寫 Branch 業務失敗的問題都必須修正。

h2. 驗收條件

  • Branch 回傳 HTTP 200 + isSuccess=false 時,HQ 與 LIFF 必須保留失敗狀態、errorCode 與 message。
  • 沒有實際 dispatch RemoteStopTransaction 時,LIFF 不得顯示停止成功。
  • User 1 啟動後,User 2(同門牌)的停止結果符合已確認的業務規則。
  • 不同門牌使用者不得停止他人交易。
  • transaction owner 可以正常停止。
  • LIFF 停止按鈕的 enabled 狀態與後端授權規則一致。
  • E2E 驗證 Branch remote transaction log、OCPP RemoteStopTransaction、charge_point 斷閘、StopTransaction 與 transaction COMPLETED 狀態。
動作

匯出至 Atom PDF