1

I have a system built that does Browser to Browser calls.

When a call comes in the use accepts and they can communicate without any problems! Hooray for twilio.

So now we have two people - the person who received the call (Let's call them the receiver) and the the person who made the call (Let's call them the Dialer)

The receiver then has a button l called Place on Hold. When this is clicked it redirects the Receiver to a looping message of You have a call on hold and also redirects the Dialer to a queue - they get some funky music to listen to.

If it is clicked again, the Receiver dials the queue and gets the caller. This works perfectly as well and they can communicate again.

However.....if I put the dialer back in the queue it works, but when I got to retrieve it via the modify Calls update method and redirecting it to the same part as before the call is not updated.

This throws no errors. It's almost as if twilio is not even trying to redirect the call to the URL as the logs return nothing. As there is no errors my app thinks everything is ok.

Is there a reason why this would happen? Is there a limit or something?

To be clear this works the first time round - perfectly. Just not the next time and only on retrieving the call.

This is a problem with the update command on a Call instance.

Im using Laravel as my framework

Here are my Routes.php

// Hold music and Client Message 
Route::post('voice/queue/music', ['uses' => 'API\VoiceController@queueHoldMusic']);
Route::post('voice/queue/client-message', ['uses' => 'API\VoiceController@clientHoldMusic']);

// Routes containing Twiml XML
Route::post('voice/inbound/enqueue-call', ['uses' => 'API\Voice\InboundCallHoldController@placeInboundCallOnHold']);
Route::post('voice/inbound/dequeue-call', ['uses' => 'API\Voice\InboundCallHoldController@dialHeldInboundCall']);

// Place Outbound Call on Hold
Route::post('inbound/enqueue', ['uses' => 'API\Voice\InboundCallHoldController@holdInboundCall']);
Route::post('inbound/dequeue', ['uses' => 'API\Voice\InboundCallHoldController@getInboundCallOnHold']);

Here is my InboundCallHoldController.php

class InboundCallHoldController extends Controller
{

public function placeInboundCallOnHold(Request $request){
    $CallSid = $request['CallSid'] !== null ? $request['CallSid'] : null;
    $response = new Twiml();
    $queue = 'call-hold:'.$CallSid;

    Log::info("---> Inbound Call | placeInboundCallOnHold --> Enqueuing Caller ".$CallSid." to ".$queue);

    $response->enqueue($queue, ['waitUrl' => env("API_URL").'/api/voice/queue/music']);
    return response($response)->header('Content-Type', 'text/xml');
}

public function dialHeldInboundCall(Request $request){
    $callSid = $request['ParentCallSid'] !== null ? $request['ParentCallSid'] : null;
    $response = new Twiml();
    $dial = $response->dial();

    $queueName = 'call-hold:'.$callSid;

    Log::info("---> Inbound Call | dialHeldInboundCall --> Dialing a queue to get a caller  ".$queueName);

    $dial->queue($queueName);
    $response->redirect(env('API_URL')."/api/voice/queue/client-message");
    return response($response)->header('Content-Type', 'text/xml');
}

public function getInboundCallOnHold(Request $request){
    $callSid = $request['CallSid'] !== null ? $request['CallSid'] : null;

    $account = Account::where("twilio_sid", "TWILIO_ACCOUNT_SID")->first();
    $client = new Client($account->twilio_sid, $account->twilio_auth_token);

    Log::info("---> Inbound Call | getInboundCallOnHold --> Updating Live call and redirecting Caller ".$callSid . " to Queue");
    $call = $client->calls($callSid)->fetch();

    $client->calls($call->sid)->update([
        "url" => env('API_URL')."/api/voice/inbound/dequeue-call",
        "method" => "POST"
    ]);

    Log::info("---> Inbound Call | getInboundCallOnHold --> ".$callSid . " status is now ".$call->status);

    return response([
        "status" => "fetched-inbound-call",
        "success" => true
    ], 200);

}

public function holdInboundCall(Request $request){
    $callSid = $request['CallSid'] !== null ? $request['CallSid'] : null;

    $account = Account::where("twilio_sid", "TWILIO_ACCOUNT_SID")->first();
    $client = new Client($account->twilio_sid, $account->twilio_auth_token);


    Log::info("---> Inbound Call | Hold Initiated");

    $call = $client->calls($callSid)->fetch();
    $parentCall = $client->calls($call->parentCallSid)->fetch();

        if($parentCall->status === "in-progress" and  $call->status == "in-progress"){
            // find the child - this is the receiver - Play the hold music

            Log::info("---> Inbound Call | holdInboundCall --> Redirect Receiver ".$call->sid . " to wait message");

            $call->update([
                "url" => env('API_URL')."/api/voice/queue/client-message",
                "method" => "POST"
            ]);
            // find the parent - this is the inbound caller - Add them to a queue
            Log::info("---> Inbound Call | holdInboundCall --> Redirect Inbound Caller ".$parentCall->sid . " to queue");
            $parentCall->update([
                "url" => env('API_URL')."/api/voice/inbound/enqueue-call",
                "method" => "POST"
            ]);

            return response([
                "status" => "on-hold-inbound",
                "success" => true
            ], 200);
    }


    return response()->json(["call_hold_failed" => ["A call not be placed on hold until it has been answered"]], 422);
}

}

Here is where the update is not occurring after the second time.

$client->calls($call->sid)->update([
    "url" => env('API_URL')."/api/voice/inbound/dequeue-call",
    "method" => "POST"
]);

It's strange as here is the process before it fails;

  1. Place call on Hold --> SUCCESS
  2. Dial Queue and Get Caller from Queue --> SUCCESS
  3. Place call on Hold --> SUCCESS
  4. Dial Queue and Get Caller from Queue --> FAIL

