POST /users/update_auto_refill.json

狀態

已補 action / routing / PHPUnit;legacy / new staging success path 已驗證。

這支 API 主流程只負責更新使用者的自動儲值方案設定;不在此 API 直接刷卡、不建立 transaction、不寫 event queue。

操作路徑

Web 帳號付款設定頁顯示目前自動扣款方案:

https://staging.pro360.com.tw/dashboard/settings

在「自動扣款設定」點「更改方案」後會進入:

https://staging.pro360.com.tw/dashboard/pricing/changing

選擇自動儲值方案或「依實際費用扣款」後儲存,前端送:

POST /users/update_auto_refill.json

前端來源:

檔案行為
/Users/mattsu/Documents/Site/web-app/modules/components/dashboard/account/PaymentSettings.js:101-138顯示目前自動扣款設定,點「更改方案」導到 /dashboard/pricing/changing
/Users/mattsu/Documents/Site/web-app/modules/components/dashboard/PriceView.js:259-289儲存方案時呼叫 `updateRefillPackage(selectedIdRefill
/Users/mattsu/Documents/Site/web-app/modules/components/dashboard/PriceView.js:378-381綁卡完成後也會呼叫 updateRefillPackage() 套用選擇方案。
/Users/mattsu/Documents/Site/web-app/modules/utils/api-manager.js:1257-1268呼叫 /users/update_auto_refill.json;有 package_id 才放進 FormData
/Users/mattsu/Documents/Site/web-app/modules/actions/index.js:272-285呼叫後重新抓 getMeBrief() 更新前端 user info。

Legacy 對照

項目legacy
Controller/Users/mattsu/Documents/Site/get-lancer-php56/app/Controller/UsersController.php:6345-6379
request data helper/Users/mattsu/Documents/Site/get-lancer-php56/app/Controller/AppController.php:1233-1239
JSON response helper/Users/mattsu/Documents/Site/get-lancer-php56/app/Controller/AppController.php:1307-1311
API error handler/Users/mattsu/Documents/Site/get-lancer-php56/app/Controller/AppController.php:1320-1343
generic exception handler/Users/mattsu/Documents/Site/get-lancer-php56/app/Controller/AppController.php:1351-1361
package helper/Users/mattsu/Documents/Site/get-lancer-php56/app/Model/Package.php:11-17

Legacy 流程:

  1. 必須是 JSON request,且 RestApiHelper::hasValidApiSession($this) 通過。
  2. 從 session 取得 user_id
  3. 讀取 flat body 欄位 package_id,不是 User[package_id]
  4. package_id 非空,檢查 packages.id = package_id AND is_active = 1 AND is_auto_refill = 1
  5. 找不到 active auto refill package 時丟一般 Exception('package_id_not_found', 2)
  6. 更新 users.auto_refill_package_id
    • package_id empty 時寫 0
    • package_id 非 empty 時寫該值
  7. {"status":"success","error":0}

Session helper 行為:

  • legacy RestApiHelper::hasValidApiSession() 不加 users.is_active = 1 guard;只要 API key、session row、user row 有效即可。
  • blocked user 會直接回 HTTP 403 + {"error":5,"message":"Blocked User"}
  • legacy session helper 的 DB load path 會更新 users.iphone_last_access / last_access_client,且符合 returned PRO 條件時可能寫 task_queuereturnedQuoteService

New 對照

項目new
EndpointEndpoint/V1/Users.php:885-943 已補 update_auto_refill()
RoutingLib/Common/RouterRule/Mapping.php:100-103 已補 users/update_auto_refill\.json explicit mapping。
package helperLib/Model/Package.php:23-28 已有 getActiveAutoRefillPackageById(),條件與 legacy helper 對齊。
user response fieldEndpoint/V1/Users.php:59-66Lib/Model/User.php:298-306 已包含 auto_refill_package_id,成功後前端 getMeBrief() 可讀到更新值。

已搬移:

  • Endpoint/V1/Users.php::update_auto_refill()
  • Mapping.php explicit route:users/update_auto_refill\.json
  • PHPUnit:tests/UsersUpdateAutoRefillTest.php

Request

成功設定方案:

POST /users/update_auto_refill.json
package_id=<active auto refill package id>

取消自動儲值 / 改成依實際費用扣款:

POST /users/update_auto_refill.json

前端 updateRefillPackage()package_id 為 null / 0 時不送欄位;legacy 會因 empty($package_id) 寫回 0

Response

成功:

{"status":"success","error":0}

Invalid request / invalid session:

{"error":1,"status":"invalid request"}

Invalid package:

legacy 丟一般 Exception('package_id_not_found', 2),會走 handleException(),不是回 error=2

{"error":999,"status":"<err_new_api_999 translated message>"}

Blocked user:

{"error":5,"message":"Blocked User"}

DB Side Effect

table欄位行為
usersauto_refill_package_id更新成 valid package id,或 empty package 時更新成 0
usersmodifiedlegacy User->save() 會更新 modified;new 明確 modified = NOW() 對齊。

Session helper side effect:

table欄位 / row行為
usersiphone_last_access, last_access_clientlegacy session helper DB load path 會更新;new 用 legacy session resolver 保留。
task_queuereturnedQuoteServiceuser 有 active service、quote_service_count > 0iphone_last_access 超過 180 天時才可能寫入。

不應新增的 side effect:

  • 不直接刷卡
  • 不新增 transactions
  • 不新增 stripe_charges
  • 不新增 quote_user_subscription_logs
  • 不新增 event queue / task event queue
  • 不更新 user_permission_preferences.payment_auto_refill
  • 不更新 wallet / debt / credit card customer

Payment 關係

這支 API 只設定 users.auto_refill_package_id。後續真正自動儲值發生在 quote bid / Stripe customer 付款流程讀取這個欄位時:

  • legacy Package::getActiveAutoRefillPackageById() 條件是 idis_auto_refill = 1is_active = 1
  • new Lib/Model/Package.php:23-28 已有同條件 helper。

因此搬移時不可把「設定方案」誤做成「立即扣款」。

測試計畫

PHPUnit 至少覆蓋:

  1. 有效 session + valid auto refill package:更新 users.auto_refill_package_id,response 為 status=success,error=0
  2. 有效 session + empty body:更新 users.auto_refill_package_id = 0
  3. 有效 session + package_id=0:依 legacy empty() 語意更新 users.auto_refill_package_id = 0
  4. inactive user + valid session:不新增 active guard,仍可更新。
  5. 有效 session + inactive / non-auto-refill / missing package:回 legacy-shaped error=999,且不更新 user。
  6. blocked user:回 HTTP 403 + {"error":5,"message":"Blocked User"},且不更新 user。
  7. missing / invalid session:回 error=1,status=invalid request
  8. negative test:確認不寫 transaction / event queue / task event queue,且不更新 user_permission_preferences.payment_auto_refill

local container PHP 8.2:

docker exec -w /project-data cd63f9147e8d vendor/bin/phpunit tests/UsersUpdateAutoRefillTest.php
OK (7 tests, 52 assertions)

Legacy staging 驗證:

  • 2026-07-06 curl package_id=36{"status":"success","error":0}
  • DB 確認 user 8616users.auto_refill_package_id = 36packages.id=36 為 active auto refill package。
  • 當日未看到此 API 直接新增 transactions / event_queue / task_event_queue

New staging 驗證:

  • 2026-07-06 07:44:18 curl 空 body 回 {"status":"success","error":0};request log context 為空 body []
  • 2026-07-06 07:45:50 curl package_id=36{"status":"success","error":0};request log context 有 {"package_id":"36"}
  • DB 確認 session 6htrhsu7n3203fcg5t8maih0h2 對到 user 8616,且 final users.auto_refill_package_id = 36users.modified = 2026-07-06 07:45:50
  • DB 確認 packages.id=36 為 active auto refill package:is_active=1is_auto_refill=1
  • 近 2 小時未看到 user 8616 因本 API 直接新增 transactions / event_queue / task_event_queue
  • 空 body 呼叫後理論上會先寫 0,但第二次 package_id=36 已覆蓋 final DB state;本次只能從 request log 確認空 body 有進入新版 endpoint。

待確認

  • 若要驗證空 body 實際 DB intermediate state,需單獨呼叫空 body 後立即查 users.auto_refill_package_id = 0,再呼叫 package_id=36 還原。