Making an outbound call

Learn how you initiate a phone call. With this example you will send an HTTP Request to the installed API Extension for starting a Call, and the API will read a text for the Caller.
Please write the following code into the right file at your web server:

Using this example you will be able to send a request to Ozeki Phone System XE through OPS SDK for making and managing an outgoing call. First of all, please login and connect to the API Extension. After that, use the CreateCall method, subscribe the necessary events and start your call.

Next: Log calls

Example code coming soon...
[HttpPost]
public void MakeCall(string dialed, string apiExtension, 
string callerId, string callerDisplayName, string url, string errorUrl)
{
	var serverUri = "http://ozekixepbx.ip:7780/";
	var queryString =
		"?Command=Call" +
		"&Dialed=" + dialed +
		"&ApiExtension=" + apiExtension +
		"&CallerId=" + callerId +
		"&CallerDisplayName=" + callerDisplayName +
		"&Url=" + url +
		"&ErrorUrl=" + errorUrl;

	byte[] data = new ASCIIEncoding().GetBytes(queryString);

	// Prepare web request...
	var request = (HttpWebRequest)WebRequest.Create(serverUri);
	request.Method = "POST";
	request.ContentType = "application/x-www-form-urlencoded";
	request.ContentLength = data.Length;
	Stream newStream = request.GetRequestStream();

	// Send the data.
	newStream.Write(data, 0, data.Length);
	newStream.Close();
}
	
class MakeCallController < ApplicationController

  require 'net/http'

  protect_from_forgery except: :index

  # In routes.rb you need to set the following routing rule
  # get '/make_call' => 'make_call#index'
  
  def index

    ops_ip_address_with_port = "ozekixepbx.ip:7780"
    api_extension = "9999"
    dialed = "2000"
    caller_id = "1000"
    caller_display_name = "Tibi"
    url = "http://yoursite.com:3000/handle_call_response"
    error_url = "http://yoursite.com:3000/handle_call_error"

    query = "http://#{ops_ip_address_with_port}/?Command=Call&Dialed=#{dialed}&
    ApiExtension=#{api_extension}&CallerId=#{caller_id}
    &CallerDisplayName=#{URI::encode(caller_display_name)}
    &Url=#{URI::encode(url)}&ErrorUrl=#{URI::encode(error_url)}"

    uri = URI query
    response = Net::HTTP.get uri 

    render :text => '<b>Response: </b>' + response

  end

end
	
<?php
 	$url = "http://yoursite.com/HandleCallResponse.php";
 	$errorUrl = "http://yoursite.com/HandleCallError.php";
    
    $server = "http://ozekixepbx.ip:7780"; 
    $commandParams['Command'] = "Call"; 
    $commandParams['Dialed'] = "883";
    $commandParams['ApiExtension'] = "9000";
    $commandParams['CallerId'] = "777";
    $commandParams['CallerDisplayName'] = "Joe";
    $commandParams['Url'] = $url;
    $commandParams['ErrorUrl'] = $errorUrl;
    
    $command = http_build_query($commandParams);
    
    $params = array('http' => array('method' => "POST",
                                    'content' => $command));   

    $context = stream_context_create($params);     
       
    $fp = @fopen($server, 'r', false, $context);

    echo "Response: ";
    $response = @stream_get_contents($fp);  
 	echo $response;
?>
	
import urllib
import urllib.request
import urllib.response
import datetime
from cgi import escape

def application(environ, start_response):
    
    result = ""
    if(environ["PATH_INFO"] == ''):
        result = createCall()
    elif(environ["PATH_INFO"] == '/HandleCallResponse'):
        result = getOzmlResponse(environ)
    elif(environ["PATH_INFO"] == '/HandleCallError'):
        result = callErrorOccured(environ)

    response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(result)))]
    start_response('200 OK', response_headers)

    return [result]

