QuoteBids Provider Receive Phone

對應 legacy / web-app 實際 API:

POST /quote_bids/provider_receive_phone/{quote_bid_id}.json

quote_bid_idquote_bids.id。web-app 使用 provider session token,body 為空 FormData / no body,不用 JSON body 傳 quote_bid_id

功能說明

web-app 通常在 provider 已送出手動報價、consumer 尚未讀取報價,且 consumer phone 已允許顯示時呼叫此 API。API 本身不檢查 quote_bids.is_requestor_readedquote_requests.is_show_phone_to_providers

成功時,這支 API 只做兩件同步 side effect:

  • 將同一筆 quote_bids.idis_provider_received_phone 更新為 1
  • 第一次更新時建立 ProReceivePhone activity。

這支不走付款主線,不寫 transaction,不送 queue。它的主要用途是讓後續退款 / 電話顯示判斷知道 provider 已主動取得 consumer phone。

快速結論

  • actor:provider session。
  • legacy API:QuoteBidsController::provider_receive_phone($quote_bid_id)
  • web-app 實際 path:/quote_bids/provider_receive_phone/{quote_bid_id}.json
  • request body:空 body / FormData,不帶 prime、不帶付款資料。
  • new API:已補 Endpoint/V1/QuoteBids.php::provider_receive_phone()
  • routing:已補 Mapping.php,支援 /quote_bids/provider_receive_phone/{quote_bid_id}.json
  • 正式機流量:2026-05-28 查詢 ip-10-5-2-242 access log,總計 6246 筆,全部 access log status 200。
  • 優先度:高。正式流量高,且影響 provider 主動取電話後的退款與電話顯示狀態。

正式機 Access Log

2026-05-28 查詢機器:ip-10-5-2-242

查詢條件:

LOG_DIR=/var/log/apache2
ACCESS_LOG=get-lancer_access.log
PATTERN='quote_bids/provider_receive_phone'

結果:

範圍筆數
get-lancer_access.log + get-lancer_access.log.1741
get-lancer_access.log.*.gz5505
total6246

HTTP status 分布:

status筆數
2006246

path 分布查詢:

{
  sudo grep -Eho 'quote_bids/provider_receive_phone[^ ?"]*' "$LOG_DIR/$ACCESS_LOG" "$LOG_DIR/$ACCESS_LOG.1"
  sudo find "$LOG_DIR" -maxdepth 1 -type f -name "$ACCESS_LOG.*.gz" -print0 \
    | xargs -0 sudo zgrep -Eho 'quote_bids/provider_receive_phone[^ ?"]*'
} | sort | uniq -c | sort -nr | head -50

path 分布重點:

筆數path
5quote_bids/provider_receive_phone/2521422439.json
2quote_bids/provider_receive_phone/2533067063.json
2quote_bids/provider_receive_phone/2532625992.json
2quote_bids/provider_receive_phone/2532446472.json
2quote_bids/provider_receive_phone/2528452577.json
1多數其他 quote_bids/provider_receive_phone/{quote_bid_id}.json

判斷:

  • 正式流量使用 path id:/quote_bids/provider_receive_phone/{quote_bid_id}.json
  • 有同一個 bid 重複呼叫的情況,因此新實作必須維持 legacy idempotent 行為:已經 is_provider_received_phone = 1 時仍回 success,但不重複建立 activity。
  • access log sample 包含 iOS pro app、Android okhttp、web / mobile web caller。

Web-App Caller

web-app 檔案:

/Users/mattsu/Documents/Site/web-app/modules/utils/api-manager.js:803-812

APIManager.providerReceivePhone(quoteId)

  1. 從 local token 取得 provider session token。
  2. 呼叫 POST /quote_bids/provider_receive_phone/${quoteId}.json
  3. 使用 defaultPOSTConfig(null, session_token),沒有 JSON body。

主要 caller:

檔案行號呼叫情境
RequestDetail.js:185-204provider 在 request detail 點電話資訊;失敗時顯示 error popup,成功後把 hidePhoneForPossibleRefund 設為 false。
RequestDetail.js:360request detail 其他 phone flow 進入時呼叫同一支 API。
ChatRoomVendor.js:546-573vendor chat panel 點電話;只有 hidePhoneForPossibleRefund 為 true 時呼叫。
BidMessages.js:203-224message / quote bid chat panel 點電話;只有 hidePhoneForPossibleRefund 為 true 時呼叫。
BidMessages.js:407-416message 內 phone 顯示流程同樣會呼叫。

Legacy Controller Rule

legacy 檔案:

/Users/mattsu/Documents/Site/get-lancer-php56/app/Plugin/Quotes/Controller/QuoteBidsController.php:6229-6298

