Flashphoner.createSession(...).createCall({callee:'+74957718000'}).call();

In this article we will explain how to create a button to make a call to any mobile or stationary phone number directly from a web page.

The flowchart of a call

First of all, we need a SIP-account of a VoIP operator. The operator picks up an internet call (VoIP) and dials the specified mobile or stationary phone.

Tasks we need to solve are as follows:

  1. Send SIP INVITE to the SIP operator.
  2. Accept SIP 200 OK from the operator.
  3. Receive sound from the operator.
  4. Send sound from the browser to the operator.

A browser does not work via plain SIP / TCP and SIP / UDP protocols, that is why we need a medium server that will communicate with the operator using classic SIP / UDP.

Server SIP / UDP

SIP account

To obtain a SIP account, you can, for example, register at the sipnet VoIP telephony service or at any other provider that offers lines for calls to mobile phones.

A SIP account consists of the following six parameters:

  1. Login
    Example alice123
  2. Authentication name (can differ from the login or be the same).
    Example alice123
  3. Password
    Example ******
  4. Domain
    Example sipnet.ru
  5. Proxy (can differ from the domain or be the same)
    Example sipnet.ru
  6. Port (usually 5060)
    Example 5060

Simplified SIP account

Often, domain is the same as outbound proxy and login is equal to authentication name, and the port is standard 5060. In this instance, the SIP operator can offer a SIP account in a simplified form:

Login alice123
Password ***
Domain sipnet.ru

This looks similar to a typical web account. After you have the access, you can test it with any softphone available, e.g. Xlite, Linphone, Ekiga, and so on.

Testing with a desktop softphone

When using Bria 4 softphone, SIP connection settings look as follows:

The connection settings for SIP

Usually, the provider offers numbers you can make a SIP call to. Some providers also give free minutes when you refill the balance.

Now, we need to make a call using the softphone and make sure SIP calls indeed pass to normal phones. For example, let us call to this Moscow number +74957718000.

Call from Softphone

If calls works correctly in a desktop softphone, we can go on to a browser phone and browser calls.

HTML page for a call

Browser calls utilize the WebRTC technology and flow through Web Call Server 5, which communicates with the browsers via WebRTC and make calls to the SIP operator via SIP.

Browser-based calls via WebRTC

The HTML code of the page to make calls is rather compact and takes as few as 13 lines:

<html>
<head lang="en">
   <script type="text/javascript" src="https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/current/flashphoner.js"></script>
    <script language="javascript" src="click-to-call.js"></script>
</head>
<body onload="init_page()">
<button id="callButton" type="button" onclick="connectAndCall('+74957718000')">Call</button>
<button id="hangupButton" type="button" onclick="hangup()">Hangup</button>
<div id="remoteMedia" style="visibility: hidden"></div>
<div id="localMedia" style="visibility: hidden"></div>
<p id="status"></p>
</body>
</html>

The page has the Call buton to make a call and the Hangup button to end it. There is a box, where the current status is displayed.

The localMedia and remoteMedia dive elements are used to embed objects that perform sending and receiving sound to the page.

The flashphoner.js script is available in the Web SDK build.

Script click-to-call.js to make a call

The click-to-call.js script has 97 lines. With this script, a connection to the server is established and a call is made.

var localMedia;
var remoteMedia;
var outCall;
 
//init API
function init_page() {
    Flashphoner.init();
    localMedia = document.getElementById("localMedia");
    remoteMedia = document.getElementById("remoteMedia");
}
 
//call
function connectAndCall(number) {
 
    //if already connected, make a call
    if (Flashphoner.getSessions().length > 0) {
        call(number, Flashphoner.getSessions()[0]);
    } else {
 
        //SIP credentials
        var sipOptions = {
            login: "10001",
            authenticationName: "10001",
            password: "12345",
            domain: "192.168.1.3",
            outboundProxy: "192.168.1.3",
            port: "5060",
            registerRequired: false
        };
 
        var connectionOptions = {
            urlServer: "wss://wcs5-eu.flashphoner.com:8443",
            sipOptions: sipOptions
        };
 
        //create new connection to WCS server
        Flashphoner.createSession(connectionOptions).on(Flashphoner.constants.SESSION_STATUS.ESTABLISHED, function (session) {
            setStatus("Session", Flashphoner.constants.SESSION_STATUS.ESTABLISHED);
            //session connected, place call
            call(number, session);
        }).on(Flashphoner.constants.SESSION_STATUS.DISCONNECTED, function () {
            setStatus("Session", Flashphoner.constants.SESSION_STATUS.DISCONNECTED);
            onHangup();
        }).on(Flashphoner.constants.SESSION_STATUS.FAILED, function () {
            setStatus("Session", Flashphoner.constants.SESSION_STATUS.FAILED);
            onHangup();
        });
    }
}
 