def createCall():    
    dict = {}
    dict["Dialed"] = "1001"
    dict["CallerId"] = "1201"
    dict["CallerDisplayName"] = "Mr. Test"
    dict["ApiExtension"] = "9000"
    dict["Url"] = "http://yoursite.com/HandleCallResponse"
    dict["ErrorUrl"] = "http://yoursite.com/HandleCallError"
    
    opsLocation = "ozekixepbx.ip"
    opsPort = 7780
    result = ""

    requestUrl = "http://{}:{}/?Command=Call&{}".format(opsLocation, opsPort, urllib.parse.urlencode(dict))
    
    result += requestUrl
    request = urllib.request.Request(requestUrl)
    response = urllib.request.urlopen(request)

    if(response.status != 200):
        result += "\r\nThe HTTP Status received indicates errors: {}".format(response.status)
        return result

    result += "\r\nCall successfully created."
    return result
	
using System;
using OPSSDK;
using OPSSDKCommon.Model.Call;
using Ozeki.Media.MediaHandlers;

namespace OPS_QuickStartExample_CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new OpsClient();
            client.ErrorOccurred += (sender, info) =>
                Console.WriteLine(info.Message);

            if (!client.Login("ozekixepbx.ip", "admin", "12345"))
                return;

            var apiExtension = client.GetAPIExtension("9000");
            var call = apiExtension.CreateCall("1001");

            var tts = new TextToSpeech();
            tts.Stopped += (s, a) => call.HangUp();
            call.ConnectAudioSender(tts);

            call.CallErrorOccurred += (sender, e) => Console.WriteLine(e.Item);
            call.CallStateChanged += (sender, e) =>
            {
                if (e.Item == CallState.Answered)
                    tts.AddAndStartText("Hello, this is a test call");
                else if (e.Item.IsCallEnded())
                    tts.Dispose();
            };
            call.Start();

            Console.ReadLine();
        }
    }
}
	
Imports OPSSDK
Imports Ozeki.Media.MediaHandlers
Imports OPSSDKCommon.Model.Call

Module Module1
    Public Sub Main(args As String())
        Dim client = New OpsClient()
        AddHandler client.ErrorOccurred, Sub(sender, info)
                                             Console.WriteLine(info.Message)
                                         End Sub

        If Not client.Login("ozekixepbx.ip", "admin", "12345") Then
            Return
        End If

        Dim apiExtension = client.GetAPIExtension("9000")
        Dim [call] = apiExtension.CreateCall("1001")

        Dim tts = New TextToSpeech()
        AddHandler tts.Stopped, Sub(s, ev)
                                    [call].HangUp()
                                End Sub
        [call].ConnectAudioSender(tts)

        AddHandler [call].CallErrorOccurred, Sub(sender, e)
                                                 Console.WriteLine(e.Item)
                                             End Sub

        AddHandler [call].CallStateChanged,
            Sub(sender, e)
                If e.Item = CallState.Answered Then
                    tts.AddAndStartText("Hello, this is a test call")
                ElseIf e.Item.IsCallEnded() Then
                    tts.Dispose()
                End If
            End Sub

        [call].Start()
        Console.ReadLine()
    End Sub
End Module
	
#!c:/Perl64/bin/perl.exe   
print "Content-Type: text/plain\n\n";
#You have to add the directory route of perl.exe, and print the content type

$address = "ozekixepbx.ip:7780"; #ip address of PBX, and the port of HttpAPI (default: 7780)
$dialedNumber = "1001";
$apiExtensionId = "9000"; 
$callerId = "777";
$callerDisplayName = "Joe";
$url = "http://yoursite.com/HandleCallResponse.pl";
$errorUrl = "http://yoursite.com/HandleCallError.pl";

use LWP::UserAgent;
$ua = LWP::UserAgent->new;