QuoteBidsController::provider_receive_phone($quote_bid_id)

  1. 預設 response 為 {"status":"success","error":0}6231-6232
  2. 必須是 JSON request 且 valid API session;失敗回 error=7statuserr_provider_receive_phone_7 對應翻譯文字:6235-6236
  3. 從 session 取得 provider user_id6239
  4. quote_bids.id = quote_bid_idquote_bids.provider_user_id = user_id 查 bid:6241-6248
  5. bid 不存在、quote_sent_on 空、或 is_auto_quote = 1 時回 error=8statuserr_provider_receive_phone_8 對應翻譯文字:6250-6255
  6. 讀取 quote request 的 is_closedis_archivedis_expireduser_id6259-6263
  7. request closed / archived / expired 任一為 1 時回 error=9statuserr_provider_receive_phone_9 對應翻譯文字:6264-6269
  8. bid 已退費 is_provider_refunded = 1 時回 error=10statuserr_provider_receive_phone_10 對應翻譯文字:6271-6273
  9. is_provider_received_phone != 1,更新 quote_bids.is_provider_received_phone = 16275-6280
  10. 第一次更新時建立 ProReceivePhone activity:6282-6289
  11. 成功回 {"status":"success","error":0}6292
  12. ProException 透過 handleProApiException($e->getMessageKey(), $e->getCode()) 回 legacy error shape:6293-6294

Legacy Side Effect Rule

成功路徑

成功條件:

  • provider session valid。
  • path quote_bid_id 對應的 bid owner 是目前 provider。
  • bid 已送出報價:quote_sent_on 非空。
  • bid 不是 auto quote:is_auto_quote != 1
  • request 未 closed / archived / expired。
  • bid 未 provider refunded。

legacy / new 都不檢查 quote_bids.is_requestor_readedquote_requests.is_show_phone_to_providers;這兩個條件主要由 web-app 決定何時呼叫。

成功 side effect:

  • quote_bids.is_provider_received_phone = 1
  • 第一次成功時建立 quote_activities.quote_activity_type_id = ConstQuoteActivityType::ProReceivePhone
  • 重複呼叫仍回 success,但因 is_provider_received_phone == 1,不再 update,也不重複建 activity。

不做的事

legacy 這支沒有:

  • fee preview。
  • wallet / card / TapPay payment。
  • transaction。
  • subscription log。
  • event queue / task event queue。
  • notification。
  • request / bid 狀態轉換。

New PHP 8.2 現況

new 檔案行號對應 legacy職責狀態
Lib/Common/RouterRule/Mapping.php:153-155access log path/quote_bids/provider_receive_phone/{quote_bid_id}.json route 到 QuoteBids::provider_receive_phone()已補
Endpoint/V1/QuoteBids.php:3419-3527QuoteBidsController.php:6229-6298session guard、bid/request guard、flag update、activity、success/error response mapping。已補
Lib/DataObject/QuoteBidsDO.php:403-406QuoteBid.php update quote_bids set is_provider_received_phone = 1已有 isProviderReceivedPhone 欄位可用於 update。可沿用
Lib/Constant/ConstQuoteActivityType.php:66ConstQuoteActivityType::ProReceivePhone已有 ProReceivePhone = 55可沿用
Lib/Model/QuoteActivity.php:136-143createQuoteBidActivityById(...)已有建立 QuoteBid activity helper。可沿用
tests/QuoteBidsProviderReceivePhoneTest.php:58-193success / idempotent / guard cases覆蓋成功、重複呼叫、auto quote guard、closed request guard、refunded guard、invalid session guard、request missing legacy behavior。已補

逐段行數對照

controller / routing:

Legacy 行號New 行號對照內容狀態
access log pathMapping.php:153-155route /quote_bids/provider_receive_phone/{quote_bid_id}.json 到 new action。已對齊
QuoteBidsController.php:6229-6236Endpoint/V1/QuoteBids.php:3419-3429action 入口、API session guard;invalid session 回 error=7 與翻譯後 status已對齊
QuoteBidsController.php:6239-6248Endpoint/V1/QuoteBids.php:3432-3446從 session 取得 provider user,並用 quote_bid_id + provider_user_id 查 bid。已對齊
QuoteBidsController.php:6250-6255Endpoint/V1/QuoteBids.php:3448-3457bid 不存在、未送出報價、auto quote 不能取電話;回 error=8 與翻譯後 status已對齊
QuoteBidsController.php:6259-6269Endpoint/V1/QuoteBids.php:3460-3480查 request closed / archived / expired;不可取電話時回 error=9 與翻譯後 status已對齊
QuoteBidsController.php:6271-6273Endpoint/V1/QuoteBids.php:3483-3488provider refunded bid 不可取電話;回 error=10 與翻譯後 status已對齊
QuoteBidsController.php:6275-6280Endpoint/V1/QuoteBids.php:3490-3495第一次取電話時更新 quote_bids.is_provider_received_phone = 1已對齊
QuoteBidsController.php:6282-6289Endpoint/V1/QuoteBids.php:3497-3504, QuoteActivity.php:136-143第一次取電話時建立 ProReceivePhone activity。已對齊
QuoteBidsController.php:6292-6294Endpoint/V1/QuoteBids.php:3507-3516success response 與 ProException error response mapping;status 使用 multi_translation_words 翻譯文字,與 legacy getMessageKey() 行為一致。已對齊

