QuoteBids Provider Receive Phone
對應 legacy / web-app 實際 API:
POST /quote_bids/provider_receive_phone/{quote_bid_id}.jsonquote_bid_id 是 quote_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_readed 或 quote_requests.is_show_phone_to_providers。
成功時,這支 API 只做兩件同步 side effect:
- 將同一筆
quote_bids.id的is_provider_received_phone更新為1。 - 第一次更新時建立
ProReceivePhoneactivity。
這支不走付款主線,不寫 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-242access 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.1 | 741 |
get-lancer_access.log.*.gz | 5505 |
| total | 6246 |
HTTP status 分布:
| status | 筆數 |
|---|---|
| 200 | 6246 |
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 -50path 分布重點:
| 筆數 | path |
|---|---|
| 5 | quote_bids/provider_receive_phone/2521422439.json |
| 2 | quote_bids/provider_receive_phone/2533067063.json |
| 2 | quote_bids/provider_receive_phone/2532625992.json |
| 2 | quote_bids/provider_receive_phone/2532446472.json |
| 2 | quote_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-812APIManager.providerReceivePhone(quoteId):
- 從 local token 取得 provider session token。
- 呼叫
POST /quote_bids/provider_receive_phone/${quoteId}.json。 - 使用
defaultPOSTConfig(null, session_token),沒有 JSON body。
主要 caller:
| 檔案行號 | 呼叫情境 |
|---|---|
RequestDetail.js:185-204 | provider 在 request detail 點電話資訊;失敗時顯示 error popup,成功後把 hidePhoneForPossibleRefund 設為 false。 |
RequestDetail.js:360 | request detail 其他 phone flow 進入時呼叫同一支 API。 |
ChatRoomVendor.js:546-573 | vendor chat panel 點電話;只有 hidePhoneForPossibleRefund 為 true 時呼叫。 |
BidMessages.js:203-224 | message / quote bid chat panel 點電話;只有 hidePhoneForPossibleRefund 為 true 時呼叫。 |
BidMessages.js:407-416 | message 內 phone 顯示流程同樣會呼叫。 |
Legacy Controller Rule
legacy 檔案:
/Users/mattsu/Documents/Site/get-lancer-php56/app/Plugin/Quotes/Controller/QuoteBidsController.php:6229-6298QuoteBidsController::provider_receive_phone($quote_bid_id):
- 預設 response 為
{"status":"success","error":0}:6231-6232。 - 必須是 JSON request 且 valid API session;失敗回
error=7、status為err_provider_receive_phone_7對應翻譯文字:6235-6236。 - 從 session 取得 provider
user_id:6239。 - 以
quote_bids.id = quote_bid_id且quote_bids.provider_user_id = user_id查 bid:6241-6248。 - bid 不存在、
quote_sent_on空、或is_auto_quote = 1時回error=8、status為err_provider_receive_phone_8對應翻譯文字:6250-6255。 - 讀取 quote request 的
is_closed、is_archived、is_expired、user_id:6259-6263。 - request closed / archived / expired 任一為
1時回error=9、status為err_provider_receive_phone_9對應翻譯文字:6264-6269。 - bid 已退費
is_provider_refunded = 1時回error=10、status為err_provider_receive_phone_10對應翻譯文字:6271-6273。 - 若
is_provider_received_phone != 1,更新quote_bids.is_provider_received_phone = 1:6275-6280。 - 第一次更新時建立
ProReceivePhoneactivity:6282-6289。 - 成功回
{"status":"success","error":0}:6292。 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_readed 或 quote_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-155 | access log path | 將 /quote_bids/provider_receive_phone/{quote_bid_id}.json route 到 QuoteBids::provider_receive_phone()。 | 已補 |
Endpoint/V1/QuoteBids.php:3419-3527 | QuoteBidsController.php:6229-6298 | session guard、bid/request guard、flag update、activity、success/error response mapping。 | 已補 |
Lib/DataObject/QuoteBidsDO.php:403-406 | QuoteBid.php update quote_bids set is_provider_received_phone = 1 | 已有 isProviderReceivedPhone 欄位可用於 update。 | 可沿用 |
Lib/Constant/ConstQuoteActivityType.php:66 | ConstQuoteActivityType::ProReceivePhone | 已有 ProReceivePhone = 55。 | 可沿用 |
Lib/Model/QuoteActivity.php:136-143 | createQuoteBidActivityById(...) | 已有建立 QuoteBid activity helper。 | 可沿用 |
tests/QuoteBidsProviderReceivePhoneTest.php:58-193 | success / idempotent / guard cases | 覆蓋成功、重複呼叫、auto quote guard、closed request guard、refunded guard、invalid session guard、request missing legacy behavior。 | 已補 |
逐段行數對照
controller / routing:
| Legacy 行號 | New 行號 | 對照內容 | 狀態 |
|---|---|---|---|
| access log path | Mapping.php:153-155 | route /quote_bids/provider_receive_phone/{quote_bid_id}.json 到 new action。 | 已對齊 |
QuoteBidsController.php:6229-6236 | Endpoint/V1/QuoteBids.php:3419-3429 | action 入口、API session guard;invalid session 回 error=7 與翻譯後 status。 | 已對齊 |
QuoteBidsController.php:6239-6248 | Endpoint/V1/QuoteBids.php:3432-3446 | 從 session 取得 provider user,並用 quote_bid_id + provider_user_id 查 bid。 | 已對齊 |
QuoteBidsController.php:6250-6255 | Endpoint/V1/QuoteBids.php:3448-3457 | bid 不存在、未送出報價、auto quote 不能取電話;回 error=8 與翻譯後 status。 | 已對齊 |
QuoteBidsController.php:6259-6269 | Endpoint/V1/QuoteBids.php:3460-3480 | 查 request closed / archived / expired;不可取電話時回 error=9 與翻譯後 status。 | 已對齊 |
QuoteBidsController.php:6271-6273 | Endpoint/V1/QuoteBids.php:3483-3488 | provider refunded bid 不可取電話;回 error=10 與翻譯後 status。 | 已對齊 |
QuoteBidsController.php:6275-6280 | Endpoint/V1/QuoteBids.php:3490-3495 | 第一次取電話時更新 quote_bids.is_provider_received_phone = 1。 | 已對齊 |
QuoteBidsController.php:6282-6289 | Endpoint/V1/QuoteBids.php:3497-3504, QuoteActivity.php:136-143 | 第一次取電話時建立 ProReceivePhone activity。 | 已對齊 |
QuoteBidsController.php:6292-6294 | Endpoint/V1/QuoteBids.php:3507-3516 | success 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,且不重複建立ProReceivePhoneactivity。- 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 = 0 | success;更新 bid flag;建立一筆 ProReceivePhone activity |
同一 bid 重複呼叫,is_provider_received_phone = 1 | success;不重複建立 activity |
| invalid session | error=7, status=發生錯誤,請稍後再試 |
| bid 不存在或不屬於 provider | error=8, status=發生錯誤,請稍後再試 |
quote_sent_on 空 | error=8, status=發生錯誤,請稍後再試 |
is_auto_quote = 1 | error=8, status=發生錯誤,請稍後再試 |
| request closed / archived / expired | error=9, status=無法主動取得此客戶聯絡資訊,待客戶讀取報價後顯示 |
is_provider_refunded = 1 | error=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: emptyresponse:
{"status":"success","error":0}DB 結果:
| table | 欄位 | 結果 |
|---|---|---|
api_sessions | id = baigkocqghnqpu60bipc5ork97 | user_id = 8617 |
quote_bids | id = 2147689580 | provider_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_requests | id = 22203 | user_id = 14738, is_closed = 0, is_archived = 0, is_expired = 0, is_show_phone_to_providers = 1 |
quote_activities | id = 406204 | quote_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 = 1與ProReceivePhoneactivity。 - 同 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: emptyresponse:
{"status":"success","error":0}DB 結果:
| table | 欄位 | 結果 |
|---|---|---|
api_sessions | id = baigkocqghnqpu60bipc5ork97 | user_id = 8617 |
quote_bids | id = 2147689387 | provider_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_requests | id = 22197 | user_id = 6591, is_closed = 0, is_archived = 0, is_expired = 0, is_show_phone_to_providers = 1 |
quote_activities | id = 406218 | quote_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 = 1與ProReceivePhoneactivity。- 同 bid 的
transactions.id = 36872建立於2026-05-28 09:39:35,是 quote payment / submission 付款紀錄,不是provider_receive_phone產生的 side effect。
下一步
- 若後續要驗證 guard,可補測 auto quote / refunded / closed request error response。