want_to_contact_provider

文件狀態:草稿 / 部分已對 new API / 待補完整實測來源
最後驗證:2026-05-07
來源:Common Process Documents 整理、quote_bids migration docs;待補 legacy / new code 逐段來源與 PHPUnit 對照

目的

want_to_contact_provider 是 consumer 從 quote card 進入「正式聯絡 provider」的流程。

API:

POST /quote_bids/want_to_contact_provider/{quote_bid_id}.json

這支 API 不是單純送訊息。成功時會更新 quote_bids 狀態,並可能觸發扣款、activity、queue、簡訊與聊天室訊息。

完整業務 trace 請先看 業務流程/quote_bid_contact。這篇只回答 want_to_contact_providerquote_bids 與相鄰資料表的影響。

主流程簡圖

consumer 呼叫 want_to_contact_provider
-> 驗 API key 與 user session
-> 讀取 quote_bids / quote_requests / provider
-> 若有 message,先寫入聊天室訊息
-> 若有 message,使用 classifyChatGPT 判斷內容是否有效
-> message 被拒絕時回 error 17,不進入正式聯絡
-> message 通過或無 message 時,進入 processWantToContactProvider
-> 更新 quote_bids 聯絡狀態
-> 寫 transaction / activity / queue
-> 回 success

輸入資料

欄位來源說明
quote_bid_idURL raw param要聯絡的 bid
reasonbody聯絡原因,例如 SEND_MESSAGEGET_PHONE_NUMBER_OF_VENDOER
messagebodyconsumer 要傳給 provider 的訊息,可為空
usersession token呼叫者必須是 requestor 或符合流程允許的 user

主要資料表

階段資料表重點欄位
判斷 bidquote_bidsid, quote_request_id, provider_user_id, is_want_to_contact_provider
判斷 requestorquote_requestsid, user_id, auto_quote_contact_count
記錄訊息messages / message_contentsconsumer 傳給 provider 的 message
記錄分類quote_bid_classify_contactsquote_bid_id, message, classes, params
記錄扣款transactionsforeign_id = quote_bid_id, class = QuoteBid
記錄活動quote_activitiesmessage activity、AutoQuoteContact activity
非同步任務task_event_queue / task_event_queue_logcontact count、SMS、badge 等任務

message 分類規則

如果 body 有帶 message,流程會先進 ChatGPT 分類。

常見分類結果:

classes意義是否正式聯絡
not-reject訊息可接受
insignificant內容太空泛,例如只有打招呼
rejected內容不符合聯絡規則

例如:

message = 哈囉
classes = insignificant
response = {"error":17,"status":""}

這代表訊息可能已寫入聊天室,但正式聯絡沒有成立。

message = 我要聯絡
classes = not-reject
response = {"status":"success","error":0}

這代表 message 通過分類,接著進入正式聯絡主線。

成功時的 quote_bids 變化

成功聯絡 provider 後,重點欄位會變成:

quote_bids.is_want_to_contact_provider = 1
quote_bids.contact_provider_on = NOW()
quote_bids.is_interested = 1
quote_bids.reason = <reason>

若流程有扣款或使用 subscription,也要一起看:

quote_bids.total_site_fee
quote_bids.quote_user_subscription_log_id
transactions

完整 wallet / card / TapPay prime / transaction 規則見 付款與扣款流程/quote_bid_contact_charge

失敗或被擋下時

當 message 被分類成 insignificantrejected,legacy 回傳格式是:

{"error":17,"status":""}

這種情況通常會維持:

quote_bids.is_want_to_contact_provider = 0
quote_bids.contact_provider_on = NULL

但仍可能已經產生:

  • messages
  • message 類型的 quote_activities
  • quote_bid_classify_contacts

所以不要只用「有訊息」判斷正式聯絡成功。

Activity 規則

成功聯絡 provider 時會建立 AutoQuoteContact activity。

legacy 非 narrow match 規則:

quote_activity_type_id = AutoQuoteContact
param1 = NULL
param2 = reason

例如:

reason = SEND_MESSAGE
param1 = NULL
param2 = SEND_MESSAGE

若是 narrow match 或其他特殊流程,param1 / param2 可能有不同語意,需要回到該流程文件確認。

常用 SQL

查 bid 與 request 狀態

SELECT
  qb.id,
  qb.quote_request_id,
  qr.user_id AS requestor_user_id,
  qb.provider_user_id,
  qb.quote_service_id,
  qb.is_auto_quote,
  qb.is_contact_charge,
  qb.is_want_to_contact_provider,
  qb.contact_provider_on,
  qb.reason,
  qb.total_site_fee,
  qb.quote_user_subscription_log_id,
  qr.auto_quote_contact_count
FROM quote_bids qb
INNER JOIN quote_requests qr ON qr.id = qb.quote_request_id
WHERE qb.id = <quote_bid_id>;

查 message 分類

SELECT
  id,
  quote_bid_id,
  message,
  model_version,
  classes,
  params,
  created
FROM quote_bid_classify_contacts
WHERE quote_bid_id = <quote_bid_id>
ORDER BY id DESC
LIMIT 10;

查 activity

SELECT
  id,
  created,
  quote_activity_type_id,
  provider_user_id,
  requestor_user_id,
  receiver_user_id,
  model,
  foreign_id,
  secondary_model,
  secondary_foreign_id,
  param1,
  param2
FROM quote_activities
WHERE secondary_foreign_id = <quote_bid_id>
ORDER BY id DESC
LIMIT 20;

查 transaction

SELECT
  id,
  created,
  user_id,
  foreign_id,
  class,
  transaction_type_id,
  amount,
  real_pay_date,
  wallet_balance
FROM transactions
WHERE foreign_id = <quote_bid_id>
  AND class = 'QuoteBid'
ORDER BY id DESC;

查 queue 或 log

SELECT
  id,
  event_key,
  params,
  created
FROM task_event_queue
WHERE params LIKE '%<quote_bid_id>%'
ORDER BY id DESC
LIMIT 20;
SELECT
  id,
  event_key,
  params,
  created
FROM task_event_queue_log
WHERE params LIKE '%<quote_bid_id>%'
ORDER BY id DESC
LIMIT 20;

排查順序

  1. 先查 quote_bids.is_want_to_contact_providercontact_provider_on
  2. 如果有帶 message,查 quote_bid_classify_contacts
  3. quote_activities,確認是否有 AutoQuoteContact
  4. transactions,確認是否有扣款或付款紀錄。
  5. task_event_queue / task_event_queue_log,確認 downstream 任務。
  6. 若 response 是付款或聯絡失敗,優先查 monolog 的 processWantToContactProvider

判斷重點

  • 有 message 不代表正式聯絡成功。
  • 有 message activity 不代表正式聯絡成功。
  • is_want_to_contact_provider = 1 才代表正式聯絡成立。
  • error 17 的 legacy response 是 {"error":17,"status":""}
  • queue 可能已被 worker 搬到 log,驗證時要同時查 queue 與 log。