# Create and Send request
$req = HTTP::Request->new(GET => "http://$address/?Command=Call&Dialed=
$dialedNumber&ApiExtension=$apiExtensionId&CallerId=$callerId&CallerDisplayName=
$callerDisplayName&Url=$url&ErrorUrl=$errorUrl");
$res = $ua->request($req);

# Check the result of the request sending
if ($res->is_success) { print "\n". $res->decoded_content . "\n" }
else { print "\nError: " . $res->status_line . "\n" }
	
package pbxsampleapp;

import com.sun.net.httpserver.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class MakingAnOutboundCall 
{
    public static void main(String[] args)
    {
        try
        {
            RunHttpServerforCallresult();
            makeCall("5500", "5440", "http://yoursite.com/callresult?action=connected",
            "http://yoursite.com/callresult?action=error");
        }
        catch (IOException ex){ System.out.println("Error" + ex.toString());}
    }

    private static void makeCall(String extension, String dialed, String url, String errorUrl) throws IOException
    {
        String queryParams = 
                "command=Call&ApiExtension=" + URLEncoder.encode(extension, "UTF-8")
                + "&Dialed=" + URLEncoder.encode(dialed, "UTF-8")
                + "&Url=" + URLEncoder.encode(url, "UTF-8")
                + "&ErrorUrl=" + URLEncoder.encode(errorUrl, "UTF-8");
        URL requrl = new URL("http://ozekixepbx.ip:7780/?" + queryParams);
        URLConnection conn = requrl.openConnection();
        InputStream input = conn.getInputStream();
        byte[] b = new byte[input.available()];
        input.read(b);
        System.out.println(new String(b));
    }

    private static void RunHttpServerforCallresult()
    {
        try
        {
            System.out.println("Starting http server for callresult...");
            HttpServer server = HttpServer.create(new InetSocketAddress
            (InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }), 12345), 0);
            server.createContext("/callresult", new PbxSampleApp.PBXRequestHandler());
            server.start();
            System.out.println("http server running on " + server.getAddress().toString());
        }
        catch (IOException ex){ System.out.println("Error" + ex.toString());}
    }
}
	
<!DOCTYPE html>
<html>
<head>
</head>
<body>
	<form action="http://ozekixepbx.ip:7780" method="POST">
		<input type="hidden" name="Command" value="Call">
		<input type="text" name="ApiExtension" value="9999">		
		<input type="text" name="Dialed" value="1001">
		<input type="text" name="CallerId" value="123456789">
		<input type="text" name="CallerDisplayName" value="Joe">
		<input type="hidden" name="Url" value="http://yoursite.com/CallResponse.xml">
		<input type="hidden" name="ErrorUrl" value="http://yoursite.com/CallError.php">
		<input type="submit" value="Make Call">
	</form>
</body>
</html>
	
Code example 1 - Make a call, by sending an HTTP Request to the PBX

Read information about the Request parameters at the following page. Please change the ozekixepbx.ip text to that ip address where the Ozeki Phone System is installed. On the yoursite.com the address should be that where the sample applications are running. The API will get the Request and execute the given OzML commands (that can be found at the Url parameter of the request). In this example, the OzML command looks like this:

[HttpPost]
public ActionResult HandleCallResponse(string notificationName, 
string callLegID, string callee, string apiExtension)
{
	return Content(
   "<Response>" +
	   "<Speak>Hello, this is a test call on " 
	   + DateTime.Now.ToString("MMMM.dd", CultureInfo.InvariantCulture) + "</Speak>" +
   "</Response>", "text/xml");
}
	
class HandleCallResponseController < ApplicationController

  require 'date'
  require 'time'
  protect_from_forgery except: :index

  # In routes.rb you need to set the following routing rule
  # post '/handle_call_response' => 'handle_call_response#index'
  
  # http://yoursite.com:3000/handle_call_response
  def index
    
    receive_time = Date::ABBR_MONTHNAMES[Date.today.month] + ' ' + Date.today.day.to_s 
    render :xml => '<?xml version="1.0" encoding="UTF-8"?>
    <Response>
      <Speakd>Hello, this is a test call on ' + receive_time + '</Speak>
    </Response>'
    
  end

end
	
<?php
	$receiveTime = date("M.d");
	print "<Response>";
		print "<Speak>Hello, this is a test call on $receiveTime</Speak>";
	print "</Response>";
?>
	
#!c:/Perl64/bin/perl.exe   
print "Content-Type: text/plain\n\n";
#You have to add the directory route of perl.exe, and print the content type

my($day, $month)=(localtime)[3,4];
#Send response by print
	
