Speaking in Whispers: Creating a “Whisper” Dialog Using a Tropo Conference

September 16th, 2011 by Justin Dupree

We often get a common request to create a “whisper” dialog, where an inbound call is transferred to a second contact, and that contact has the option to decline the call or accept it. While our transfer doesn’t have that level of functionality, there is a relatively straightforward method using a conference to mimic it.

The following app is written in PHP and intended for Tropo Scripting; it also utilizes our REST API to submit an interrupt signal, which we’ll get into in more detail shortly.

We’ll need to initially describe what the app does, as it loops back on itself, making code breakouts difficult to explain linearly. Essentially, the app has if/else logic built into to handle an inbound call and an outbound call. When an inbound call comes in, Tropo drops the user into a conference and lets them sit for a few moments. While they wait, Tropo relaunches the same app using the curl REST client for PHP and makes an outbound call to a second contact. When this contact picks up, they’re prompted to accept or decline a call – if they say yes, they’re dropped into the same conference as the inbound caller. If they say no, Tropo disconnects the original conference with the inbound caller using a signal and then disconnects the outbound call as well.

With the general explanation out of the way, we’ll move on to the code. First, we define a couple of functions:

<?php

function choiceFCN($event) {
    global $session;
    if ($event->value == "yes") {
        conference("1337");
    }
    else {
        $curl_handle=curl_init(); 
        curl_setopt($curl_handle,CURLOPT_URL,'https://api.tropo.com
/1.0/sessions/'.$session.'/signals?action=signal&value=exit'); 
        curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2); 
        curl_exec($curl_handle); 
        curl_close($curl_handle);
        say("You declined, disconnecting");
    }
}

function badChoiceFCN($event) {
    say("I’m sorry,  I didn’t understand that. You can say yes or no");
}

These functions determine what to do when the outbound call recipient says yes or no, or something completely different like “okay”. choiceFCN is the more complicated of the two – if the recipient says ‘yes’, then you can see where the conference is connected. If they say ‘no’, curl is utilized to submit a signal to the inbound caller’s conference to disconnect it, and then disconnects the outbound call as well.

Next, we have the if/else functionality, which is the bulk of the app:

if ($currentCall->callerID == null) {
    call("+14075550100");
    ask("Do you want to connect to ".$caller."?", array(
        "choices" => "yes, no",
        "timeout" => 10.0,
        "attempts" => 3,
        "onChoice" => "choiceFCN",
        "onBadChoice" => "badChoiceFCN"
        )
    );
}
else {
    $token = 'your_token';
    $callerID = $currentCall->callerID;
    $sessionID = $currentCall->sessionId; 
    $curl_handle=curl_init(); 

    curl_setopt($curl_handle,CURLOPT_URL,'http://api.tropo.com/1.0/
sessions?action=create&token='.$token.'&caller='.$callerID.'
&session='.$sessionID); 
    curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2); 
    curl_exec($curl_handle); 
    curl_close($curl_handle); 

    say("please hold while we connect your call");
    conference("1337", array(
        "allowSignals" => "exit"
        ));
    say("The recipient declined the call.  Goodbye.");
    }
?>

The inbound/outbound detection is done through the use of “callerID” – no callerID means the app was launched using a token, and therefore outbound. So if callerID is null, trigger the outbound portion of the app; if there is a callerID, launch the inbound portion.

The outbound portion is relatively straightforward – call out to a number, ask the user if they want to connect, use the onChoice and onBadChoice handlers to define which function to use in each case. The inbound, on the other hand, is a little more complex. There’s several variables to start:

$token = 'your_token'; $callerID = $currentCall->callerID; $sessionID = $currentCall->sessionId;

First variable is the token for your app, which is found beneath the URLs when you’re looking at your app in the Tropo UI. Second is saving the callerID of the inbound user for use during the outbound session, and then the sessionID as well for use in the signaling.

Once the variables are locked in, the curl to relaunch the app for the outbound call is started, and then the inbound caller is dropped into the conference. Note in the URL for the curl we add in the variable from earlier – this passes them into the outbound portion of the app as variables that we can then use. Also note in the actual conference the inbound caller is added to, there’s an extra variable in there called “allowSignals”. This is where you define a keyword (or “signal”) that can be used by the REST API to interrupt the conference, dropping the caller back to the application. If the outbound user says “no” and the signal is sent (defined in the URL

https://api.tropo.com/1.0/sessions/'.$session.'/signals?action=signal&value=exit

shown in the earlier portion of code), the conference will disconnect and the inbound user will hear “The recipient declined the call. Goodbye.”

That’s the extent of it; hope it helps someone! You can find the complete app on my Github, feel free to use it and abuse it as you see fit.

Related posts:

  1. Tropo’s in Poland, so we’re speaking Polish
  2. Building a full-featured conference call application with Tropo and PHP
  3. Conference Call Apps Made Easy with Tropo
  4. Creating a Chat Room Interface using Multiple Conferences
  5. The Conference Pop-In Timer

Leave a Reply

Please note: By submitting a comment you agree to comply with our Comment Policy. We welcome all comments, positive or negative, but do reserve the right to remove all or part of blog comments that do not comply with our policy.

Additionally, the first time you leave a comment on this blog, it will be held for moderation. After that first comment has been approved, future comments will be posted without delay.

Additional comments powered by BackType