function call(number, session) {
 
    //disable call button
    document.getElementById("callButton").disabled=true;
 
    var constraints = {
        audio: true,
        video: false
    };
 
    //prepare outgoing call
    outCall = session.createCall({
        callee: number,
        visibleName: "Click To Call",
        localVideoDisplay: localMedia,
        remoteVideoDisplay: remoteMedia,
        constraints: constraints,
        receiveAudio: true,
        receiveVideo: false
    }).on(Flashphoner.constants.CALL_STATUS.RING, function () {
        setStatus("Call", Flashphoner.constants.CALL_STATUS.RING);
    }).on(Flashphoner.constants.CALL_STATUS.ESTABLISHED, function () {
        setStatus("Call", Flashphoner.constants.CALL_STATUS.ESTABLISHED);
    }).on(Flashphoner.constants.CALL_STATUS.FINISH, function () {
        setStatus("Call", Flashphoner.constants.CALL_STATUS.FINISH);
        onHangup();
    }).on(Flashphoner.constants.CALL_STATUS.FAILED, function () {
        setStatus("Call", Flashphoner.constants.CALL_STATUS.FAILED);
        onHangup();
    });
 
    outCall.call();
}
 
function hangup() {
    if (outCall) {
        outCall.hangup();
    }
}
 
function onHangup(){
    //will be invoked on hangup
}
 
function setStatus(callOrSession,status){
    document.getElementById("status").innerHTML= callOrSession +" "+status;
}

Here are four functions we want to highlight in this script:

  • Initialization
  • Establishing connection to the server
  • Calling
  • Hanging up

Initialization

Here, we simply call the init() function and initialize the API.

Flashphoner.init();

Establishing connection to the server

Here, we connect to the server via the secure websockets protocol and send data of the SIP account, so that the server in turn could connect to the SIP operator (provider) too.

var sipOptions = {
            login: "10001",
            authenticationName: "10001",
            password: "12345",
            domain: "192.168.1.3",
            outboundProxy: "192.168.1.3",
            port: "5060",
            registerRequired: false
};
 
var connectionOptions = {
            urlServer: "wss://wcs5-eu.flashphoner.com:8443",
            sipOptions: sipOptions
};
 
Flashphoner.createSession(connectionOptions);

Calling

We create a call and invoke the call() method. When we create a call, we send the callee parameter. This is a number of the subscriber we want to call to, for instance, a mobile number.

outCall = session.createCall({
        callee: number,
        visibleName: "Click To Call",
        localVideoDisplay: localMedia,
        remoteVideoDisplay: remoteMedia,
        constraints: constraints,
        receiveAudio: true,
        receiveVideo: false
});
 
outCall.call();

Hanging up the call

To hang up the call, we invoke the hangup() API method.

outCall.hangup();

Testing the web page of the call

To run the test in Google Chrome we need to upload click-to-call.html and click-to-call.js files to the web server that supports https. Chrome allows microphone access only for secure pages (https) The source code of the scripts is available for download here.

Scripts connect to the test server wss://wcs5-eu.flashphoner.com:8443. To test with your own server, install WCS5 to a Linuc system. You can download the WCS5 server with this link.

Open the click-to-call.html page in Google Chrome and click the Call button. The server receives the call and sends the ESTABLISHED status. A mobile subscriber picks up the phone, and as a result the call between the browser and the mobile phone is established.

Call between browser and mobile phone

In conclusion, we reviewed how SIP accounts of IP telephony providers look like, tested calls with softphones, created two files to make a call from the browser: click-to-call.html and click-to-call.js and tested these scripts by making a call from the Google Chrome browser to a mobile phone through the SIP operator. A call from the browser goes to Web Call Server 5 and then to the SIP operator where it lands to the mobile phone.

References

SIP – session initiation protocol used in VoIP telephony
Web Call Server – WebRTC-SIP gateway to allows browser to work with SIP telephony.
Web SDK – JavaScript API of the server to develop browser phones. The build contains the flashphoner.js script.
Source – scripts click-to-call.html and click-to-call.js