搬移注意

  • path 必須支援 /quote_bids/provider_receive_phone/{quote_bid_id}.json,因正式流量與 web-app 都是 path id。
  • quote_bid_id 必須視為 quote_bids.id
  • 不要新增付款、transaction、queue 或 notification;legacy 沒做。
  • 不要讓 auto quote 通過;legacy 明確以 is_auto_quote = 1 擋掉。
  • is_provider_received_phone = 1 的重複呼叫要回 success,且不重複建立 ProReceivePhone activity。
  • request row 不存在時 legacy 沒有明確 guard,會繼續 success;new 已照此行為處理,activity 的 requestor_user_id 會是 NULL

Verification Scenario Matrix

情境預期
valid provider、manual quote、request open、未 refunded、is_provider_received_phone = 0success;更新 bid flag;建立一筆 ProReceivePhone activity
同一 bid 重複呼叫,is_provider_received_phone = 1success;不重複建立 activity
invalid sessionerror=7, status=發生錯誤,請稍後再試
bid 不存在或不屬於 providererror=8, status=發生錯誤,請稍後再試
quote_sent_onerror=8, status=發生錯誤,請稍後再試
is_auto_quote = 1error=8, status=發生錯誤,請稍後再試
request closed / archived / expirederror=9, status=無法主動取得此客戶聯絡資訊,待客戶讀取報價後顯示
is_provider_refunded = 1error=10, status=此案件已退費,無法取得消費者的聯絡資訊。
request row 不存在但 bid 存在legacy 沒有明確 guard;會更新 is_provider_received_phone = 1,建立 activity 時 requestor_user_id = NULL。new 已照此行為處理。

Staging 舊 Code 實測

2026-05-28:web-app 空 body 呼叫

呼叫:

POST https://api-staging.pro360.com.tw/quote_bids/provider_receive_phone/2147689580.json
body: empty

response:

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

DB 結果:

table欄位結果
api_sessionsid = baigkocqghnqpu60bipc5ork97user_id = 8617
quote_bidsid = 2147689580provider_user_id = 8617, quote_request_id = 22203, quote_sent_on = 2026-05-28 09:01:51, is_auto_quote = 0, is_provider_refunded = 0, is_provider_received_phone = 1
quote_requestsid = 22203user_id = 14738, is_closed = 0, is_archived = 0, is_expired = 0, is_show_phone_to_providers = 1
quote_activitiesid = 406204quote_activity_type_id = 55, provider_user_id = 8617, requestor_user_id = 14738, receiver_user_id = 8617, foreign_id = 22203, secondary_foreign_id = 2147689580

判斷:

  • DB side effect 與 legacy / new 規則一致。
  • 本次 API 只需要確認 is_provider_received_phone = 1ProReceivePhone activity。
  • 同 bid 既有 transactions.id = 36869 是 quote payment / submission 付款紀錄,不是 provider_receive_phone 產生的 side effect。

2026-05-28:new code web-app 空 body 呼叫

呼叫:

POST https://api-staging.pro360.com.tw/quote_bids/provider_receive_phone/2147689387.json
body: empty

response:

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

DB 結果:

table欄位結果
api_sessionsid = baigkocqghnqpu60bipc5ork97user_id = 8617
quote_bidsid = 2147689387provider_user_id = 8617, quote_request_id = 22197, quote_sent_on = 2026-05-28 09:39:35, is_auto_quote = 0, is_provider_refunded = 0, is_provider_received_phone = 1
quote_requestsid = 22197user_id = 6591, is_closed = 0, is_archived = 0, is_expired = 0, is_show_phone_to_providers = 1
quote_activitiesid = 406218quote_activity_type_id = 55, provider_user_id = 8617, requestor_user_id = 6591, receiver_user_id = 8617, foreign_id = 22197, secondary_foreign_id = 2147689387

判斷:

  • response 與 DB side effect 均和 legacy 一致。
  • provider_receive_phone 本身只確認 is_provider_received_phone = 1ProReceivePhone activity。
  • 同 bid 的 transactions.id = 36872 建立於 2026-05-28 09:39:35,是 quote payment / submission 付款紀錄,不是 provider_receive_phone 產生的 side effect。

下一步

  1. 若後續要驗證 guard,可補測 auto quote / refunded / closed request error response。