Fix hold functionality to put customer on hold instead of agent

## Hold Logic Fix
- Now correctly identifies which call leg to put on hold
- For browser phone calls (client: prefix), looks for parent call to hold customer
- For regular calls, puts the call recipient on hold
- Agent remains connected and can hear when customer speaks

## Smart Call Leg Detection
- Detects browser phone calls by 'client:' prefix in 'To' field
- Uses parentCallSid to find the customer's call leg
- Falls back gracefully if parent call structure isn't available
- Added detailed error logging to help debug call structures

## Improved User Experience
- Customer hears "Please hold while we assist you" before hold music
- Agent stays connected and can monitor the call
- Resume includes "Thank you for holding" message
- Better messaging tailored to who is actually being put on hold

## Technical Details
- Added call structure analysis and logging
- Proper handling of Twilio's call hierarchy
- Different TwiML logic for browser vs regular phone calls
- Maintains backwards compatibility with existing call flows

This resolves the issue where agents were being put on hold instead of customers when using the browser phone interface.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-30 16:06:54 -07:00
parent 0d0667cf3d
commit e216abdd86

View File

@@ -6943,27 +6943,81 @@ class TWP_Admin {
$client = $twilio->get_client();
if ($hold) {
// Place call on hold with music
// For browser phone calls, we need to find the customer's call leg and put THAT on hold
$hold_music_url = get_option('twp_hold_music_url', '');
if (empty($hold_music_url)) {
// Fall back to default queue music if no hold music is set
$hold_music_url = get_option('twp_default_queue_music_url', 'https://www.soundjay.com/misc/sounds/bell-ringing-05.wav');
}
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->play($hold_music_url, ['loop' => 0]);
// Get the call details to understand the call structure
$call = $client->calls($call_sid)->fetch();
error_log("TWP Hold: Call SID $call_sid - From: {$call->from}, To: {$call->to}, Status: {$call->status}");
$call = $client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
// For browser phone calls, we need to find the parent call or customer leg
if (strpos($call->to, 'client:') === 0) {
// This is the browser client leg - we need to find the customer leg instead
// Look for the parent call or related calls
$conference_sid = $call->parentCallSid;
if ($conference_sid) {
// Use the parent call (which should be the customer)
$customer_call = $client->calls($conference_sid)->fetch();
error_log("TWP Hold: Found parent call $conference_sid - From: {$customer_call->from}, To: {$customer_call->to}");
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->say('Please hold while we assist you.', ['voice' => 'alice']);
$twiml->play($hold_music_url, ['loop' => 0]);
$client->calls($conference_sid)->update([
'twiml' => $twiml->asXML()
]);
} else {
// Fallback: put this call on hold (might be wrong leg but better than nothing)
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->play($hold_music_url, ['loop' => 0]);
$client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
}
} else {
// This appears to be the customer call - put it on hold
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->say('Please hold while we assist you.', ['voice' => 'alice']);
$twiml->play($hold_music_url, ['loop' => 0]);
$client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
}
} else {
// Resume call - for browser phone, just provide empty TwiML to continue
$twiml = new \Twilio\TwiML\VoiceResponse();
// Empty TwiML allows the call to continue normally
// Resume call - similar logic to find the right leg
$call = $client->calls($call_sid)->fetch();
$call = $client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
if (strpos($call->to, 'client:') === 0) {
$conference_sid = $call->parentCallSid;
if ($conference_sid) {
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->say('Thank you for holding.', ['voice' => 'alice']);
// Empty TwiML after message allows call to continue
$client->calls($conference_sid)->update([
'twiml' => $twiml->asXML()
]);
} else {
$twiml = new \Twilio\TwiML\VoiceResponse();
$client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
}
} else {
$twiml = new \Twilio\TwiML\VoiceResponse();
$twiml->say('Thank you for holding.', ['voice' => 'alice']);
$client->calls($call_sid)->update([
'twiml' => $twiml->asXML()
]);
}
}
wp_send_json_success(['message' => $hold ? 'Call on hold' : 'Call resumed']);