最近更新 API
這份文件只記錄近期更新或需要切換確認的 API 摘要,方便前後端、QA 與 LB 切換時快速對照。
完整 legacy parity、DB side effect、測試結果與切換驗證細節,仍以各 API detail 文件為準。
新的調整一律追加在文件最下面,避免改動既有排序造成 review 時難以判斷新增內容。
POST /quote_bids/want_to_contact_provider/{quote_bid_id}.json
功能說明
消費者在報價列表點選「立即回覆」,進入單一報價頁後,再點選「開始洽談」並選擇快速回覆時,會呼叫此 API。
操作路徑
- 消費者在首頁點選「查看需求」
- 進入報價列表頁:
/dashboard/projects/quotelist/21874 - 點選專家的「立即回覆」
- 進入報價詳情頁:
/dashboard/projects/quote/21874/2147688065 - 點選「開始洽談」
- 選擇快速回覆
- 呼叫 API:
POST /quote_bids/want_to_contact_provider/{quote_bid_id}.json
備註
更新時間:2026-05-20 11:05
POST /quote_bids/consumer_want_provider_quote/{quote_bid_id}.json
功能說明
消費者在新客源 / narrow match 卡片邀請指定專家報價時,會呼叫此 API。
成功後,同一筆 quote bid 會進入 waiting invitation 狀態,並建立 WantProviderQuote activity。
操作路徑
備註
更新時間:2026-05-19
POST /quote_bids/provider_accept_narrow_match/{quote_bid_id}.json
功能說明
專家回應消費者送出的 narrow match invitation 時,會呼叫此 API。
接受邀請時,會把 bid 轉進聯絡 / 扣款主線;拒絕邀請時,會更新 narrow match 狀態並寫對應 activity。
操作路徑
備註
更新時間:2026-05-07
POST /quote_bids/change_status/reviews/{quote_bid_id}.json
功能說明
消費者對已聯絡的專家送出評價時,會呼叫此 API。
一般 review 流程已補齊。completed / closed 狀態流仍拆在另一份文件追蹤,不和一般 reviews 混在一起。
操作路徑
備註
更新時間:2026-05-13
POST /quote_bids/change_status/rating/{quote_bid_id}.json
功能說明
專家送出報價或處理 contact charge / 手動報價付款流程時,會呼叫此 API。
這支是 change_status 裡付款與通知 side effect 較重的 API。
操作路徑
備註
更新時間:2026-05-13
POST /quote_bids/change_status/self_hire/{quote_bid_id}.json
功能說明
專家在已聯絡且進行中的案件中,自行標記已接案時,會呼叫此 API。
操作路徑
備註
更新時間:2026-05-13
POST /quote_requests/copy/{quote_request_id}.json
功能說明
消費者複製既有需求時,會呼叫此 API。
這不是單純複製 quote_requests row,而是拿舊 request 當來源,重新跑一輪建單、fee、summary、異常掃描與配對後處理。
操作路徑
備註
更新時間:2026-04-27
GET /quote_bids/preview_quote_fee/{quote_bid_id}/is_auto_quote:{is_auto_quote}.json
功能說明
專家在送出報價或聯絡前,預覽本次需要支付的費用時,會呼叫此 API。
這支 API 會依照 quote bid、quote request、報價類型與可用折扣,回傳原始費用、實際費用、費用原因與 contact charge 資訊;只做費用預覽,不會扣款,也不會送出報價。
操作路徑
- 專家進入案件列表或案件詳情頁
- 在尚未正式送出報價 / 聯絡前,前端呼叫 API:
GET /quote_bids/preview_quote_fee/{quote_bid_id}/is_auto_quote:{is_auto_quote}.json
備註
手動報價 is_auto_quote:0 時,費用主要來自 quote_requests.manual_fee,並會套用 quote_requests.manual_fee_discount。
manual_fee_discount = 1.0000 代表無折扣;0.8000 代表 8 折;0.6000 代表 6 折。
更新時間:2026-05-22
POST /quote_requests/edit.json
功能說明
消費者在需求成立後,修改「電話可聯絡時間」時,會呼叫此 API。
這支 API 會依照 quote request owner、quote_request_id 與 fields.phone_available_time,更新需求上的電話可聯絡時間,並同步控制是否將電話資訊顯示給 provider;只處理電話可聯絡時間,不會修改需求表單答案、需求摘要、費用、activity 或 notification。
操作路徑
- 消費者進入需求管理或需求詳情頁。
- 在修改電話可聯絡時間後,前端呼叫 API:
POST /quote_requests/edit.json
備註
fields[phone_available_time] 非空時,會寫入 quote_requests.phone_available_time,並設定 quote_requests.is_show_phone_to_providers = 1。
fields[phone_available_time] 為空字串或 trim 後為空時,會寫入原字串,並設定 quote_requests.is_show_phone_to_providers = 0。
成功 response:
{"error":0,"message":"success"}只有香港環境 area = hk 且 quote_requests.match_type in (Multiple, Authorize) 時,才會透過 Redis 60 秒去重後寫入 newQuoteRequest queue;台灣 / local TW 環境不會因這支 API 寫 queue。
更新時間:2026-05-25
POST /quote_bids/want_to_contact_provider_for_call_jwt
POST /quote_bids/call_fee_jwt
功能說明
電話聯絡流程在通話有接通或進入可收費條件後,會由 Twilio / Infobip callback 內部呼叫這兩支 API。
want_to_contact_provider_for_call_jwt 用來保證電話聯絡成功後,仍會進入聯絡 provider 的扣款與 contact side effect 主線。
call_fee_jwt 用來在通話超過免費秒數後,補收電話接通服務費;它只處理電話費 transaction,不直接建立通話狀態。
操作路徑
- consumer 發起電話聯絡。
- Twilio / Infobip callback 更新
quote_bid_calls。 - 通話接通且
DialCallDuration > 0時,callback 呼叫POST /quote_bids/want_to_contact_provider_for_call_jwt。 - 通話超過 180 秒時,callback 計算 call fee 後呼叫
POST /quote_bids/call_fee_jwt。
備註
Load Balancer 要新增兩條精準 path 並切到 PHP 8.2 / pro360_api_82 target group:
/quote_bids/want_to_contact_provider_for_call_jwt
/quote_bids/call_fee_jwt不要使用 /quote_bids/* 或 /quote_bids/want_to_contact_provider*,避免誤切其他 quote_bids API。
完整 LB rule order、切換前後驗證與本地實測結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/call_jwt.md。
更新時間:2026-05-27
POST /quote_bids/switch_to_manual_quote/{quote_bid_id}.json
功能說明
provider 在尚未聯絡 consumer 的 auto quote bid 上,選擇改成自己手動送出報價時會呼叫此 API。
成功後,同一筆 bid 會變成一般手動報價已送出且已付款:is_auto_quote = 0、is_want_to_contact_provider = 1、is_paid_for_subscription = 1、is_contact_charge = 0,並依手動報價規則重算 total_site_fee。付款會寫入 transaction / subscription log;後續會建立 SwitchToManualQuote activity、送出 consumer 收到報價通知,並寫入 counter queue。
操作路徑
- provider 開啟 auto quote / 保證回覆相關案件。
- provider 選擇改用手動報價。
- 若 wallet 不足,可能會帶 TapPay
prime。 - 前端呼叫 API:
POST /quote_bids/switch_to_manual_quote/{quote_bid_id}.json
備註
2026-05-27 正式機 access log 查到 934 筆,已補 action、routing 與 PHPUnit。
web-app 實際呼叫 path 帶 quote_bid_id,body 是 FormData,只有需要 TapPay 時才帶 prime。目前新專案也保留 request body 帶 quote_bid_id 的 fallback;仍需回填正式流量 path 分布。
2026-05-28 staging 新 code 實測:
POST https://api-staging.pro360.com.tw/quote_bids/switch_to_manual_quote/2147689868.json
body: empty FormData
response: {"status":"success","error":0}DB 結果符合 legacy:quote_bids.id = 2147689868 已轉成 manual quote,is_auto_quote = 0、is_want_to_contact_provider = 1、is_contact_charge = 0、is_paid_for_subscription = 1、is_restore_balance = 1,total_site_fee = 160,並寫入 quote_user_subscription_log_id = 20815。
付款路徑是「wallet 不足、有有效 auto quote card、但 unpaid auto quote debt 未達刷卡門檻」:本次新增 transactions.id = 36859、transaction_type_id = 40、amount = 160、real_pay_date = NULL,和同 bid 原 auto quote debt 36858 / 176 合計 debt = 336,未達 quote.auto_quote_max_debt 500,因此 success 但不立即刷卡,符合 legacy processCharge() + chargeByCreditCard() threshold 行為。
side effect 已確認:SwitchToManualQuote activity、AutoQuoteRestoreBalance activity、Receive_Quote event log、request_sent_count / request_requestor_read_count task log 都存在。quote_user_subscription_logs.quote_bid_id 因 signed int 上限顯示為 2147483647,驗證時要以 quote_bids.quote_user_subscription_log_id -> quote_user_subscription_logs.id 為準。
完整 legacy rule、DB side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/switch_to_manual_quote.md。
更新時間:2026-05-28
POST /quote_bids/provider_receive_phone/{quote_bid_id}.json
功能說明
provider 在已送出手動報價後,主動點開 consumer 電話資訊時會呼叫此 API。
成功後,同一筆 quote_bids.id 會標記 is_provider_received_phone = 1;第一次成功時會建立 ProReceivePhone activity。這支不處理付款,不寫 transaction / subscription log,也不送 queue。
操作路徑
- provider 進入案件詳情或 chat。
- consumer phone 可顯示,且前端仍判斷
is_provider_received_phone = 0。 - provider 點開電話資訊。
- 前端呼叫 API:
POST /quote_bids/provider_receive_phone/{quote_bid_id}.json
備註
2026-05-28 正式機 access log 查到 6246 筆,全部 access log status 200。正式流量與 web-app 都使用 path id:/quote_bids/provider_receive_phone/{quote_bid_id}.json。
已補 action、routing 與 PHPUnit,覆蓋 success、idempotent、auto quote guard、closed request guard、refunded guard。staging 已驗證 success response、quote_bids.is_provider_received_phone = 1 與 ProReceivePhone activity。
完整 legacy rule、逐段行數對照與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/provider_receive_phone.md。
更新時間:2026-05-28
POST /quote_bids/edit/{quote_bid_id}.json
功能說明
provider 在案件列表 / 報價卡片標記或取消標記重要案件時會呼叫此 API。
這支只更新 quote_bids.provider_tag,並建立 UpdateQuoteBid activity、更新 my work unread count;不處理付款、transaction、subscription log 或通知 queue。
操作路徑
- provider 進入案件列表或案件詳情。
- provider 點擊標記圖示。
- 前端送出
FormData provider_tag。 - 前端呼叫 API:
POST /quote_bids/edit/{quote_bid_id}.json
備註
2026-05-28 正式機 access log 查到 POST 200 合計 16569 筆,另有 OPTIONS 200 合計 918 筆。
web-app 目前只會送:
provider_tag=favorite
provider_tag=legacy 只檢查 isset(provider_tag),不限制值;空字串會寫入空字串,不是 NULL。
2026-05-29 staging 觀察到部署前 response 是 {"error":0,"message":"success"};這來自 RouterV3::dispatch() 在 action 沒有明確 $this->json() 時補的預設 response,不是 legacy 行為。legacy 與 web-app 成功判斷都要求 message = "Success",新程式已補明確 response,避免大小寫差異造成前端誤判。
完整 legacy rule、web-app caller、逐段對照與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/edit.md。
更新時間:2026-05-29
GET /quote_bids/consumer_want_to_see_more_quote/{quote_request_id}/page:{page}/limit:{limit}.json
功能說明
consumer 在邀請更多專家報價時會呼叫此 API。
這支只讀取同一筆 quote_requests.id 底下仍可被 consumer 邀請的 narrow match bid 清單;不更新 bid / request,不建立 activity、queue、transaction 或通知。真正送出邀請的是 POST /quote_bids/consumer_want_provider_quote/{quote_bid_id}.json。
操作路徑
- consumer 在服務頁或建單後進入「推薦更多專家」流程。
- 前端已有部分推薦 bids;若數量不足目標上限,會補撈更多可邀請 bid。
- 前端呼叫 API:
GET /quote_bids/consumer_want_to_see_more_quote/{quote_request_id}/page:{page}/limit:{limit}.json
備註
2026-05-28 正式機 access log 查到 GET 200 合計 1688 筆,另有 OPTIONS 200 合計 953 筆。
web-app 實際 caller 是 APIManager.getMoreProWithRequest(id, limit = 0, page = 1),path 使用 quote_request_id,不送 body。
legacy 與 new 都只回 narrow match NOT_SEND bids;已用 staging request 22447 對照 legacy response,回傳 bid id、pagination meta 與 nested response id shape 均一致。staging response 對表已完成。
完整 legacy rule、web-app caller、逐段對照、DB 對照與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/consumer_want_to_see_more_quote.md。
更新時間:2026-06-17
POST /quote_bids/add_consumer_survey/quote_bid_id:{quote_bid_id}.json
功能說明
consumer 在案件後續填寫實際支付 / 預算問卷時呼叫此 API。
這支只新增或覆蓋 quote_consumer_surveys;不更新 bid / request,不建立 activity、queue、transaction 或通知。
操作路徑
- consumer 進入案件後續問卷或支付資訊填寫流程。
- 前端收集
total_pay、comment、unit。 - 前端呼叫 API:
POST /quote_bids/add_consumer_survey/quote_bid_id:{quote_bid_id}.json
備註
2026-06-02 正式機 access log 查到 POST 200 合計 598 筆,另有 OPTIONS 200 合計 104 筆。
web-app 實際 caller 是 APIManager.postBudgetSurvey(quoteId, budget, comment, unit),body 是 FormData。legacy 成功 response 是 {"error":0,"status":"success"};bid 不存在回 error=2/status=quote_bid_not_found,不是 request owner 回 error=3/status=not_consumer。
已補 action、routing 與 PHPUnit,覆蓋新增、覆蓋同一筆 survey、缺欄位清成 legacy 預設、bid missing、非 request owner、invalid session。完整 legacy rule、DB side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/add_consumer_survey.md。
更新時間:2026-06-02
POST /quote_bids/provider_request_review/{quote_bid_id}.json
功能說明
provider 在已聯絡 consumer 的案件中,邀請 consumer 留下評價時會呼叫此 API。
成功後會更新 quote_bids.review_requested_at,建立 ProviderInviteReview activity,並寫入 Request_Review event;若 body 有 invite_info,會同步更新 quote_services.invite_info,沒有則沿用既有邀請文字。
操作路徑
- provider 進入已聯絡案件的詳情或 chat。
- 前端判斷尚未邀請評價,且未被封鎖。
- provider 點選「邀請評價」。
- 前端呼叫 API:
POST /quote_bids/provider_request_review/{quote_bid_id}.json
備註
2026-06-01 正式機 access log 查到 POST 200 合計 961 筆,另有 OPTIONS 200 合計 41 筆。
web-app 實際 caller 是 APIManager.requestReviewForBid(bid_id, invite_info),body 是 FormData;invite_info 可省略。若頁面已有 chat room,web-app 會先送 chat message,再呼叫本 API;該 SendChat activity 不屬於本 API side effect。正式流量 caller 包含 iOS app、Android app 與 web。
Config 切換檢查:
- 觸發條件:notification payload 使用
##STAR_ICON##。 - 必要 key:
mail.icon.star_full。 - legacy 正式機值:
https://s3-ap-northeast-1.amazonaws.com/pro360/images/icon/star_full.png。 - new 本地設定:確認
Lib/Common/Configuration.php的ProConfig::$config有同名 key。 - 部署設定:staging / production 的實際 config 也要同步;
Configuration.php被.gitignore忽略,不會隨一般 commit 自動部署。 - 補 mail icon 時,建議以正式機
mail.icon.*區塊為準一次補齊,不要只看本地 legacy checkout。
已補 action、routing 與 PHPUnit,覆蓋 success、沿用既有 invite_info、非 bid owner guard、blocked chat guard。完整 legacy rule、side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/provider_request_review.md。
2026-06-17 new staging 已用 web-app FormData 實測:
POST /quote_bids/provider_request_review/2147691285.json
response: {"error":0,"status":"Success"}DB / queue 已確認:
quote_bids.review_requested_at已更新。quote_services.invite_info已寫入 request body。- 已建立
ProviderInviteReviewactivity 與quote_activity_consumers。 - 已建立
security_hashespublic review hash。 Request_Reviewevent 已被 worker 搬到event_queue_log_3,payload 含INVITE_INFO、STAR_ICON、publicREVIEW_URL,task 包含 MoEngage、push、web push。
同一操作的 SendChat activity 是 web-app 先送 chat message,不屬於本 API side effect。requestor 本次沒有 fetnet_users row,因此沒有 unread counter 可更新。
更新時間:2026-06-17
GET /quote_services/static_fields.json
功能說明
provider 建立 / 編輯服務資料時讀取 static fields。legacy 目前固定回空 StaticFormField,不讀寫 DB。
操作路徑
- provider 進入專家加入頁:
/pro。 - 頁面載入
ProQuestionnairePopupContainer。 componentDidMount()呼叫fetchProQUestionnaire()。- 前端呼叫 API:
GET /quote_services/static_fields.json
也會在 /pro-signup/:slug、/pro-newyear 觸發。這支不是 dashboard 服務編輯頁 /dashboard/profiles... 的主要 API。
備註
2026-06-03 正式機 access log 查到 GET 200 合計 7006 筆,另有 OPTIONS 200 合計 6632 筆。
legacy 成功 response 固定是:
{"StaticFormField":[]}已補 action、routing 與 PHPUnit。完整 legacy rule、side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/static_fields.md。
更新時間:2026-06-03
POST /quote_services/change_status/archive/{quote_service_id}.json
功能說明
provider 在前端刪除公司資料時呼叫。前端文案是「刪除公司」,後端實際行為是把 service 標記為 archived,並同步寫 activity 與 task event。
操作路徑
- provider 進入
/dashboard/profiles或/dashboard/profiles/{quote_service_id}/...。 - provider 在服務資料編輯頁選擇「刪除公司」。
- 前端呼叫
deleteService(),實際送出 API:POST /quote_services/change_status/archive/{quote_service_id}.json
備註
成功 response:
{"error":0,"status":"Success"}已補 action、routing 與 PHPUnit。完整 legacy rule、DB side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/change_status/archive.md。
同一個 legacy change_status 入口還有 profile_ready,已另以獨立文件與測試搬移;不可套用 archive 的簡單狀態更新結論。
更新時間:2026-06-03
GET /quote_services/external_review/link/{quote_service_id}.json
功能說明
provider 進入服務資料編輯頁時呼叫,用來預先取得服務評價邀請連結。前端可見入口是「服務評價」;點進該編輯內容後,內部標題顯示為「推薦」。已有 external_review_url 時直接回傳;空值時會建立 security_hashes,產生短網址並寫回 service。
操作路徑
- provider 進入
/dashboard/profiles/。 - 點選新增專家檔案或進入既有服務資料。
- 前端進入
/dashboard/profiles/{quote_service_id}/0或/dashboard/profiles/{quote_service_id}/...。 ServicesContainer.displayServiceWithIndex()dispatchselectService()後呼叫getExternalReviewLink()。- 服務資料頁「服務評價」入口下的「推薦」內容使用回傳的
short_url,前端 API 為:GET /quote_services/external_review/link/{quote_service_id}.json
正式機流量
2026-06-04 查正式機 access log:
4433 GET /quote_services/external_review/link/{quote_service_id}.json 200
3568 OPTIONS /quote_services/external_review/link/{quote_service_id}.json 200
125 POST /quote_services/external_review/submit.json 200
82 OPTIONS /quote_services/external_review/submit.json 200同一流程另有 POST /quote_services/external_review/invite/{quote_service_id}.json 與 POST /quote_services/external_review/submit.json,已各自拆成 detail doc。
備註
成功 response:
{"error":0,"message":"Success","short_url":"..."}2026-06-04 staging 實測 legacy response 範例:
{"error":0,"message":"Success","short_url":"https://p36.net/sw/NlkXw"}已補 action、routing 與 PHPUnit。完整 legacy rule、DB side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/external_review/link.md。
更新時間:2026-06-04
POST /quote_services/external_review/invite/{quote_service_id}.json
功能說明
provider 對外寄送服務評價邀請 email。request 支援單一 email 與多筆 emails;每個收件人各寫一筆 External_Review event queue,template key 是 390 External Review Invite。
流量與前端狀態
2026-06-04 正式機 quote_services/external_review 統計只看到 link 與 submit,未列出 invite path;web-app 目前也只找到 link / submit caller。仍補 invite 是因為 legacy controller 有完整 invite 分支,且 external_review 已拆成 explicit routes。
Response 與 Side Effect
- invalid session:
{"error":1,"message":"Invalid session"} - 有 session 但無收件人:
{"error":2,"message":"Invalid data"} - success:
{"error":0,"message":"Success"} - legacy 沒有 service owner guard;新版照 legacy,只要 session 有效就使用 path 的
quote_service_id - legacy 會先取得 external review URL,再判斷收件人;因此無收件人時仍可能建立 / 寫回
quote_services.external_review_url - success 會寫
External_Reviewevent queue,payload 內含 email task 與 replacement
Config 切換檢查
這支 mail template 直接需要 mail.icon.star_full 作為 ##STAR_ICON##。目前 Lib/Common/Configuration.php:288 與 docker/staging/Configuration.php:279 都有:
https://s3-ap-northeast-1.amazonaws.com/pro360/images/icon/star_full.png切 staging / production 時要確認實際部署 config 也有同 key;不可只看本地 legacy checkout 判斷設定不存在。
已補 action、routing 與 PHPUnit。完整 legacy rule、event payload 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/external_review/invite.md。
更新時間:2026-06-04
POST /quote_services/external_review/submit.json
功能說明
consumer 透過外部評價頁提交服務評價時呼叫。此 API 會先 resolve 提交者;有 session 時使用 session user,無 session 時使用 User[...] 欄位登入或自動建立 consumer user。hash owner 不可評價自己。
正式機流量
2026-06-04 查正式機 access log:
125 POST /quote_services/external_review/submit.json 200
82 OPTIONS /quote_services/external_review/submit.json 200Response 與 Side Effect
- invalid hash:
{"error":4,"message":"Invalid hash"} - same user:
{"error":5,"message":"Cannot review the same user"} - success:
{"error":0,"message":"Success"};若走無 session 登入 / 註冊路徑,會附session_id - success 會建立
quote_feedbacks,model = QuoteService、foreign_id = quote_service_id - success 會寫
QuoteService/AddReviewactivity,param1為原始QuoteFeedbackJSON
備註
legacy updateUserFeedbackStats() 只統計 model = QuoteBids;外部 service review 仍照 legacy 呼叫此 helper,但不會因此更新 service stats。
已補 action、routing 與 PHPUnit。完整 legacy rule、DB side effect 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/external_review/submit.md。
更新時間:2026-06-04
POST /quote_services/change_status/profile_ready/{quote_service_id}.json
功能說明
provider 完成 onboarding 服務資料後呼叫。後端會啟用 service、設定 users.onboard_state = 2、更新 quote_services.modified,並寫 ServiceProfileReady activity。
操作路徑
- provider 進入
/dashboard/onboarding/{quote_service_id}onboarding 流程;服務資料頁可能由/dashboard/profiles導入。 - 完成服務資料設定。
- 前端
OnboardingContainer.onEndOnboarding()呼叫APIManager.markServiceProfileReady()。 - 實際送出 API:
POST /quote_services/change_status/profile_ready/{quote_service_id}.json
備註
成功 response:
{"error":0,"status":"Success"}這支有舊版免費點數分支。若 user_id > start_identity_free_credit_user_id,只會啟用 service、設 onboard、更新 modified、寫 activity;不排 newQuoteService、不送 Pro_Ready、不改 wallet。若進舊 user 分支,需依 free_credit_events.slug = quote.free_credit_new_provider 或 quote.free_credit_new_provider config 決定 wallet / transaction / event 寫入。
切換前需確認部署環境:
start_identity_free_credit_user_idfree_credit_events的quote.free_credit_new_providersystem eventquote.free_credit_new_providerconfig fallback
已補 action、routing 與 PHPUnit。完整 legacy rule、DB 寫入、config 檢查與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/change_status/profile_ready.md。
更新時間:2026-06-04
POST /quote_services/add.json
功能說明
provider 新增專家服務檔案時呼叫的 JSON API。已按 legacy QuoteServicesController::add() 搬移,包含 session user、無 session 登入 / 註冊、social path、service 建立、category mapping、external review URL、activity、queue、notification 與 other category report / email。
完整 legacy rule、DB side effect、config 檢查與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_services/add.md。
前端觸發
主要入口:
- provider 進入
https://staging.pro360.com.tw/dashboard/profiles - 點選頁面下方「新增專家檔案」
- 完成服務資料表單後,前端送出
POST /quote_services/add.json
相關前端 path:
- 已登入 provider 新增 service:
ServicesContainer/GoogleReservePro - 未登入或問卷新增 service:
questionnaireActions.submitServiceQuestionnaire();成功後由ProQuestionnairePopupContainer將 responsesession_id寫入session_tokencookie
流量與範圍
2026-06-12 查正式機 access log:
2209 POST /quote_services/add.json 200
887 OPTIONS /quote_services/add.json 200同次查詢 /quote_services/add 與 /quote_services/add/... legacy HTML path,未看到流量;本次搬移範圍以 JSON API 為準。
legacy HTML page 才用到的 Sudopay payout view state 不在 JSON API response 內,新版 API 不搬這段 view-only state。
對外行為
成功 response:
{"error":0,"service_id":123,"session_id":"...","user_id":456}Legacy 相容重點
QuoteCategory: [""]是有效 input:會建立 service,但不建立 numeric category mapping;不可改成 category required error。QuoteService[travel_pref]需支援 legacy web-app 格式:travel_vendor.value/travel_customer.value/remote.value。- 沒送
QuoteService[address]時,即使有zip_code也保留傳入的full_address。 is_not_this_area=1時保留傳入的full_address。travel_upto未勾時,service_provider_travels_upto清成0。City[name/id]、State[name/id]、zip-derived city/state、city slug 需維持 legacy 行為。- 新 user name fallback、email verification guard、social login path、counter cache、
service_updatequeue 皆已對齊 legacy。 sendProviderNeedNewCategoryMail()目前 new 有 empty email guard,legacy helper 沒有;因為是 shared helper,且前端 add path 未看到送other|...category,先列為 staging 必查,不直接改 shared behavior。
Side Effect / Logging
- 建立
quote_services。 - 建立 numeric category mapping;但
QuoteCategory: [""]不建立 mapping。 - 產生
external_review_url。 - 寫
QuoteServiceactivity。 - 寫
newQuoteServicequeue。 - request log:new 不再補 legacy
quote_services/add::POST/quote_services_addendpoint duplicate full request log;保留RouterV3generic request log,password/passwd key 由 router 層過濾。 newServiceScan:失敗只寫 LogHelper,不中斷新增 service 成功流程。
legacy 的 CakeLog::info(...) / $this->log(...) 是 CakePHP file log;new project 沒有 CakePHP file logging,FileLogHandler 目前是 no-op。若要求 literal file-log parity,需另補新專案 file log handler 或指定替代 channel。
Config / 部署檢查
ProConfig 指的是 new 專案 Lib/Common/Configuration.php 的 class ProConfig { public static $config = [...] }。要補的 key 就放在這個 array,或放在 staging / production 等效的部署 config。這個檔案可能不在一般 commit 內,切環境時要查實際部署值。
注意:不要在台灣環境補 ProConfig::$config['area'] = 'tw'。這個專案的 area key 是非台灣環境開關,只能在確認為 sg / hk 等非 TW 部署時設定;台灣環境維持未設定 / 空值。sys_area = tw 不能當成要補 area = tw 的依據。
值的來源以 legacy 部署環境為準:優先查正式 / 測試機 /var/www/html/app/Config/settings.yml,再用本地 legacy get-lancer-php56/app/Config/settings.yml 輔助比對。本地 checkout 沒有的 key 不代表不存在,要查部署環境。
必補 / 必查 ProConfig::$config:
| key | 用途 | legacy 值來源 |
|---|---|---|
site.url | external review long URL、service management URL、email replacement | legacy settings.yml 的 site.url |
yourls.api_url, yourls.api_key | 產生 external review 短網址 | legacy 部署環境 settings.yml 同名 key;本地 checkout 未必有 |
email.signature | other category provider email replacement | legacy settings.yml 的 email.signature |
mail.icon.help_center, mail.icon.resume_instruction | other category provider email icon replacement | legacy 部署環境 settings.yml 同名 key;本地找不到時仍要查實際環境 |
EmailTemplate.from_email | email sender fallback | legacy settings.yml 的 EmailTemplate.from_email |
實測 / 測試
2026-06-12 legacy staging 實測確認:QuoteCategory[0]="" 會建立 service、不建立 numeric mapping;request 沒有 QuoteService[address] 時保留傳入 full_address;phone_number 未傳時 fallback 到 user_profiles.phone,但不建立 service_update queue。
2026-06-15 new staging 實測確認:從 https://staging.pro360.com.tw/dashboard/profiles 點「新增專家檔案」送出後,response 為 {"error":0,"service_id":13665,"session_id":"...","user_id":8617}。DB 確認 service 建立、空 category 不建 mapping、external review URL 建立、QuoteService activity 與 newQuoteService queue log 存在。
已補 action、routing 與 PHPUnit。
更新時間:2026-07-03
POST /quote_services/edit/{quote_service_id}.json
功能說明
專家在 dashboard 編輯專家檔案時呼叫。這支會更新 quote_services profile 欄位,並處理聯絡方式、logo attachment、照片 / YouTube、內容審核、category mapping、profile score、activity 與 queue。
操作路徑
- provider 進入
https://staging.pro360.com.tw/dashboard/profiles - 開啟既有專家檔案編輯畫面
- 修改基本資料、服務地區、聯絡方式、照片或公開地址設定
- 前端呼叫
POST /quote_services/edit/{quote_service_id}.json
前端主要呼叫:
APIManager.updateServiceWithData(id, modified)APIManager.updateServiceProfileVisibility(id, visibility)
Legacy 相容重點
- 只用
quote_services.id查原 service,owner guard 在查 row 後比對user_id;不新增 active / archived guard。 - 未送
QuoteCategory時不更新quote_category_ids,也不重建 mapping。 - 更新 category 時重建
quote_categories_quote_services,並保留舊 mapping counter 欄位。 QuoteServiceContact是 full sync;沒送的 contact key 會被 inactive,Website / LINE remove 時同步清website_url/line_id。- 移除舊
quote_service_categories時會對齊 legacy side effect:auto quote bid 改 Removed、寫 category log,web / newer iOS pro 會同步刪 nshop service category。 - logo / 一般照片會依 legacy
QuoteUtil::gen_attachment_thumb()語意產amazon_s3_thumb_url;YouTube 影片不產縮圖。 phone_numberkey 存在即送service_updatetask event。- activity
param1會保留 legacy mutate 後的 request JSON,包含QuoteService.id/user_id/external_review_url。 business_name空白回{"error":1,"message":"專家檔案名稱不可為空白"}。- 成功 response:
{"error":0,"message":"Success"}。
實測 / 測試
已補 action、routing、thumbnail parity 與 PHPUnit。
2026-06-16 local container PHP 8.2:
docker exec -w /project-data cd63f9147e8d php vendor/bin/phpunit tests/QuoteServicesEditTest.php
OK (14 tests, 90 assertions)同日回歸既有 quote_services tests,不含 edit 單檔:
docker exec -w /project-data cd63f9147e8d php vendor/bin/phpunit \
tests/QuoteServicesAddTest.php \
tests/QuoteServicesChangeStatusArchiveTest.php \
tests/QuoteServicesChangeStatusProfileReadyTest.php \
tests/QuoteServicesExternalReviewInviteTest.php \
tests/QuoteServicesExternalReviewLinkTest.php \
tests/QuoteServicesExternalReviewSubmitTest.php \
tests/QuoteServicesStaticFieldsTest.php
OK (16 tests, 53 assertions)更新時間:2026-06-16
GET /quote_services/search.json
功能說明
保留 legacy pro search compatibility endpoint,支援:
GET /quote_services/search.json
GET /quote_services/search/tag:{tag}.json
GET /quote_services/search/page:{page}.json目前 web-app active pro list 已走 /quote_services/pro_list/page_size:{pageSize}/page:{page}/.../sort:hired_count/direction:desc.json;getServicesWithTag() 仍存在,但 active caller 已註解。本 API 主要處理 legacy / old bundle / external 低流量相容。
Legacy 相容重點
- response top-level key 固定為
services,total_pages,page。 - 每頁固定 20 筆,排序
QuoteService.id desc。 tag有值時才加is_active = 1、is_archived = 0。tag找不到 service id 時,legacy 仍回 active/non-archived list;new 不改成空結果。- 沒有
tag時不加 active / archived filter,維持 legacy no-tag list。 keywordquery 不做文字搜尋;legacy staging 實測等同 no-tag list。- 每筆保留 legacy shape:
QuoteService、Attachment、User、QuoteFaqAnswer、QuoteServicePhoto,並把quote_category_ids轉成QuoteService.categories。
實測 / 測試
2026-06-17 legacy staging 已測 /search/tag:{tag}、missing tag、search.json?keyword=a&page:1、search.json。
local container PHP 8.2:
docker exec -w /project-data cd63f9147e8d php vendor/bin/phpunit tests/QuoteServicesSearchTest.php
OK (3 tests, 23 assertions)更新時間:2026-06-17
2026-06-18 QuoteBids 驗證狀態同步
範圍
POST /quote_bids/add_consumer_survey/quote_bid_id:{quote_bid_id}.jsonPOST /quote_bids/change_status/hired/{quote_bid_id}.jsoncompleted/is_closedquote bid lifecycle 狀態流
結論
add_consumer_survey:staging response / DB 對表已完成;這支只 upsertquote_consumer_surveys,不寫 bid、activity、queue、transaction 或 notification。change_status/hired:staging response / DB baseline 已確認;不再列為待 baseline 項目。completed/is_closed:已確認現況,近期正式流量為 0,且 new 目前沒有獨立 completed route;暫不列下一支 migration 候選。若後續出現流量,再以 quote bid lifecycle 狀態流獨立處理。
完整規則維持在各 detail doc:
API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/add_consumer_survey.mdAPI 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/change_status/hired.mdAPI 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_bids/change_status/completed_closed.md
更新時間:2026-06-18
GET /quote_service_categories/pricing_form/{quote_category_id}.json
功能說明
provider 編輯服務分類 / 報價設定時讀取 pricing form schema。這支會回傳 pricing form fields、平均價格設定、pricing description、pricing unit 與預設週預算;legacy controller 只讀取資料並組 response,沒有業務資料寫入。
操作路徑
staging:進入項目管理頁 https://staging.pro360.com.tw/dashboard/services/9930/159,點「編輯」後再點「價格表」,會觸發 GET /quote_service_categories/pricing_form/159.json。
流量與 caller
2026-06-18 查正式機目前保留的 get-lancer_access.log*,quote_service_categories/pricing_form/{quote_category_id}.json 是 quote_service_categories 系列最高流量候選之一。
高量樣本:
895 GET /quote_service_categories/pricing_form/201.json 200
829 GET /quote_service_categories/pricing_form/206.json 200
397 GET /quote_service_categories/pricing_form/290.json 200
372 GET /quote_service_categories/pricing_form/199.json 200raw line 樣本主要來自 pro app pro360/6.6.0 ... Alamofire/5.10.2。web-app 也有 caller:APIManager.getQuoteServiceCategoryPricing(categoryID),path 為 /quote_service_categories/pricing_form/${categoryID}.json。
同次流量也看到 POST /quote_service_categories/edit/.json 與多個 POST /quote_service_categories/edit/{id}.json;edit 是寫入型 API,已另開 detail doc:API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_service_categories/edit.md。
目前狀態
新專案已有 Endpoint/V1/QuoteServiceCategories.php::pricing_form();2026-06-18 已補 legacy 缺漏欄位並保留新專案既有 response marker:
Mapping.php補 explicitpricing_form/{quote_category_id}route。- legacy success top-level 只有
quote_form_fields;new 保留 2022 舊 API 導流時加入的 top-levelnew = 1,作為 migration decision。 - legacy 會把
default_weekly_budget_limit放在quote_form_fields內;new 已補quote_category_suggest_budgets.suggest_budget,無 row fallback500。 - legacy staging category
159已確認 top-level shape、pricing_unit = ""、default_weekly_budget_limit = 800。 - 本地測試:
docker exec -w /project-data cd63f9147e8d vendor/bin/phpunit tests/QuoteServiceCategoriesPricingFormTest.php通過,OK (2 tests, 13 assertions)。
完整 legacy / new 對照、migration decision 與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_service_categories/pricing_form.md。
更新時間:2026-06-18
POST /quote_service_categories/edit/.json / POST /quote_service_categories/edit/{quote_service_category_id}.json
功能說明
provider 在項目管理頁新增或編輯服務分類設定。這支 API 同時承接新增分類、接案偏好、服務方式 / 地區、價格表、預算、自動報價與直接預約開關。
流量與 caller
2026-06-18 查正式機目前保留的 get-lancer_access.log*,同次 quote_service_categories 統計看到:
561 POST /quote_service_categories/edit/.json 200
494 OPTIONS /quote_service_categories/edit/.json 200
46 POST /quote_service_categories/edit/1395196.json 200
38 POST /quote_service_categories/edit/1108340.json 200
37 POST /quote_service_categories/edit/1382902.json 200web-app caller 是 APIManager.postQuoteServiceCategoriesSetting(QSC),path 為 /quote_service_categories/edit/${QSC.id || ''}.json。QSC.id 空值會打 /edit/.json,有 id 會打 /edit/{id}.json。
目前狀態
新專案已補:
- route:
Lib/Common/RouterRule/Mapping.php - endpoint:
Endpoint/V1/QuoteServiceCategories::edit() - model:
QuoteServiceCategory::checkUserForEdit()/validateSave()/ budget / pricing rows / auto quote log helpers
legacy controller 很薄,核心行為在 QuoteServiceCategory::validateSave(),new 已同步主要寫入與 side effect:
quote_service_categoriesquote_categories_quote_servicesquote_servicesquote_service_category_logs- 條件式寫入
auto_quote_logs、auto_quote_price_note_filter_logs、quote_service_content_reviews、quote_service_prohibited_logs - 每次結尾會重建
pro_search_quote_pricing - legacy staging 已補 baseline:description / pricing update / service area / job preference /
is_auto_quote_on = 1success;direct reserve 開啟仍待獨立實測。
本地測試:
docker exec -w /project-data cd63f9147e8d vendor/bin/phpunit tests/QuoteServiceCategoriesEditTest.php
docker exec -w /project-data cd63f9147e8d vendor/bin/phpunit tests/QuoteServiceCategoriesPricingFormTest.php結果:
tests/QuoteServiceCategoriesEditTest.php: OK (5 tests, 68 assertions)
tests/QuoteServiceCategoriesPricingFormTest.php: OK (2 tests, 13 assertions)完整欄位分類、legacy side effect、legacy staging baseline 與 new staging 待驗證項目見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_service_categories/edit.md。
更新時間:2026-06-22
POST /quote_categories/related.json
功能說明
前端依目前已選分類或 quote_service_id 取得相關分類推薦;主要實測入口是 provider 項目管理的新增服務項目流程。
本次已補 legacy path routing、selected_ids / filter_ids / quote_service_id 分支、association + related mapping、keyword fallback、final fallback 與 legacy response shape。
操作路徑
正式機 2026-06-22 access log 有 POST /quote_categories/related.json 200 共 7672 筆。
已確認專家端新增服務項目會觸發 quote_service_id 分支:
https://staging.pro360.com.tw/dashboard/services/add/{quote_service_id}例如 quote_service_id=9930 時,前端送 POST /quote_categories/related.json,body 只有 quote_service_id=9930,response 為 {quote_categories: [...]}。
公開分類頁 /category/:slug 也有可能透過 selected_ids 呼叫,但實際觸發依分類資料載入流程;不建議拿 https://staging.pro360.com.tw/category/home_repair 當主要驗證點。
備註
完整對照與測試見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_categories/related.md。
更新時間:2026-06-23
GET /quote_categories/index/type:tree.json
功能說明
前端取得服務分類樹資料,用於服務管理、案件篩選、分類選擇與相關分類 UI。這支是 read-only API,不新增或編輯分類資料。
legacy response top-level key 是 quote_category_genres;genre 底下掛主分類 quote_categories,子分類掛在父分類 contains。
操作路徑
web-app APIManager.getCategoriesTree() 呼叫:
GET /quote_categories/index/type:tree.json正式機 2026-06-23 access log:
11984 GET /quote_categories/index/type:tree.json 200
9717 OPTIONS /quote_categories/index/type:tree.json 200備註
已補 type=tree 專用 branch、QuoteCategory::getTree() 與 PHPUnit;一般 /quote_categories/index.json 仍維持原本 quote_categories response。
2026-06-24 staging diff 後修正:legacy tree category 會帶 Attachment.amazon_s3_original_url,但 genre 查詢未 contain Attachment,因此不回 QuoteCategoryGenre.image_url / header_image_url。新專案已移除這兩個非 legacy 欄位,且 QuoteCategory::getTree() PHP caller 只在 index_tree()。
本地測試:
docker exec -w /project-data cd63f9147e8d ./vendor/bin/phpunit tests/QuoteCategoriesIndexTreeTest.php
docker exec -w /project-data cd63f9147e8d ./vendor/bin/phpunit tests/QuoteCategoriesRelatedTest.php結果:
tests/QuoteCategoriesIndexTreeTest.php: OK (3 tests, 25 assertions)
tests/QuoteCategoriesRelatedTest.php: OK (3 tests, 20 assertions)完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_categories/index_tree.md。
更新時間:2026-06-23
POST /users/forgot_password.json
功能說明
使用者在忘記密碼流程輸入 email 後,後端查 users.email,若 user 存在則寄出重設密碼 email。
這支 API 不會直接修改密碼;只有在 users.mobile_app_hash 空值時補 hash,已有 hash 時重用舊值。成功後寫入 User_Change_Password event queue,worker 會處理 email。
操作路徑
前端 forgot password form 送出:
POST /users/forgot_password.json正式機 2026-06-24 access log:
3900 POST /users/forgot_password.json 200
1226 OPTIONS /users/forgot_password.json 200備註
已補 Users::forgot_password()、PHPUnit 與 staging/local diff。response 對齊 legacy:
{"error":0,"message":"Reset password email sent"}legacy JSON path 會進 forgot_password_from_api(),不是頁面版 captcha / validation 流程;new 不加 is_active、session、blacklist、rate limit 等 legacy 沒有的 guard。
queue payload 維持 legacy shape,只含 user_id、quote_service_id、tasks;不可因 new task DO 多出 public property 就回寫 quote_request_id、quote_bid_id、shopList。
request log 只保留 RouterV3 generic request log;不補 legacy forgot_password_from_api endpoint duplicate full request log。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/forgot_password.md。
更新時間:2026-07-03
POST /users/sign_up.json
功能說明
Consumer 註冊 API。成功後建立 user、profile、login、session、RequestorSignup activity,非 ibon/qna 流程會寫入 Consumer_Signup event。
操作路徑
POST /users/sign_up.json正式機 2026-06-24 access log:
894 POST /users/sign_up.json 200
201 OPTIONS /users/sign_up.json 200備註
已補 Users::sign_up() 與 PHPUnit。實作只依 legacy UsersController::sign_up() 實際路徑補欄位與 side effect,不沿用其他 auto signup helper。
高風險 legacy parity:
- email / social existing user lookup 不加
is_activefilter。 - 保留 legacy
country_code雙 prepend 行為。 usersexplicit insert allowlist 不補 legacy 沒指定的 wallet、counter、security、app timestamp 欄位。Consumer_Signupevent payload 維持 legacy shape,只含user_id、quote_service_id、tasks。- phone conflict 時,舊 user 有 auto quote service category 才寫
Reset_Phone_Confirmemail event。 - Google token 驗證依賴
google.oauth_client_id*deployment config;但 2026-06-26 已確認 web-app Google 登入走/users/login.json,不會自然 fallback 呼叫/users/sign_up.json。台灣環境不補area=tw。 - request log 只保留
RouterV3generic request log;不補 legacysign_upendpoint duplicate full request log。
測試結果:
tests/UsersSignUpTest.php: OK (11 tests, 129 assertions)2026-06-26 已用 staging is_qna_user=1 curl 確認 response 與 DB side effect;完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/sign_up.md。仍需完整 staging diff 與真實 social token path 實測。
更新時間:2026-07-03
POST /users/login_once.json
功能說明
一次性登入 API。透過 security_hashes 建立 session,成功後會寫 api_sessions、security_hash_use_logs、user_logins。
備註
2026-06-29 已補 legacy parity guard / fallback 與 PHPUnit:
- active user guard:hash user 必須
is_active = 1。 - Session hash 14 天前或已 fulfilled 時回 consumed。
- 已 fulfilled 的
ibonHyperlinkLogin/OrderLoginUrl直接 consumed。 - device id fallback:
User.device_id-> flatdevice_id->my-device-id。 - 只改
Users::login_once(),未改 sharedSecurityHashmodel,避免影響其他 API。
測試結果:
tests/UsersLoginOnceTest.php: OK (5 tests, 50 assertions)
tests/UsersForgotPasswordTest.php: OK (3 tests, 39 assertions)
tests/UsersSignUpTest.php: OK (11 tests, 129 assertions)2026-06-29 staging 實測:
- 第一次呼叫
hash = 4f48b7e16e1e8c1420e93be77ffc3bab回{"error":0,"session_id":"6h9rmece3ac0pgemn5h4r53sgm"}。 - 第二次同 hash 回
{"error":1,"message":"hash was consumed"}。 - DB 確認
security_hashes.is_fulfilled = 1、api_sessions建立、security_hash_use_logs寫入、user_logins.channel = 2。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/login_once.md。
更新時間:2026-06-29
POST /users/login.json
操作路徑
https://staging.pro360.com.tw/login
App / web 登入流程會呼叫 POST /users/login.json;Google login 依 User[platform] 對應 google.oauth_client_id* 驗 id_token。
功能說明
使用者登入 API。已補 legacy JSON path parity,包含 password / social / OTP login、session / cookie、login_logs / user_login_infos 與 legacy response shape。
2026-07-01 staging 驗證 platform=ios 時,new google.oauth_client_id_ios 與 legacy deployment config 不一致;已補 client id mismatch log context,會顯示 expected_config_key、expected_client_id、actual_aud。config 同步為 legacy cvvd... 值後,staging Google login 已正常。
2026-07-21 migration decision:一般 login 成功時,同 user_id + device_id 的舊 token 會先寫入 api_session_logs(action=login_rotate)再刪除,並於同一 transaction 建立新 token。其他 device、失敗登入與其他 ApiSession::upsert() caller 不受影響。本地 UsersLoginTest 為 11 tests, 234 assertions;staging / production 的 api_session_logs schema 與部署後 token rotation 實測待確認。
備註
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/login.md。
更新時間:2026-07-21
POST /users/delete.json
操作路徑
Web 帳號設定刪除帳號會呼叫:
https://staging.pro360.com.tw/dashboard/settings/deactivate前端確認後送 POST /users/delete.json,body 無必要欄位,需要 valid API key 與 valid user session。
功能說明
使用者刪除帳號 API。成功後會停用 user、釋出 email / phone、清 social 綁定與 session、歸檔 user 的 services / requests,並寫 activity、moengage_erase_user、sumsub_deactivate_user、Delete_User event。
這支不是單純關閉 users.is_active,也不是物理刪除所有資料;刪除後沒有直接復原 API,一般情境視為重新註冊。
備註
已補 legacy path routing、response shape、user row update、service/request archive、activity、session delete、task/event queue、Life55688 wrapper 與 PHPUnit。DeleteUser activity param1 對齊 legacy DB 實際值 (self);不更新 password、wallet、counter、user_profiles 等 legacy 沒碰的欄位。
request log 只保留 RouterV3 generic request log;不補 legacy RestApiHelper::getUserId() endpoint duplicate full request log。
完整對照與測試結果見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/delete.md。
更新時間:2026-07-03
POST /users/change_password.json
操作路徑
Web 帳號設定頁點選「變更密碼」會呼叫:
https://staging.pro360.com.tw/dashboard/settings進入設定頁後點選變更密碼,表單送出後送 POST /users/change_password.json,body 為 current_password、new_password,需要 valid API key 與 valid user session。
功能說明
使用者修改或建立密碼 API。legacy JSON path 會從 change_password() 直接轉進 change_password_from_api();成功主流程更新 users.password 並回 {"error":0,"message":"Success"}。
這支不會刪 session、不會更新 profile、不會走 web/admin 的 logout 或 email 分支;session helper 仍保留 legacy 的 access 更新,以及超過 180 天回訪專家的 returnedQuoteService 條件式 task queue。
備註
已補 action、routing、legacy session resolver、blocked user、legacy response shape、password verify/update、RouterV3 password/passwd log filter 與 PHPUnit。2026-07-03 已完成新版 staging curl / DB / log 驗證:成功只更新 users.password,產生的 bcrypt $2y$12$ hash 可被 legacy / new 互驗,無新增 activity / queue / error log,request log 只保留 RouterV3 generic log 且 password 欄位已過濾。搬移時不可直接沿用 new UserUtil::change_password(),因為 shared helper 的 8 碼密碼規則與 response shape 不符合 legacy JSON path;legacy/web 前端目前允許 6 碼,且支援 DB password 空值時用空 current password 建立密碼。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/change_password.md。
更新時間:2026-07-03
POST /users/connect_social/{type}.json
操作路徑
Web 帳號設定頁的「連結帳號」會呼叫:
https://staging.pro360.com.tw/dashboard/settings支援:
POST /users/connect_social/google.json
POST /users/connect_social/facebook.json
POST /users/connect_social/apple.jsonbody 走 FormData。Google / Facebook normal login 送 access_token;Facebook limited login 可送 authentication_token;Apple web 送 platform=web 與 code。
功能說明
使用者 social 帳號綁定 API。後端用目前 session user 綁定 Google / Facebook / Apple social id;若 social id 已屬於目前 user,回 success 不更新;若已屬於其他 user,回 error=2;若目前 user 已有不同的同類 social id,legacy 行為是回 success 但不覆蓋。
成功時只更新 users 的 social 欄位,不建立 user、不建立 session、不寫 login log、不寫 payment / wallet / queue。Google connect path 對齊 legacy 實際行為,google_access_token 寫空字串。
備註
已補 action、routing、legacy session resolver、Google / Facebook / Apple verify wrapper、social id conflict、empty-only update、legacy response shape 與 PHPUnit。
2026-07-08 已完成新版 staging Google / Apple 實測:Google success 會更新 users.google_user_id;Google / Apple 若 social id 已綁在其他 user,會回 error=2;Apple success 會寫 apple_verify_logs 並更新 users.apple_user_id。request log 只保留 RouterV3 generic log;文件不記錄完整 token payload。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/connect_social.md。
更新時間:2026-07-08
GET /users/referrals.json
操作路徑
Web 免費接案金頁的推薦好友區塊會呼叫:
https://staging.pro360.com.tw/dashboard/free-credits/referral前端 ProReferral mount 後送 GET /users/referrals.json,需要 valid API key 與 valid user session,body 為空。
功能說明
回傳目前 user 近一年內的推薦好友列表,前端用 referred_users.length 顯示累積推薦人數與進度條,並用每筆 UserProfile.first_name、User.quote_status_id、User.awarded_credits 顯示好友名稱、推薦進度與獎勵金。
這支只讀 referral list,不寄信、不新增 referral、不寫 queue、不做付款;寄推薦信是另一支 POST /users/refer.json。
備註
已補 action、routing、legacy session resolver、blocked user、1 年 filter、legacy nested response shape、inactive referred user parity、missing avatar fallback 與 PHPUnit。2026-07-08 legacy staging 空資料實測回 {"referred_users":[],"error":0,"message":"Success"}。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/referrals.md。
更新時間:2026-07-09
POST /users/refer.json
操作路徑
Web 免費接案金頁的推薦好友區塊點「發送Email」會呼叫:
https://staging.pro360.com.tw/dashboard/free-credits/referral前端送 POST /users/refer.json,body 為 email,需要 valid API key 與 valid user session。
功能說明
寄出推薦好友 email。成功時寫 event_queue 的 Invite_Referral event,template 為 204 Vendor Signup Invitation by Referral,email 內容包含 provider name、referral URL、email signature、provider photo 與 learn-more URL。
這支不新增 user_referrals、不發 referral bonus、不改 wallet / transaction,也不自動補 users.referral_hash;如果目前 user 沒有 referral_hash,legacy 行為仍回 success,但不寫 queue。
備註
已補 action、routing、legacy session resolver、blocked user、legacy response shape、email task payload、provider name fallback、missing email parity、no-referral-hash no-queue parity 與 PHPUnit。legacy 註解掉的 Email Existed 檢查沒有加回。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/users/refer.md。
更新時間:2026-07-09
POST /users/verify/{type}/{action}.json
操作路徑
Web 簡訊驗證會先呼叫:
POST /users/verify/phone/preauth.json
body 為 phone、選填的 country_code,登入流程另送 is_login=1。收到 hash 後再呼叫:
POST /users/verify/phone/auth.json
body 為 hash、otp 與選填的 is_login=1。
前端 API 封裝在 web-app/modules/utils/api-manager.js:3287-3323。主要觸發位置是帳號簡訊驗證 PhoneVerificationView.js:107-146、問卷 QuestionnairePopupContainer.js:1167-1193 與 Booking phone login LoginContainer.js:141-159。語音驗證會另外呼叫 POST /users/verify/voice/preauth.json。
部署設定
台灣 staging 使用 sms_platform_local=infobip,並需設定 InfoBipUrl、InfoBipAPIKey。台灣環境的 ProConfig['area'] 必須維持未設定或 NULL,不可設成 tw。
設定位置是 Lib/Common/Configuration.php。此檔被 .gitignore 忽略,本機修改不會進 commit,staging / production 必須另外同步。語音驗證另需確認 sms_platform_voice、InfoBipAPIUrl 與 voice.verify_message。
2026-07-16 已確認 staging 簡訊送達、delivery callback 與 OTP auth 成功;production 設定尚待確認。
更新時間:2026-07-16
POST /quote_service_categories/add…
操作路徑
這支 API 是讓專家新增一個「我可以接這類工作」的服務項目。需 valid API key 與 valid user session,Cake named parameters 傳 quote_service_id、quote_category_id;service 必須屬於登入使用者。
新增時會複製 service 的服務地區與郵遞區號,並依 category form fields 建立全部接案偏好與預設服務方式。相同 service/category 重複呼叫會回既有 id,不重複新增。
目前 checkout 的 Web「項目管理 → 新增項目」不呼叫 add,而是呼叫 POST /quote_service_categories/edit/.json。2026-07-22 已確認 iOS pro app legacy 呼叫 /add/quote_service_id:9930/quote_category_id:130.json,並找到同時間 QSC、mapping、QSC log 與完整 request log。2026-07-23 app 切到 new staging 後,以 9930 / 700 建立 QSC 10722;raw response、mapping、QSC log 及 duplicate 無額外寫入均符合預期。
同次 staging 驗證發現專用 Legacy log 因 Nginx rewrite 只記成 quote_service_categories/add.json::POST,Router generic log 則保有完整 named parameters。已改由 Router 提供原始 dispatch path 給專用 logger,保留 client 實際參數順序;本地測試同時覆蓋兩種順序、短 REQUEST_URI 與 invalid-session warning。Add 測試為 17 tests, 147 assertions,完整 QSC regression 為 27 tests, 234 assertions;待部署後複驗專用 channel。
部署設定
沒有新增 API 專用 config key;shared validateSave() 在 HK service area 101 分支會讀 sys_area。本地為 tw,Configuration.php 被 .gitignore 忽略;staging / production 實際值仍須在部署前確認。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_service_categories/add.md。
更新時間:2026-07-23
GET /quote_feedbacks/sent[/sort:{sort}].json
操作路徑
Web 切到案主/消費者模式後,開啟:
https://staging.pro360.com.tw/dashboard/settings/reviews進入「帳戶設定 → 評價紀錄」會先呼叫 sort:time;切換排序會呼叫 sort:score_high 或 sort:score_low。專家模式不顯示此選單。
功能說明
回傳目前 session user 送出的案件評價 raw array,包含 service name/photo、feedback 全欄位、bid request id、comments 與 active feedback attachments。Domain query 不寫 feedback / bid / service,也不做付款或 notification;auth cache miss 仍保留 legacy access update 與可能的 returnedQuoteService queue。
備註
已補 action、routing、專用 model query、Redis session cache、legacy info/warning log 與 PHPUnit。保留 legacy 的 LEFT/INNER JOIN、空值與未知 sort fallback、JSON 字串型別、inactive session user 與 cache hit/miss side effects;不新增 abnormal、active、public 或 visibility filter。
2026-07-24 本地 Docker PHP 8.2 測試 10 tests, 76 assertions 全部通過;legacy staging baseline 四種 sort 與本地 output 的 canonical JSON 結構、值、array order 與型別一致。前端觸發截圖已放入 detail doc。new staging 部署後的 raw response、排序與 log 複驗尚待完成。
完整對照見 API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_feedbacks/sent.md。
更新時間:2026-07-24
GET /quote_category_subgenres/index/genre_id:{id}.json
本次調整
目前Production以API key條件分流:指定key走PHP 8,其餘走Legacy。最終ALB只保留/quote_category_subgenres/index/genre_id*並全部送PHP 8,因此PHP 8程式內改為:
- Deployment config精確matching key:維持現有PHP 8完整genre tree及
is_skip_pro_search。 - 其他valid key:回Legacy-compatible指定genre subgenre array,不含
is_skip_pro_search。 - 其他valid key的unknown genre:HTTP 200、
text/html、bodyNot Found。 - Missing / invalid key:HTTP 401。
- Config缺少或為空:error
999,禁止部署或切流。
必要config為quote_category_subgenres.existing_php8_api_key。本地/Staging使用Staging DB可通過guard的key;Production使用目前ALB條件值並確認Production DB active。目前本地/Staging matching key為3C3A284DD02A3A6E237E7C44A56A34B4;此值只放部署config,不可寫死在endpoint程式。
本地已通過專用測試13 tests, 85 assertions、相關regression6 tests, 45 assertions,並以實際本地config驗證matching與non-matching雙分支。Colon與slash route都由既有File rule解析,未修改Mapping;request log維持RouterV3既有行為,不新增endpoint專用filter。2026-07-29 reviewer接受unknown genre不搬Legacy全域exception Slack webhook,只保留HTTP 200 Not Found前端行為。
2026-07-29 Staging已新增config並將path導向PHP 8。Matching key、genre_id:1回完整genre object且有is_skip_pro_search;non-matching valid key命中X-PHP-Env: php82-staging-1,HTTP 200回20筆Legacy-compatible subgenre array,欄位與JSON string型別符合預期,且沒有完整genre tree與is_skip_pro_search。
Staging curl
curl只取得完整HTTP headers與raw body,結果另外人工比對,不在指令中加入jq或通過條件。
Matching key、有效genre:
curl -i \
-H 'X-PRO360-Rest-Api-Key: 3C3A284DD02A3A6E237E7C44A56A34B4' \
'https://api-staging.pro360.com.tw/quote_category_subgenres/index/genre_id:1.json'Non-matching valid key、有效genre:
curl -i \
-H 'X-PRO360-Rest-Api-Key: 34F4249749CDF7F8E295F535BC37C3B5' \
'https://api-staging.pro360.com.tw/quote_category_subgenres/index/genre_id:1.json'Non-matching valid key、unknown genre:
curl -i \
-H 'X-PRO360-Rest-Api-Key: 34F4249749CDF7F8E295F535BC37C3B5' \
'https://api-staging.pro360.com.tw/quote_category_subgenres/index/genre_id:999999.json'Missing key:
curl -i \
'https://api-staging.pro360.com.tw/quote_category_subgenres/index/genre_id:1.json'完整API contract見API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_category_subgenres/index_by_genre.md;config與ALB切流見同目錄deployment_config_and_cutover.md。
更新時間:2026-07-29
GET /quote_feedback_tags/index.json
功能與前端入口
回傳啟用中的評價標籤,依分數與顯示順序分組。Web 會在消費者商品訂單的「評價/編輯評價」視窗開啟時呼叫;request 帶有效 API key,不需要 user session。
PHP 8 已維持 Legacy 的 query、排序、翻譯、response shape 與型別:
- 成功回 HTTP 200、
error=0,data以字串分數 key 分組。 is_satisfied:{score}只接受 CakePHP colon named parameter;missing、0或 invalid value 回全部 active tags。- Endpoint 本身不寫 DB,不產生 payment、queue、activity 或 notification。
- 沒有 endpoint 專用 config;切流前仍需核對部署環境的
use_multi_translation、use_multi_langs、default_lang與 PHP session 設定。
驗證狀態
- 本地 PHP 8:
12 tests / 68 assertions通過。 - 2026-07-30 Staging raw response 已與 active tag、
is_satisfied ASC, display_order ASC對照一致。 - Staging 前端 Network 已確認實際 caller 與 HTTP 200,截圖已保存。
- 該次證據未顯示
x-php-env,因此處理 instance 仍待用 response header 確認;Production 尚未切流。 - Production 最近 30 天為 26,911 calls,盤點時全部走 Legacy。
完整 contract:API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_feedback_tags/index.md
Staging smoke test:各種API測試/quote_feedback_tags/index.md
更新時間:2026-07-30
quote_feedback_comments/save / delete
POST /quote_feedback_comments/save/{feedback_id}.json
GET/POST /quote_feedback_comments/delete/id:{comment_id}.json功能與前端入口
save 新增或更新案件評價回覆;session user 必須是 feedback 雙方之一,更新時還必須是 comment owner。delete 只允許 comment owner hard delete,並維持 Legacy 同時接受 GET 與 POST。
現行 Web 的主要入口是專家登入後進入 /dashboard/works/{bid_id},在消費者案件評價卡片點「回覆評價/修改回覆」並送出。另可從 /dashboard/services/{service_id}/reviews 的「案件評價」進入,但已有 comment 時不顯示回覆按鈕。
注意:
- 消費者新增評價不呼叫這支 API;商品評價回覆走另一支 Nshop API。
- Web caller 只送
feedback_id + comment,不送 commentid,所以 UI 只驗證 create;update branch 需用 curl 或其他 client。 - 現行
web-app找不到deletecaller;Production 仍有 GET/POST 流量,因此保留兩種 method,Staging 以 curl 驗證。
Route 與 Legacy parity
PHP 8 使用明確且 anchored mapping,並排在 generic File route 前:
^quote_feedback_comments/save/([0-9]+)\.json$
^quote_feedback_comments/delete/id:([0-9]+)\.json$save成功:{"error":0,"status":"Success"}。delete成功:{"error":0,"message":"success"}。save只寫quote_feedback_comments;保留原始 comment,不自行 trim、escape 或增加 feedback 狀態 guard。delete直接 hard delete owner 的 comment,不額外 join feedback。- 兩支只接受
.json。2026-07-31 reviewer 已接受不搬 Legacy 的無副檔名Acceptnegotiation;錯誤 action 與 route negative test 已補。 - 沒有 endpoint 專用 config;部署需確認 PHP 8 與 Legacy 共用正確 DB、Redis、API key 與 API session 資料。
驗證狀態
- 本地 PHP 8 syntax 通過。
- Core:
3 tests / 36 assertions;Other:16 tests / 97 assertions;專用測試合計19 / 133。 - Regression:
quote_feedbacks/sent為10 / 76,quote_feedback_tags/index為12 / 68,全部通過。 - Production 最近 30 天:
save751 calls、delete10 calls,盤點時全部走 Legacy。 - Legacy retained log 的實際
save/deletepath 全為.json;目前是單台 Legacy host 證據,其他 instances/ALB logs 尚待確認。 - 2026-07-31 Legacy Staging 已完成
save/2286.jsoncreate baseline:response 為 success;DB 新增 comment730,feedback、actor、is_customer、原始 comment 與 timestamp 均符合 Legacy 預期。 - PHP 8 Staging 的 save create/update、delete、DB side effect 與
x-php-env尚待 smoke test;完成前不調整 Production ALB。
完整 contract:
API 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_feedback_comments/save.mdAPI 路由與遷移/API Migration/pro360_api_82/api_migration/details/quote_feedback_comments/delete.md
Staging smoke test:各種API測試/quote_feedback_comments/
更新時間:2026-07-31
POST /quote_requests/search_add.json
同步現況
PHP 8 已承接主要建單、表單、計價、配對、bid、queue 與 response 流程。Current Legacy 以 get-lancer-docker-2/get-lancer 的 NewStaging / e8341ac62 為準;2026-08-10 複核後沒有 2026-08-05 之後的新 search_add commit。
本輪 LINE actor / 帳號綁定已由 PHP 8 commit fb8897d7 完成:讀取 User[line_id_token],從 line_verify_logs 找 LINE 身分,使用或綁定既有 PRO360 user,auto signup 時寫入 line_users。LINE 不增加 response 欄位;user_id 與 DB id / flag 維持 JSON string,error 維持 integer。
相關 PHP 8.2 測試:SearchAddInputTest 9/24、CredentialActorResolverTest 12/62、LINE repository integration 2/20,合計 23 tests, 106 assertions 全部通過。
目前仍有三項 Legacy parity gap:
- device-only:PHP 8 仍可成立 actor;Legacy 會回
error=2。 - existing session:PHP 8 shared upsert 會更換 token;Legacy search_add 沿用原 token。
inner_text:Legacy 另寫quote_request_inners並排除一般表單、計價與配對;PHP 8 尚未實作。
部署狀態
fb8897d7 已推到 origin/NewStagingForPHP82_search_add,尚未進入 NewStagingForPHP82 / staging,因此目前不可標成完整 parity,也不可進行全流量切換。
search_add 本身沒有新增 deployment config。LINE end-to-end OAuth 仍依賴 LINE_LOGIN_CLIENT_ID、LINE_LOGIN_SECRET、api.url、site.url 與 callback allowlist;staging / production 實際設定尚待確認。
完整狀態見 API 路由與遷移/API Migration/pro360_api_82/search_add/newstaging_delta_audit_2026-08-05.md。
更新時間:2026-08-10