How to make a call from the website to mobile phone by using JavaScript
In this article, we’ll show you how to make a button for a call from a website page to a mobile or landline phone number.
Flashphoner.createSession(...).createCall({callee:<span class="hljs-string">'+1647*******'</span>}).call();
Call scheme
First of all, you need an SIP-account of the operator of VoIP telephony. The operator “lands” the call, going on the Internet (VoIP) and dialing up to a mobile or landline phone.
Our tasks, in this case, are as follows:
- Send SIP INVITE in the direction of the SIP operator.
- Accept the SIP 200 OK from the operator.
- Take sound from the operator.
- Send sound from the browser to the operator.
The browser does not work on honest SIP / TCP and SIP / UDP protocols, so in our scheme, there will be an intermediary server that will talk to the operator on the classic SIP / UDP.
SIP account
To get a SIP account, you can register, for example, in VoIP telephony service sipnet or from any other provider that provides lines for calls to mobile phones.
The SIP account consists of the following six parameters:
- Login
For example alice123 - Name for authentication (may differ from login or match).
For example alice123 - Password
For example ****** - Domain Name
For example sipnet.ru - Proxy (may differ from domain or match)
For example sipnet.ru - Port (usually 5060)
For example 5060
Simplified SIP account
It often happens that the domain matches the outbound proxy and login matches the authentication name, and the port uses the standard 5060. In this case, the SIP operator can provide the SIP account in a simplified form:
Then something similar to the usual access to the web resource. After access, it is possible to test it with any of the softphones, for example, Xlite, Linphone, Ekiga, etc.
Test with desktop softphone
When using the Bria 4 softphone, the SIP connection settings look like this:
Usually, the provider provides numbers to which you can make a SIP call. Some providers give free minutes with minimal replenishment of the account.
It remains to call from the softphone and make sure that SIP calls do go to normal phones. For example, call the Ministry of Communications on the phone number +1647*******.
If the calls work normally through the desktop softphone, you can go to the browser phone and to browser calls.
HTML page for the call
Browser calls will go via WebRTC technology through the Web Call Server 5 server, which, on the one hand, works with the browser on the WebRTC, and on the other hand calls up the SIP operator via SIP.
The HTML code of the page with which the calls are executed is quite compact:
</pre> <pre>&lt;!DOCTYPE html&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;html&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;head&lt;/span&gt; &lt;span class="hljs-attr"&gt;lang&lt;/span&gt;=&lt;span class="hljs-string"&gt;"en"&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;script&lt;/span&gt; &lt;span class="hljs-attr"&gt;type&lt;/span&gt;=&lt;span class="hljs-string"&gt;"text/javascript"&lt;/span&gt; &lt;span class="hljs-attr"&gt;src&lt;/span&gt;=&lt;span class="hljs-string"&gt;"flashphoner.js"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;script&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;script&lt;/span&gt; &lt;span class="hljs-attr"&gt;language&lt;/span&gt;=&lt;span class="hljs-string"&gt;"javascript"&lt;/span&gt; &lt;span class="hljs-attr"&gt;src&lt;/span&gt;=&lt;span class="hljs-string"&gt;"click-to-call.js"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;script&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;head&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;body&lt;/span&gt; &lt;span class="hljs-attr"&gt;onload&lt;/span&gt;=&lt;span class="hljs-string"&gt;"init_page()"&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;button&lt;/span&gt; &lt;span class="hljs-attr"&gt;id&lt;/span&gt;=&lt;span class="hljs-string"&gt;"callButton"&lt;/span&gt; &lt;span class="hljs-attr"&gt;type&lt;/span&gt;=&lt;span class="hljs-string"&gt;"button"&lt;/span&gt; &lt;span class="hljs-attr"&gt;onclick&lt;/span&gt;=&lt;span class="hljs-string"&gt;"connectAndCall('+1647*******')"&lt;/span&gt;&gt;&lt;/span&gt;Call&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;button&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;button&lt;/span&gt; &lt;span class="hljs-attr"&gt;id&lt;/span&gt;=&lt;span class="hljs-string"&gt;"hangupButton"&lt;/span&gt; &lt;span class="hljs-attr"&gt;type&lt;/span&gt;=&lt;span class="hljs-string"&gt;"button"&lt;/span&gt; &lt;span class="hljs-attr"&gt;onclick&lt;/span&gt;=&lt;span class="hljs-string"&gt;"hangup()"&lt;/span&gt;&gt;&lt;/span&gt;Hangup&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;button&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;div&lt;/span&gt; &lt;span class="hljs-attr"&gt;id&lt;/span&gt;=&lt;span class="hljs-string"&gt;"remoteMedia"&lt;/span&gt; &lt;span class="hljs-attr"&gt;style&lt;/span&gt;=&lt;span class="hljs-string"&gt;"visibility: hidden"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;div&lt;/span&gt; &lt;span class="hljs-attr"&gt;id&lt;/span&gt;=&lt;span class="hljs-string"&gt;"localMedia"&lt;/span&gt; &lt;span class="hljs-attr"&gt;style&lt;/span&gt;=&lt;span class="hljs-string"&gt;"visibility: hidden"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;div&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;&lt;span class="hljs-name"&gt;p&lt;/span&gt; &lt;span class="hljs-attr"&gt;id&lt;/span&gt;=&lt;span class="hljs-string"&gt;"status"&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;p&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;body&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class="hljs-tag"&gt;&lt;/&lt;span class="hljs-name"&gt;html&lt;/span&gt;&gt;
The page contains the Call button for the call and the Hangup button to reset it. There is a field in which the status is displayed.
Div – elements of localMedia and remoteMedia are used to embed into the page the objects responsible for receiving and sending audio.
The script flashphoner.js is available for download in the Web SDK assembly.
The click-to-call.js script for the call
The click-to-call.js script. Using this script, you connect to the server and make a call.
&lt;/pre&gt; &lt;pre&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; localMedia; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; remoteMedia; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; outCall; &lt;span class="hljs-comment"&gt;//init API&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;init_page&lt;/span&gt;() &lt;/span&gt;{ Flashphoner.init(); localMedia = &lt;span class="hljs-built_in"&gt;document&lt;/span&gt;.getElementById(&lt;span class="hljs-string"&gt;"localMedia"&lt;/span&gt;); remoteMedia = &lt;span class="hljs-built_in"&gt;document&lt;/span&gt;.getElementById(&lt;span class="hljs-string"&gt;"remoteMedia"&lt;/span&gt;); } &lt;span class="hljs-comment"&gt;//call&lt;/span&gt; &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;connectAndCall&lt;/span&gt;(&lt;span class="hljs-params"&gt;number&lt;/span&gt;) &lt;/span&gt;{ &lt;span class="hljs-comment"&gt;//if already connected, make a call&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (Flashphoner.getSessions().length &amp;gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt;) { call(number, Flashphoner.getSessions()[&lt;span class="hljs-number"&gt;0&lt;/span&gt;]); } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; { &lt;span class="hljs-comment"&gt;//SIP credentials&lt;/span&gt; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; sipOptions = { login: &lt;span class="hljs-string"&gt;"10001"&lt;/span&gt;, authenticationName: &lt;span class="hljs-string"&gt;"10001"&lt;/span&gt;, password: &lt;span class="hljs-string"&gt;"12345"&lt;/span&gt;, domain: &lt;span class="hljs-string"&gt;"192.168.1.3"&lt;/span&gt;, outboundProxy: &lt;span class="hljs-string"&gt;"192.168.1.3"&lt;/span&gt;, port: &lt;span class="hljs-string"&gt;"5060"&lt;/span&gt;, registerRequired: &lt;span class="hljs-literal"&gt;false&lt;/span&gt; }; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; connectionOptions = { urlServer: &lt;span class="hljs-string"&gt;"wss://wcs5-eu.flashphoner.com:8443"&lt;/span&gt;, sipOptions: sipOptions }; &lt;span class="hljs-comment"&gt;//create new connection to WCS server&lt;/span&gt; Flashphoner.createSession(connectionOptions).on(Flashphoner.constants.SESSION_STATUS.ESTABLISHED, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; (&lt;span class="hljs-params"&gt;session&lt;/span&gt;) &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Session"&lt;/span&gt;, Flashphoner.constants.SESSION_STATUS.ESTABLISHED); &lt;span class="hljs-comment"&gt;//session connected, place call&lt;/span&gt; call(number, session); }).on(Flashphoner.constants.SESSION_STATUS.DISCONNECTED, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Session"&lt;/span&gt;, Flashphoner.constants.SESSION_STATUS.DISCONNECTED); onHangup(); }).on(Flashphoner.constants.SESSION_STATUS.FAILED, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Session"&lt;/span&gt;, Flashphoner.constants.SESSION_STATUS.FAILED); onHangup(); }); } } &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;call&lt;/span&gt;(&lt;span class="hljs-params"&gt;number, session&lt;/span&gt;) &lt;/span&gt;{ &lt;span class="hljs-comment"&gt;//disable call button&lt;/span&gt; &lt;span class="hljs-built_in"&gt;document&lt;/span&gt;.getElementById(&lt;span class="hljs-string"&gt;"callButton"&lt;/span&gt;).disabled=&lt;span class="hljs-literal"&gt;true&lt;/span&gt;; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; constraints = { audio: &lt;span class="hljs-literal"&gt;true&lt;/span&gt;, video: &lt;span class="hljs-literal"&gt;false&lt;/span&gt; }; &lt;span class="hljs-comment"&gt;//prepare outgoing call&lt;/span&gt; outCall = session.createCall({ callee: number, visibleName: &lt;span class="hljs-string"&gt;"Click To Call"&lt;/span&gt;, localVideoDisplay: localMedia, remoteVideoDisplay: remoteMedia, constraints: constraints, receiveAudio: &lt;span class="hljs-literal"&gt;true&lt;/span&gt;, receiveVideo: &lt;span class="hljs-literal"&gt;false&lt;/span&gt; }).on(Flashphoner.constants.CALL_STATUS.RING, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Call"&lt;/span&gt;, Flashphoner.constants.CALL_STATUS.RING); }).on(Flashphoner.constants.CALL_STATUS.ESTABLISHED, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Call"&lt;/span&gt;, Flashphoner.constants.CALL_STATUS.ESTABLISHED); }).on(Flashphoner.constants.CALL_STATUS.FINISH, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Call"&lt;/span&gt;, Flashphoner.constants.CALL_STATUS.FINISH); onHangup(); }).on(Flashphoner.constants.CALL_STATUS.FAILED, &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; () &lt;/span&gt;{ setStatus(&lt;span class="hljs-string"&gt;"Call"&lt;/span&gt;, Flashphoner.constants.CALL_STATUS.FAILED); onHangup(); }); outCall.call(); } &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;hangup&lt;/span&gt;() &lt;/span&gt;{ &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (outCall) { outCall.hangup(); } } &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;onHangup&lt;/span&gt;()&lt;/span&gt;{ &lt;span class="hljs-comment"&gt;//will be invoked on hangup&lt;/span&gt; } &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title"&gt;setStatus&lt;/span&gt;(&lt;span class="hljs-params"&gt;callOrSession,status&lt;/span&gt;)&lt;/span&gt;{ &lt;span class="hljs-built_in"&gt;document&lt;/span&gt;.getElementById(&lt;span class="hljs-string"&gt;"status"&lt;/span&gt;).innerHTML= callOrSession +&lt;span class="hljs-string"&gt;" "&lt;/span&gt;+status;&lt;/pre&gt; &lt;pre&gt;
There are four main functions in this script:
- Initialization
- Establishing a connection to the server
- Call
- Reset call
Initialization
Here we just call the init () function and thus initialize the API.
&lt;/pre&gt; &lt;pre&gt;&lt;span class="hljs-type"&gt;Flashphoner&lt;/span&gt;.&lt;span class="hljs-keyword"&gt;init&lt;/span&gt;();&lt;/pre&gt; &lt;pre&gt;
Establishing a connection to the server
Here we connect to the server via a secure WebSockets protocol and send the SIP account data, so that the server, in turn, can connect to the SIP operator (provider).
&lt;/pre&gt; &lt;pre&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; sipOptions = { login: &lt;span class="hljs-string"&gt;"10001"&lt;/span&gt;, authenticationName: &lt;span class="hljs-string"&gt;"10001"&lt;/span&gt;, password: &lt;span class="hljs-string"&gt;"12345"&lt;/span&gt;, domain: &lt;span class="hljs-string"&gt;"192.168.1.3"&lt;/span&gt;, outboundProxy: &lt;span class="hljs-string"&gt;"192.168.1.3"&lt;/span&gt;, port: &lt;span class="hljs-string"&gt;"5060"&lt;/span&gt;, registerRequired: &lt;span class="hljs-literal"&gt;false&lt;/span&gt; }; &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; connectionOptions = { urlServer: &lt;span class="hljs-string"&gt;"wss://wcs5-eu.flashphoner.com:8443"&lt;/span&gt;, sipOptions: sipOptions }; Flashphoner.createSession(connectionOptions);&lt;/pre&gt; &lt;pre&gt;
Call
Create a call and call the call () method for the call. When creating a call, the parameter callee is transmitted – this is the number of the subscriber we call, for example, the mobile number.
&lt;/pre&gt; &lt;pre&gt;outCall = session.createCall({ callee: number, visibleName: &lt;span class="hljs-string"&gt;"Click To Call"&lt;/span&gt;, localVideoDisplay: localMedia, remoteVideoDisplay: remoteMedia, constraints: constraints, receiveAudio: &lt;span class="hljs-literal"&gt;true&lt;/span&gt;, receiveVideo: &lt;span class="hljs-literal"&gt;false&lt;/span&gt; }); outCall.call();&lt;/pre&gt; &lt;pre&gt;
Reset call
In order to reset the call, we call the API method hangup ()
&lt;/pre&gt; &lt;pre&gt;outCall.hangup();&lt;/pre&gt; &lt;pre&gt;
Testing the call page
For testing in Google Chrome, you need to fill in the pages click-to-call.html and click-to-call.js on a web server with https support. Chrome only gives access to the microphone from secure pages (https). The script code is available for download via this link.
The scripts are connected to the test server was: //wcs5-eu.flashphoner.com: 8443. For testing with your own server, you need to install the WCS5 server on a Linux system. You can download WCS5 server from this link.
Open the click-to-call.html page in the Google Chrome browser and click the Call button. The server accepts the call and sends the ESTABLISHED status. The mobile subscriber picks up the phone and the result is a call between the browser and the mobile phone.
Thus, we analyzed how the SIP-accounts provided by IP-telephony providers look, tested the calls with softphones, created two files for the call from the browser click-to-call.html and click-to-call.js and tested these scripts with a call From Google Chrome browser to mobile phone, through SIP-operator. The call from the browser goes to Web Call Server 5 and on to the SIP operator with a landing on the mobile phone.
References
SIP – session setup protocol, which is used in VoIP telephony
Web Call Server – WebRTC-SIP gateway for browsers with SIP telephony.
Web SDK – JavaScript API server for developing browser phones. The assembly contains the script flashphoner.js.
Source – click-to-call.html and click-to-call.js scripts