print
'<?xml version="1.0" encoding="UTF-8"?>
<Response>
	<Speak>Hello, this is a test call on '.$month.'.'.$day.'</Speak>
</Response>'
	
def getOzmlResponse(environ):
    today = datetime.datetime.now();

    return """<?xml version="1.0" encoding="UTF-8"?>
        <Response>
            <Speak>Hello, this is a test call on {0}</Speak>
        </Response>""".format(today.strftime('%B %d'))

	
static String HandleResponse(String query, Map<String, String> params)
{ 
    if (query.contains("action=connected")) 
             return "<?xml version=\"1.0\"?>"
                    + "<Response>"
                    + "<Speak>Hello, this is a test call on " 
                    + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new Date())
                    + "!</Speak>"
                    + "</Response>";
    else if (query.contains("action=error"))
          for (Map.Entry<String, String> entry : params.entrySet())
            {
                String string = entry.getKey();
                String string1 = entry.getValue();
                System.out.println(String.format("%s %S", string, string1));   
            }
    return "";
}

static class PBXRequestHandler implements HttpHandler
{
    @Override
    public void handle(HttpExchange httpExchange) throws IOException
    {
        InputStream inputStream = httpExchange.getRequestBody();
        byte[] body = new byte[inputStream.available()];
        inputStream.read(body);
        String response = "";
        String query = httpExchange.getRequestURI().getQuery().toLowerCase();
       
        if (query.contains("action=connected") || query.contains("action=error"))
          response =  HandleResponse(query ,parseBody(body));
                  
        if (response.length()==0 )
           httpExchange.getResponseHeaders().add("Content-type", "text/html");
       else
            httpExchange.getResponseHeaders().add("Content-type", "text/xml");
        httpExchange.sendResponseHeaders(200, response.length());
        OutputStream os = httpExchange.getResponseBody();
        os.write(response.getBytes());
        os.close();
    }

    private Map<String, String> parseBody(byte[] params) throws UnsupportedEncodingException
    {
        Map<String, String> query_pairs = new LinkedHashMap<String, String>();
        String[] pairs = URLDecoder.decode(new String(params), "UTF-8").split("&");
        String paramname;
        String value;
        for (String pair : pairs)
        {
            int idx = pair.indexOf("=");
            paramname = pair.substring(0, idx);
            value = pair.substring(idx + 1);
            query_pairs.put(paramname, value);
            System.out.println(String.format("%s: %s", paramname, value));
        }
        return query_pairs;
    }
}
	
<Response>
  <Speak>This is a test call</Speak>
</Response>
	
Code example 2 - Speak to the Caller, and hang up the line.

The API Extension just say “Hello, this is a test call” sentence to the Caller, and hang up the line. If any errors occur during the call then the ErrorUrl will be requested. For example you can write a simple application on that URL, what will log the errors.

IN MORE DETAILS

Get the OPSSDK.dll

First you need to add the OPSSDK.dll reference to your project
(You can find OPSSDK.dll at C:\Program Files\Ozeki\Ozeki Phone System\Examples.NET API\OPSSDK.dll).

Login and connect

Create a new instance of OpsClient, and subscribe to the ErrorOccurred event. Your program will communicate with the Ozeki Phone System through this client. Try to login with the client into the running Ozeki Phone System, with the address of the server(ozekixepbx.ip) and a valid username, password combination.

If you are ready, try to get an existing API Extension, with the GetApiExtension method of the OpsClient. Read more about installation of API Extension.

Further steps

When you are ready with the initial steps above, please create a call object with the help of apiExtension's CreateCall method. Subscribe the CallStateChanged, CallErrorOccurred events of the call object and call call.Start() method.

The CallStateChanged event will be triggered when the call is going to another state . When the CallState is Answered, you can connect the devices to the call. When the call has ended, please do not forget to disconnect all devices from the call.

When the CallState is Answered, start and connect a TextToSpeech object to the call, that will read the "Hello, this is a test call" text to the caller. When the TextToSpeech is finished the call will hang up.

With these steps, you learned how to make a call.

More information