Несколько строк JS кода для звонка из браузера на мобильный телефон

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

    В этой статье мы расскажем как сделать кнопку для звонка со страницы сайта на мобильный или городской номер телефона.

    Схема звонка


    Прежде всего, потребуется SIP-аккаунт оператора VoIP телефонии. Оператор «приземляет» звонок, идущий по интернету (VoIP) и дозванивается до мобильного или городского телефона.

    Наши задачи в этом случае следующие:

    1. Послать SIP INVITE в сторону SIP оператора.
    2. Принять SIP 200 OK от оператора.
    3. Принять звук от оператора.
    4. Отправить звук из браузера оператору.

    Браузер не работает по честным SIP / TCP и SIP / UDP протоколам, поэтому в нашей схеме будет сервер-посредник, который будет говорить с оператором на классическом SIP / UDP.


    SIP аккаунт


    Чтобы получить SIP аккаунт, можно зарегистрироваться, например в сервисе VoIP телефонии sipnet или у любого другого провайдера, который предоставляет линии для звонков на мобильные телефоны.

    SIP аккаунт состоит из шести следующих параметров:

    1. Логин
      Например alice123
    2. Имя для аутентификации (может отличаться от логина или совпадать).
      Например alice123
    3. Пароль
      Например ******
    4. Домен
      Например sipnet.ru
    5. Прокси (может отличаться от домена или совпадать)
      Например sipnet.ru
    6. Порт (обычно 5060)
      Например 5060

    Упрощенный SIP аккаунт


    Часто бывает, что domain совпадает с outbound proxy и login совпадает с authentication name, и порт используется стандартный 5060. В этом случае SIP оператор может предоставить SIP аккаунт в упрощенном виде:
    Login alice123
    Password ***
    Domain sipnet.ru

    Это уже чем-то похоже на привычный доступ к веб ресурсу. После того, как доступ получен можно протестировать его с любым из софтфонов, например Xlite, Linphone, Ekiga, и т.д.

    Тест с десктопным софтфоном


    При использовании софтфона Bria 4, настройки подключения по SIP выглядят так:


    Обычно провайдер предоставляет номера, на которые можно сделать SIP-звонок. Некоторые провайдеры дают бесплатные минуты при минимальном пополнении счета.

    Осталось позвонить с софтфона и убедиться в том, что SIP звонки действительно проходят на нормальные телефоны. Например, позвоним в Минкомсвязь по телефону +74957718000.


    Если звонки нормально работают через десктопный софтфон, можно переходить к браузерному телефону и к браузерным звонкам.

    HTML страница для звонка


    Браузерные звонки будут идти по технологии WebRTC через сервер Web Call Server 5, который с одной стороны работает с браузером по WebRTC, а с другой созванивается с SIP оператором по SIP.


    Код HTML-страницы, с которой выполняются звонки довольно компактный и занимает 14 строк:

    <!DOCTYPE html>
    <html>
    <head lang="en">
       <script type="text/javascript" src="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>

    На странице размещена кнопка Call для звонка и кнопка Hangup для его сброса. Есть поле, в котором отображается статус.

    Div — элементы localMedia и remoteMedia используются для внедрения в страницу объектов, отвечающих за получение и отправку звука.

    Скрипт flashphoner.js доступен для скачивания в сборке Web SDK.

    Скрипт click-to-call.js для звонка


    Скрипт click-to-call.js содержит 97 строк. С помощью этого скрипта устанавливается коннект к серверу и делается звонок.

    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;
    }

    В данном скрипте можно отметить четыре основных функции:

    • Инициализация
    • Установка соединения с сервером
    • Звонок
    • Сброс звонка

    Инициализация


    Здесь мы просто вызываем функцию init() и тем самым инициализируем API.

    Flashphoner.init();

    Установка соединения с сервером


    Здесь мы подключаемся к серверу по защищенному протоколу websockets и передаем данные SIP аккаунта, для того, чтобы сервер, в свою очередь смог подключиться к SIP оператору (провайдеру).

     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);

    Звонок


    Создаем звонок и вызываем метод call() для вызова. При создании звонка передается параметр callee — это номер абонента, которому звоним, например номер мобильного.

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

    Сброс звонка


    Для того, чтобы сбросить звонок, вызываем метод API hangup()

    outCall.hangup();

    Тестируем страницу звонка


    Для тестирования в Google Chrome нужно залить страницы click-to-call.html и click-to-call.js на web-сервер с поддержкой https. Chrome дает доступ к микрофону только с защищенных страниц (https). Код скриптов доступен для скачивания по этой ссылке.

    Скрипты соединяются с тестовым сервером wss://wcs5-eu.flashphoner.com:8443. Для тестирования с собственным сервером, вам нужно установить сервер WCS5 на Linux систему. Скачать сервер WCS5 можно по этой ссылке.

    Открываем страницу click-to-call.html в браузере Google Chrome и нажимаем кнопку Call. Сервер принимает вызов и присылает статус ESTABLISHED. Мобильный абонент берет трубку и в результате устанавливается звонок между браузером и мобильным телефоном.


    Таким образом, мы разобрали, как выглядят SIP-аккаунты, предоставляемые провайдерами IP-телефонии, протестировали звонки с софтфонами, создали два файла для звонка из браузера click-to-call.html и click-to-call.js и протестировали эти скрипты звонком из браузера Google Chrome на мобильный телефон, через SIP-оператора. Звонок из браузера идет на Web Call Server 5 и далее на SIP оператора с приземлением на мобильный телефон.

    Ссылки


    SIP — протокол установки сессии, который используется в VoIP телефонии
    Web Call Server — WebRTC-SIP шлюз для работы браузеров с SIP телефонией.
    Web SDK — JavaScript API сервера для разработки браузерных телефонов. Сборка содержит скрипт flashphoner.js.
    Source — скрипты click-to-call.html и click-to-call.js
    • –3
    • 6.8k
    • 3
    Flashphoner
    16.69
    Компания
    Share post

    Comments 3

      +13
      Читаю заголовок. Становится жутко интересно, как же можно всего несколькими строками js звонить из браузера.

      Лезу под кат. Читаю, что для этого понадабится:

      1. sip-аккаунт.
      2. Сервер-посредник.
      3. Скрипт flashphoner.js, который весит почти мегабайт
      4. Скрипт click-to-call.js на 97 строк.

      Вам не кажется, что фраза «Несколько строк JS кода» в заголовке слегка вводит в заблуждение?
        –6
        function several_lines_of_js_code_to_make_a_call(){
        
            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).on(Flashphoner.constants.SESSION_STATUS.ESTABLISHED, function (session) {
                session.createCall({callee: number}).call();
            })
        }
        

        Вот так вполне похоже на несколько строк JS — кода. Полные листинги с комментариями приведены для законченности примера. Чтобы не только позвонить можно было, но и сбросить звонок, и статусы показать.

        Что касается зависимостей, без них не обойтись. Да. Мало чего можно сделать на JavaScript без зависимостей. Обычно подразумевается, что есть какое-то API, библиотека.

        Что касается заголовка, это всего лишь заголовок. Если бы заголовок был «Как дрессировать котят», то да, пожалуй вводил бы кого-то в заблуждение.
          +3

          Я думаю, что ко многим виджетам звонка можно написать короткую обертку для методов, и потом назвать "несколько строк кода"

      Only users with full accounts can post comments. Log in, please.