As i've said no error are thrown.

I'm invoking these with Javascript calling the following URLs

// Place Outbound Call on Hold
Route::post('inbound/enqueue', ['uses' => 'API\Voice\InboundCallHoldController@holdInboundCall']);
Route::post('inbound/dequeue', ['uses' => 'API\Voice\InboundCallHoldController@getInboundCallOnHold']);

Here is a log of the output;

[2017-09-04 13:42:47] local.INFO: ---> Inbound Call | Hold Initiated  
[2017-09-04 13:42:47] local.INFO: ---> Inbound Call | holdInboundCall --> Redirect Receiver CA784af9a0419cde8dc3ab2379ad93e5b2 to wait message  
[2017-09-04 13:42:48] local.INFO: ---> Inbound Call | holdInboundCall --> Redirect Inbound Caller CA3c31e8169647a7d90455058ce7bfa70f to queue  
[2017-09-04 13:42:49] local.INFO: ---> Inbound Call | placeInboundCallOnHold --> Enqueuing Caller CA3c31e8169647a7d90455058ce7bfa70f to call-hold:CA3c31e8169647a7d90455058ce7bfa70f  
[2017-09-04 13:43:09] local.INFO: ---> Inbound Call | getInboundCallOnHold --> Updating Live call and redirecting Caller CA784af9a0419cde8dc3ab2379ad93e5b2 to Queue  
[2017-09-04 13:43:10] local.INFO: ---> Inbound Call | getInboundCallOnHold --> CA784af9a0419cde8dc3ab2379ad93e5b2 status is now in-progress  
[2017-09-04 13:43:10] local.INFO: ---> Inbound Call | dialHeldInboundCall --> Dialing a queue to get a caller  call-hold:CA3c31e8169647a7d90455058ce7bfa70f  
[2017-09-04 13:43:10] local.INFO: ---> Inbound Call | dialHeldInboundCall --> Call Sid is  CA3c31e8169647a7d90455058ce7bfa70f  
[2017-09-04 13:43:36] local.INFO: ---> Inbound Call | Hold Initiated  
[2017-09-04 13:43:37] local.INFO: ---> Inbound Call | holdInboundCall --> Redirect Receiver CA784af9a0419cde8dc3ab2379ad93e5b2 to wait message  
[2017-09-04 13:43:43] local.INFO: ---> Inbound Call | holdInboundCall --> Redirect Inbound Caller CA3c31e8169647a7d90455058ce7bfa70f to queue  
[2017-09-04 13:43:44] local.INFO: ---> Inbound Call | placeInboundCallOnHold --> Enqueuing Caller CA3c31e8169647a7d90455058ce7bfa70f to call-hold:CA3c31e8169647a7d90455058ce7bfa70f  
[2017-09-04 13:44:06] local.INFO: ---> Inbound Call | getInboundCallOnHold --> Updating Live call and redirecting Caller CA784af9a0419cde8dc3ab2379ad93e5b2 to Queue  
[2017-09-04 13:44:07] local.INFO: ---> Inbound Call | getInboundCallOnHold --> CA784af9a0419cde8dc3ab2379ad93e5b2 status is now in-progress  
YayoUK
  • 11
  • 3
  • Did you check the client side logs? Any known bugs at twilio? Without code, I don't think we can help the most likely problem. – Lucas Sep 01 '17 at 17:37
  • No internal errors in the debugger. It's like a ghost! It says performs the update command (I presume as it doesn't throw any errors) but doesn't actually redirect the call. – YayoUK Sep 01 '17 at 17:40
  • I will post some code when I get back to my desk – YayoUK Sep 01 '17 at 17:40
  • Glad to hear you're going to add some code, I was going to ask for that too. Happy to help when you've added it to the question :) – philnash Sep 01 '17 at 19:26
  • Hey @philnash I've added some code and really appreciate some help :) – YayoUK Sep 04 '17 at 11:53
  • Thanks for adding the code. Have you checked or done any logging/debugging around the queue dialling action (`dialHeldInboundCall`)? My initial thought would be to check you're definitely getting the right `$callSid` at that point. – philnash Sep 04 '17 at 12:02
  • @philnash Looks fine to me :( I have added a set of logs to the question - as you can see it does not get to the `dialHeldInboundCall` function – YayoUK Sep 04 '17 at 13:50
  • @philnash is there a limit on how often a call can be added/removed from a queue? – YayoUK Sep 05 '17 at 09:12
  • Not that I'm aware of. I'm trying to get more info from the internal team here (and they are in the US and had the day off yesterday). Hopefully I can update you later. – philnash Sep 05 '17 at 09:26
  • Hey @philnash any update from the US – YayoUK Sep 06 '17 at 19:13
  • They are looking into it right now. Can you drop me an email at philnash@twilio.com so that I can keep on top of this and connect you with the team if they need more information? Thanks – philnash Sep 07 '17 at 09:45
  • Still looking to resolve this - support from twilo is non existent - I'm having the same problem as this https://stackoverflow.com/questions/41236926/twilio-retrieve-call-on-hold-back – YayoUK Sep 30 '17 at 15:09

1 Answers1

1

Since OnHoldStatus set via PHP and it does not look like you do any serialization in code, (session tracking in case used in multi user senior)

Is it that the PHP globals or others server side variable are not getting cleared when you exit the OnHold conditions IE: add code just before exit to clear PHP

Or to say it another way it's the PHP variables on your server. They are set to the last state of on old already.

Mogar
  • 11
  • 1