Warning: make sure that you have read through the Plivo Web SDK Quick-Start Guide and the Make Outgoing Calls Tutorial before you start this tutorial.


Receive Incoming Calls

After building a web app that makes outgoing calls, it's time to enable your app to receive incoming calls. This tutorial will show you how to receive calls from mobile phones, landlines, or SIP-enabled devices (e.g., softphones) directly in your browser-based app.

Assuming that your web server is located at www.example.com. We will name this app receive_incoming. To receive incoming calls, the receiver needs to be logged into the browser app via the SIP Endpoint credentials. When a calls comes in, the following will happen:

  1. The caller will dial the phone number associated with the web application. The call can be dialed from a mobile phone, landline, or SIP-enabled device (e.g., softphones).
  2. Upon receiveing a call, the web app will notify the receiver and the receiver can either choose to "answer" or "reject" the call.
  3. If a call is answered, the receiver can choose to either "mute" or "unmute" during the call. If the call is rejected, then the call will be hung up immediately.
  4. During the call, the caller or receiver can send DTMF digits to perform pre-programmed behaviors (e.g., call forwarding).
  5. The caller or receiver can hang up the call at anytime.


Below are the steps and the code snippet to set up a route on your webserver and associate a Plivo phone number to your app to receive phone calls.

Warning: make sure that you have read through the Plivo Web SDK Quick-Start Guide and have all of the Pre-requisites before you start this tutorial.

Step 1: Create a Plivo Application

First, we must configure the Plivo application and link it to the direct-dial app that you set up during the Web SDK Quick Start Guide. If you're using the default "Direct Dial" app that's provided in your Plivo account, or have completed the Make Outgoing Calls tutorial, you may skip this step and go directly to "Create a SIP Endpoint". If you've set up a route on your own web server, then follow the steps below to configure your Plivo application:

Note: you may skip this step if you've already gone through these steps in the Make Outgoing Calls tutorial.
  1. Create a Plivo Application by visiting the Application Page in your Plivo GUI and click on New Application or by using Plivo's Application API.
  2. Give your application a name.
  3. Enter your server URL with your caller ID appended (e.g., http://www.example.com/direct-dial/?DialMusic=real&CLID=14152223333) in the Answer URL and Hangup URL fields.
  4. Set both methods as POST.
  5. Click on Create to save your application.
  6. Advanced Hack: you can also create, edit, and delete Plivo Applications through the Application API.
Plivo Create Direct Dial Application

Step 2: Assign a Plivo number to your app

  1. Navigate to the Numbers page and select the phone number you want to use for this app.
  2. Note: If you don’t yet have a Plivo number, go to the Buy Numbers page to purchase a Plivo phone number or read the Search and Buy Phone Numbers Guide for complete details.
  3. Select the name of your app from the Plivo App dropdown list.
  4. Click on Update to save.
Assign Phone Number to Receive Incoming Call App

Step 3: Create a SIP Endpoint

  1. Create a Plivo SIP Endpoint by visiting the Endpoint Page in your Plivo GUI and click on New Endpoint or by using Plivo's Endpoint API.
  2. Choose a username, password, and alias for your SIP endpoint. You will use the username and password to login to the webapp that you will build in the following steps.
  3. Link this SIP Endpoint to your server application by selecting it in the Application drop down. Select Direct Dial if you're using the default Plivo application. Or select the name of the application you set up in the first step (i.e., Create an Application section) of this tutorial.
Plivo Create SIP Endpoint

Step 4: Understanding the Code

If you've already completed the Make Outgoing Calls tutorial, a lot of the code provided below will look familiar. However, we made some adjustments in order to create user interface logic that makes sense for receiving calls. For example, when a call comes in, the receiver can choose whether to "answer" or "reject" the call. Before we start building, let's first understand what the code is doing. We will provide the entire code in the Build the App section below.

To simplify things, here are the lines of code responsible for all the behaviors of the incoming call:

Code Snippet Function
Plivo.conn.answer(); Answer a call
Plivo.conn.reject(); Reject a call
Plivo.conn.mute(); Mute a call
Plivo.conn.unmute(); Unmute a call
var digit = "1";
Plivo.conn.send_dtmf(digit);
Send DTMF digits during a call

Step 5: Build the App

Select the language you would like to use for your app.


Download the asset files
To build the web app, we first need all the static assets that will be supporting your web app (e.g., CSS, JavaScript, images, etc).
1. Create a "static" folder in the root directory of your app.
2. Download assets.zip and save it in the "static" folder that you just created.
3. Serve up the asset files either directly through the web server or by using a content delivery network (CDN).

Create the calling app in Python
The code below will help to set up a route on your webserver.
1. Copy the code below into a text file and save it as receive_incoming.py.
2. Replace Your SIP Endpoint Username and Your SIP Endpoint Password with your SIP Endpoint credentials created in the previous step.
3. Next, we will render the HTML file of this app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import plivo, plivoxml
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/receive_incoming', methods=['GET','POST'])
def receive_incoming():

    username = "Your SIP Endpoint Username"
    password = "Your SIP Endpoint Password"
    # Render the html file
    return render_template('receive_incoming.html', username=username, password=password)

if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True)


Render the HTML file
Assuming that your web server is located at www.example.com, the following HTML file will be rendered when we send an HTTP request to www.example.com/receive_incoming.
1. Create a folder called templates in the same path. For example, if receive_incoming.py was saved in the folder /documents/websdkapp/ then the new folder would be /documents/websdkapp/templates.
2. Copy the code below into a text file, name it as receive_incoming.htmland save it in your new templates folder.
3. Make an HTTP request to www.example.com/receive_incoming. This will instruct the receive_incoming.py app to render the receive_incoming.html file.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Plivo Webphone Demo</title>
        <meta name="description" content="">
        <script language="javascript" content-type="text/javascript" src="static/jquery.js"></script>
        <script type="text/javascript" src="http://s3.amazonaws.com/plivosdk/web/plivo.min.js"></script>
        <link href="static/bootstrap-combined.min.css" rel="stylesheet">
        <style type="text/css">
            body {
                padding-top: 20px;
                padding-bottom: 40px;
            }
            .container-narrow {
                margin: 0 auto;
                max-width: 700px;
            }
            .container-narrow > hr {
                margin: 30px 0;
            }
            #btn-container a{
                margin-top:7px;
                min-width:7px;
            }
        </style>
        <script type="text/javascript">
            // Answer incoming calls
            function answer() {
                console.log("answering")
                $('#status_txt').text('Answering....');
                Plivo.conn.answer();
                $('#status_txt').text('Answered the Call');
                $('#btn-container').show();
                $('#incoming_callbox').hide();
            }
            // Reject incoming calls
            function reject() {
                $('#status_txt').text('Rejected the Call');
                Plivo.conn.reject();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            // Incoming calls
            function onIncomingCall(account_name, extraHeaders) {
                console.log("onIncomingCall:"+account_name);
                console.log("extraHeaders=");
                for (var key in extraHeaders) {
                    console.log("key="+key+".val="+extraHeaders[key]);
                }
                $('#status_txt').text('Incoming Call');
                $('#incoming_callbox').show('slow');
            }
            // Login with SIP Endpoint
            function login() {
                // SIP Endpoint username and password
                var username = '{{username}}';
                var password = '{{password}}';
                // Login
                Plivo.conn.login(username, password);
            }
            function  onMediaPermission (result) {
                if (result) {
                    console.log("get media permission");
                } else {
                    alert("you don't allow media permission, you will can't make a call until you allow it");
                }
            }
            function onCallTerminated() {
                console.log("onCallTerminated");
            }
            function webrtcNotSupportedAlert() {
                $('#txtStatus').text("");
                alert("Your browser doesn't support WebRTC. You need Chrome 25 to use this demo");
            }
            function onLogin() {
                $('#status_txt').text('Logged in');
            }
            function onLoginFailed() {
                $('#status_txt').text("Login Failed");
            }
            function onReady() {
                console.log("onReady...");
                login();
            }
            function mute() {
                Plivo.conn.mute();
                $('#linkUnmute').show('slow');
                $('#linkMute').hide('slow');
            }
            function unmute() {
                Plivo.conn.unmute();
                $('#linkUnmute').hide('slow');
                $('#linkMute').show('slow');
            }
            function hangup() {
                $('#status_txt').text('Hanging up..');
                Plivo.conn.hangup();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            function dtmf(digit) {
                console.log("send dtmf="+digit);
                Plivo.conn.send_dtmf(digit);
            }
            // Initialization 
            $(document).ready(function() {
                Plivo.onWebrtcNotSupported = webrtcNotSupportedAlert;
                Plivo.onReady = onReady;
                Plivo.onLogin = onLogin;
                Plivo.onLoginFailed = onLoginFailed;
                Plivo.onCallTerminated = onCallTerminated;
                Plivo.onIncomingCall = onIncomingCall;
                Plivo.onMediaPermission = onMediaPermission;
                Plivo.init();
            });
        </script>
    </head>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <img class="muted" src="static/logo.png">
            </div>
            <div class="row-fluid marketing">
                <div class="span12">
                    <h4>Plivo WebSDK Webphone Demo</h4>
                    <span class="label" id="status_txt">Login</span><br/><br/>
                    </form>
                        <div id="incoming_callbox" style="display: none;" class="call">
                            <a href="#" class="btn main-btn btn-success" onclick="answer()">Answer</a>
                            <a href="#" class="btn main-btn btn-danger" onclick="reject()">Reject</a>
                        </div>
                        <div id="btn-container" style="display: none">
                            <a href="#" id="hangup_call" class="btn main-btn btn-danger" onclick="hangup();">Hangup</a>
                            <a href="#" id="linkMute" class="badge badge-warning" onclick="mute();">Mute</a>
                            <a href="#" id="linkUnmute" class="badge badge-warning" onclick="unmute();" style="display: none">Unmute</a><br/>
                            <a class="btn btn-info" href="#" onclick="dtmf('1');">1</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('2');">2</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('3');">3</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('4');">4</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('5');">5</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('6');">6</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('7');">7</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('8');">8</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('9');">9</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('*');">*</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('0');">0</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('#');"> #</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


Download the asset files
To build the web app, we first need all the static assets that will be supporting your web app (e.g., CSS, JavaScript, images, etc).
1. Create a "public" folder in the root directory of your app.
2. Download assets.zip and save it in the "public" folder that you just created.
3. Serve up the asset files either directly through the web server or by using a content delivery network (CDN).

Create the calling app in Ruby
The code below will help to set up a route on your webserver.
1. Copy the code below into a text file and save it as receive_incoming.rb.
2. Replace Your SIP Endpoint Username and Your SIP Endpoint Password with your SIP Endpoint credentials created in the previous step.
3. Next, we will render the HTML file of this app.

1
2
3
4
5
6
7
8
9
require 'sinatra'
require 'rubygems'

get '/receive_incoming' do
    username = "Your SIP Endpoint Username"
    password = "Your SIP Endpoint Password"
    # Render the erb file
    erb :receive_incoming, :locals => {:username => username, :password => password}
end


Render the HTML file
Assuming that your web server is located at www.example.com, the following Embedded Ruby (i.e., .erb) file will be rendered when we send an HTTP request to www.example.com/receive_incoming.
1. Create a folder called views in the same path. For example, if receive_incoming.rb was saved in the folder /documents/websdkapp/ then the new folder would be /documents/websdkapp/views.
2. Copy the code below into a text file, name it as receive_incoming.erb and save it in your new views folder.
3. Make an HTTP request to www.example.com/receive_incoming. This will instruct the receive_incoming.rb app to render the receive_incoming.erb file.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Plivo Webphone Demo</title>
        <meta name="description" content="">
        <script language="javascript" content-type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="http://s3.amazonaws.com/plivosdk/web/plivo.min.js"></script>
        <link href="bootstrap-combined.min.css" rel="stylesheet">
        <style type="text/css">
            body {
                padding-top: 20px;
                padding-bottom: 40px;
            }
            .container-narrow {
                margin: 0 auto;
                max-width: 700px;
            }
            .container-narrow > hr {
                margin: 30px 0;
            }
            #btn-container a{
                margin-top:7px;
                min-width:7px;
            }
        </style>
        <script type="text/javascript">
            // Answer incoming calls
            function answer() {
                console.log("answering")
                $('#status_txt').text('Answering....');
                Plivo.conn.answer();
                $('#status_txt').text('Answered the Call');
                $('#btn-container').show();
                $('#incoming_callbox').hide();
            }
            // Reject incoming calls
            function reject() {
                $('#status_txt').text('Rejected the Call');
                Plivo.conn.reject();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            // Incoming calls
            function onIncomingCall(account_name, extraHeaders) {
                console.log("onIncomingCall:"+account_name);
                console.log("extraHeaders=");
                for (var key in extraHeaders) {
                    console.log("key="+key+".val="+extraHeaders[key]);
                }
                $('#status_txt').text('Incoming Call');
                $('#incoming_callbox').show('slow');
            }
            // Login with SIP Endpoint
            function login() {
                // SIP Endpoint username and password
                var username = "<%= username %>";
                var password = "<%= password %>";
                // Login
                Plivo.conn.login(username, password);
            }
            function  onMediaPermission (result) {
                if (result) {
                    console.log("get media permission");
                } else {
                    alert("you don't allow media permission, you will can't make a call until you allow it");
                }
            }
            function webrtcNotSupportedAlert() {
                $('#txtStatus').text("");
                alert("Your browser doesn't support WebRTC. You need Chrome 25 to use this demo");
            }
            function onCallTerminated() {
                console.log("onCallTerminated");
            }
            function onLogin() {
                $('#status_txt').text('Logged in');
            }
            function onLoginFailed() {
                $('#status_txt').text("Login Failed");
            }
            function onReady() {
                console.log("onReady...");
                login();
            }
            function mute() {
                Plivo.conn.mute();
                $('#linkUnmute').show('slow');
                $('#linkMute').hide('slow');
            }
            function unmute() {
                Plivo.conn.unmute();
                $('#linkUnmute').hide('slow');
                $('#linkMute').show('slow');
            }
            function hangup() {
                $('#status_txt').text('Hanging up..');
                Plivo.conn.hangup();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            function dtmf(digit) {
                console.log("send dtmf="+digit);
                Plivo.conn.send_dtmf(digit);
            }
            // Initialization 
            $(document).ready(function() {
                Plivo.onWebrtcNotSupported = webrtcNotSupportedAlert;
                Plivo.onReady = onReady;
                Plivo.onLogin = onLogin;
                Plivo.onLoginFailed = onLoginFailed;
                Plivo.onCallTerminated = onCallTerminated;
                Plivo.onIncomingCall = onIncomingCall;
                Plivo.onMediaPermission = onMediaPermission;
                Plivo.init();
            });
        </script>
    </head>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <img class="muted" src="logo.png">
            </div>
            <div class="row-fluid marketing">
                <div class="span12">
                    <h4>Plivo WebSDK Webphone Demo</h4>
                    <span class="label" id="status_txt">Login</span><br/><br/>
                    </form>
                        <div id="incoming_callbox" style="display: none;" class="call">
                            <a href="#" class="btn main-btn btn-success" onclick="answer()">Answer</a>
                            <a href="#" class="btn main-btn btn-danger" onclick="reject()">Reject</a>
                        </div>
                        <div id="btn-container" style="display: none">
                            <a href="#" id="hangup_call" class="btn main-btn btn-danger" onclick="hangup();">Hangup</a>
                            <a href="#" id="linkMute" class="badge badge-warning" onclick="mute();">Mute</a>
                            <a href="#" id="linkUnmute" class="badge badge-warning" onclick="unmute();" style="display: none">Unmute</a><br/>
                            <a class="btn btn-info" href="#" onclick="dtmf('2');">2</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('3');">3</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('4');">4</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('5');">5</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('6');">6</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('7');">7</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('8');">8</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('9');">9</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('*');">*</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('0');">0</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('#');"> #</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


Download the asset files
To build the web app, we first need all the static assets that will be supporting your web app (e.g., CSS, JavaScript, images, etc).
1. Create a "static" folder in the root directory of your app. 2. Download assets.zip and save it in the "static" folder that you just created.
3. Serve up the asset files either directly through the web server or by using a content delivery network (CDN).

Create the calling app in PHP
The code below will help to set up a route on your webserver.
1. Copy the code below into a text file and save it as receive_incoming.php.
2. Replace Your SIP Endpoint Username and Your SIP Endpoint Password with your SIP Endpoint credentials created in the previous step.
3. Assuming that your web server is located at www.example.com, make an HTTP request to www.example.com/receive_incoming.php to invoke the route.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<?php
$username = "Your SIP Endpoint Username";
$password = "Your SIP Endpoint Password";
?>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Plivo Webphone Demo</title>
        <meta name="description" content="">
        <script language="javascript" content-type="text/javascript" src="static/jquery.js"></script>
        <script type="text/javascript" src="http://s3.amazonaws.com/plivosdk/web/plivo.min.js"></script>
        <link href="static/bootstrap-combined.min.css" rel="stylesheet">
        <style type="text/css">
            body {
                padding-top: 20px;
                padding-bottom: 40px;
            }
            .container-narrow {
                margin: 0 auto;
                max-width: 700px;
            }
            .container-narrow > hr {
                margin: 30px 0;
            }
            #btn-container a{
                margin-top:7px;
                min-width:7px;
            }
        </style>
        <script type="text/javascript">
            // Answer incoming calls
            function answer() {
                console.log("answering")
                $('#status_txt').text('Answering....');
                Plivo.conn.answer();
                $('#status_txt').text('Answered the Call');
                $('#btn-container').show();
                $('#incoming_callbox').hide();
            }
            // Reject incoming calls
            function reject() {
                $('#status_txt').text('Rejected the Call');
                Plivo.conn.reject();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            // Incoming calls
            function onIncomingCall(account_name, extraHeaders) {
                console.log("onIncomingCall:"+account_name);
                console.log("extraHeaders=");
                for (var key in extraHeaders) {
                    console.log("key="+key+".val="+extraHeaders[key]);
                }
                $('#status_txt').text('Incoming Call');
                $('#incoming_callbox').show('slow');
            }
            // Login with SIP Endpoint
            function login() {
                // SIP Endpoint username and password
                var username = "<?php echo $username; ?>";
                var password = "<?php echo $password; ?>";
                // Login
                Plivo.conn.login(username, password);
            }
            function  onMediaPermission (result) {
                if (result) {
                    console.log("get media permission");
                } else {
                    alert("you don't allow media permission, you will can't make a call until you allow it");
                }
            }
            function onCallTerminated() {
                console.log("onCallTerminated");
            }
            function webrtcNotSupportedAlert() {
                $('#txtStatus').text("");
                alert("Your browser doesn't support WebRTC. You need Chrome 25 to use this demo");
            }
            function onLogin() {
                $('#status_txt').text('Logged in');
            }
            function onLoginFailed() {
                $('#status_txt').text("Login Failed");
            }
            function onReady() {
                console.log("onReady...");
                login();
            }
            function mute() {
                Plivo.conn.mute();
                $('#linkUnmute').show('slow');
                $('#linkMute').hide('slow');
            }
            function unmute() {
                Plivo.conn.unmute();
                $('#linkUnmute').hide('slow');
                $('#linkMute').show('slow');
            }
            function hangup() {
                $('#status_txt').text('Hanging up..');
                Plivo.conn.hangup();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            function dtmf(digit) {
                console.log("send dtmf="+digit);
                Plivo.conn.send_dtmf(digit);
            }
            // Initialization 
            $(document).ready(function() {
                Plivo.onWebrtcNotSupported = webrtcNotSupportedAlert;
                Plivo.onReady = onReady;
                Plivo.onLogin = onLogin;
                Plivo.onLoginFailed = onLoginFailed;
                Plivo.onCallTerminated = onCallTerminated;
                Plivo.onIncomingCall = onIncomingCall;
                Plivo.onMediaPermission = onMediaPermission;
                Plivo.init();
            });
        </script>
    </head>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <img class="muted" src="static/logo.png">
            </div>
            <div class="row-fluid marketing">
                <div class="span12">
                    <h4>Plivo WebSDK Webphone Demo</h4>
                    <span class="label" id="status_txt">Login</span><br/><br/>
                    </form>
                        <div id="incoming_callbox" style="display: none;" class="call">
                            <a href="#" class="btn main-btn btn-success" onclick="answer()">Answer</a>
                            <a href="#" class="btn main-btn btn-danger" onclick="reject()">Reject</a>
                        </div>
                        <div id="btn-container" style="display: none">
                            <a href="#" id="hangup_call" class="btn main-btn btn-danger" onclick="hangup();">Hangup</a>
                            <a href="#" id="linkMute" class="badge badge-warning" onclick="mute();">Mute</a>
                            <a href="#" id="linkUnmute" class="badge badge-warning" onclick="unmute();" style="display: none">Unmute</a><br/>
                            <a class="btn btn-info" href="#" onclick="dtmf('2');">2</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('3');">3</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('4');">4</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('5');">5</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('6');">6</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('7');">7</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('8');">8</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('9');">9</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('*');">*</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('0');">0</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('#');"> #</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


Download the asset files
To build the web app, we first need all the static assets that will be supporting your web app (e.g., CSS, JavaScript, images, etc).
1. Create a "static" folder in the root directory of your app.
2. Download assets.zip and save it in the "static" folder that you just created.
3. Serve up the asset files either directly through the web server or by using a content delivery network (CDN).

Create the calling app in .NET
The code below will help to set up a route on your webserver.
1. Copy the code below into a text file and save it as receive_incoming.cshtml.
2. Replace Your SIP Endpoint Username and Your SIP Endpoint Password with your SIP Endpoint credentials created in the previous step.
3. Assuming that your web server is located at www.example.com, make an HTTP request to www.example.com/receive_incoming to invoke the route.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
@{
    var username = "Your SIP Endpoint username"; 
    var password = "Your SIP Endpoint password";
}

<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Plivo Webphone Demo</title>
        <meta name="description" content="">
        <script language="javascript" content-type="text/javascript" src="static/jquery.js"></script>
        <script type="text/javascript" src="http://s3.amazonaws.com/plivosdk/web/plivo.min.js"></script>
        <link href="static/bootstrap-combined.min.css" rel="stylesheet">
        <style type="text/css">
            body {
                padding-top: 20px;
                padding-bottom: 40px;
            }
            .container-narrow {
                margin: 0 auto;
                max-width: 700px;
            }
            .container-narrow > hr {
                margin: 30px 0;
            }
            #btn-container a{
                margin-top:7px;
                min-width:7px;
            }
        </style>
        <script type="text/javascript">
            // Answer incoming calls
            function answer() {
                console.log("answering")
                $('#status_txt').text('Answering....');
                Plivo.conn.answer();
                $('#status_txt').text('Answered the Call');
                $('#btn-container').show();
                $('#incoming_callbox').hide();
            }
            // Reject incoming calls
            function reject() {
                $('#status_txt').text('Rejected the Call');
                Plivo.conn.reject();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            // Incoming calls
            function onIncomingCall(account_name, extraHeaders) {
                console.log("onIncomingCall:"+account_name);
                console.log("extraHeaders=");
                for (var key in extraHeaders) {
                    console.log("key="+key+".val="+extraHeaders[key]);
                }
                $('#status_txt').text('Incoming Call');
                $('#incoming_callbox').show('slow');
            }
            // Login with SIP Endpoint
            function login() {
                // Login
                Plivo.conn.login("@username", "@password");
            }
            function  onMediaPermission (result) {
                if (result) {
                    console.log("get media permission");
                } else {
                    alert("you don't allow media permission, you will can't make a call until you allow it");
                }
            }
            function onCallTerminated() {
                console.log("onCallTerminated");
            }
            function webrtcNotSupportedAlert() {
                $('#txtStatus').text("");
                alert("Your browser doesn't support WebRTC. You need Chrome 25 to use this demo");
            }
            function onLogin() {
                $('#status_txt').text('Logged in');
            }
            function onLoginFailed() {
                $('#status_txt').text("Login Failed");
            }
            function onReady() {
                console.log("onReady...");
                login();
            }
            function mute() {
                Plivo.conn.mute();
                $('#linkUnmute').show('slow');
                $('#linkMute').hide('slow');
            }
            function unmute() {
                Plivo.conn.unmute();
                $('#linkUnmute').hide('slow');
                $('#linkMute').show('slow');
            }
            function hangup() {
                $('#status_txt').text('Hanging up..');
                Plivo.conn.hangup();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            function dtmf(digit) {
                console.log("send dtmf="+digit);
                Plivo.conn.send_dtmf(digit);
            }
            // Initialization 
            $(document).ready(function() {
                Plivo.onWebrtcNotSupported = webrtcNotSupportedAlert;
                Plivo.onReady = onReady;
                Plivo.onLogin = onLogin;
                Plivo.onLoginFailed = onLoginFailed;
                Plivo.onCallTerminated = onCallTerminated;
                Plivo.onIncomingCall = onIncomingCall;
                Plivo.onMediaPermission = onMediaPermission;
                Plivo.init();
            });
        </script>
    </head>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <img class="muted" src="static/logo.png">
            </div>
            <div class="row-fluid marketing">
                <div class="span12">
                    <h4>Plivo WebSDK Webphone Demo</h4>
                    <span class="label" id="status_txt">Login</span><br/><br/>
                    </form>
                        <div id="incoming_callbox" style="display: none;" class="call">
                            <a href="#" class="btn main-btn btn-success" onclick="answer()">Answer</a>
                            <a href="#" class="btn main-btn btn-danger" onclick="reject()">Reject</a>
                        </div>
                        <div id="btn-container" style="display: none">
                            <a href="#" id="hangup_call" class="btn main-btn btn-danger" onclick="hangup();">Hangup</a>
                            <a href="#" id="linkMute" class="badge badge-warning" onclick="mute();">Mute</a>
                            <a href="#" id="linkUnmute" class="badge badge-warning" onclick="unmute();" style="display: none">Unmute</a><br/>
                            <a class="btn btn-info" href="#" onclick="dtmf('2');">2</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('3');">3</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('4');">4</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('5');">5</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('6');">6</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('7');">7</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('8');">8</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('9');">9</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('*');">*</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('0');">0</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('#');"> #</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>


Download the asset files
To build the web app, we first need all the static assets that will be supporting your web app (e.g., CSS, JavaScript, images, etc).
1. Create a "WebContent" folder in the main directory of your app (i.e., "src/main/WebContent"). 2. Download assets.zip and save it in the "static" folder that you just created.
3. Serve up the asset files either directly through the web server or by using a content delivery network (CDN).

Create the calling app in Java
The code below will help to set up a route on your webserver.
1. Copy the code below into a text file and save it as receive_incoming.java.
2. Replace Your SIP Endpoint Username and Your SIP Endpoint Password with your SIP Endpoint credentials created in the previous step.
3. Next, we will render the HTML file of this app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package web_phne;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import java.io.IOException;

@WebServlet("/receive_incoming")
public class receive_incoming extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        String username = "Your SIP Endpoint username";
        String password = "Your SIP Endpoint Password";

        // Forward the username and password information to a JSP view
        response.setContentType("text/html");
        request.setAttribute("username", username);
        request.setAttribute("password", password);
        RequestDispatcher view = request.getRequestDispatcher("receive_incoming.jsp");
        view.forward(request, response);
    }
}


Render the HTML file
Assuming that your web server is located at www.example.com, the following Java Server Page (i.e., .jsp) file will be rendered when we send an HTTP request to www.example.com/receive_incoming.
1. Create a folder called WebContent in the same path. For example, if receive_incoming.java was saved in the folder /documents/websdkapp/ then the new folder would be /documents/websdkapp/WebContent.
2. Copy the code below into a text file, name it as receive_incoming.jsp and save it in your new WebContent folder.
3. Make an HTTP request to www.example.com/receive_incoming. This will instruct the receive_incoming.java app to render the receive_incoming.jsp file.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Plivo Webphone Demo</title>
        <meta name="description" content="">
        <script language="javascript" content-type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="http://s3.amazonaws.com/plivosdk/web/plivo.min.js"></script>
        <link href="bootstrap-combined.min.css" rel="stylesheet">
        <style type="text/css">
            body {
                padding-top: 20px;
                padding-bottom: 40px;
            }
            .container-narrow {
                margin: 0 auto;
                max-width: 700px;
            }
            .container-narrow > hr {
                margin: 30px 0;
            }
            #btn-container a{
                margin-top:7px;
                min-width:7px;
            }
        </style>
        <script type="text/javascript">
            // Answer incoming calls
            function answer() {
                console.log("answering")
                $('#status_txt').text('Answering....');
                Plivo.conn.answer();
                $('#status_txt').text('Answered the Call');
                $('#btn-container').show();
                $('#incoming_callbox').hide();
            }
            // Reject incoming calls
            function reject() {
                $('#status_txt').text('Rejected the Call');
                Plivo.conn.reject();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            // Incoming calls
            function onIncomingCall(account_name, extraHeaders) {
                console.log("onIncomingCall:"+account_name);
                console.log("extraHeaders=");
                for (var key in extraHeaders) {
                    console.log("key="+key+".val="+extraHeaders[key]);
                }
                $('#status_txt').text('Incoming Call');
                $('#incoming_callbox').show('slow');
            }
            // Login with SIP Endpoint
            function login() {
                // SIP Endpoint username and password
                var username = '<%= request.getAttribute("username") %>';
                var password = '<%= request.getAttribute("password") %>';
                // Login
                Plivo.conn.login(username, password);
            }
            function  onMediaPermission (result) {
                if (result) {
                    console.log("get media permission");
                } else {
                    alert("you don't allow media permission, you will can't make a call until you allow it");
                }
            }
            function webrtcNotSupportedAlert() {
                $('#txtStatus').text("");
                alert("Your browser doesn't support WebRTC. You need Chrome 25 to use this demo");
            }
            function onCallTerminated() {
                console.log("onCallTerminated");
            }
            function onLogin() {
                $('#status_txt').text('Logged in');
            }
            function onLoginFailed() {
                $('#status_txt').text("Login Failed");
            }
            function onReady() {
                console.log("onReady...");
                login();
            }
            function mute() {
                Plivo.conn.mute();
                $('#linkUnmute').show('slow');
                $('#linkMute').hide('slow');
            }
            function unmute() {
                Plivo.conn.unmute();
                $('#linkUnmute').hide('slow');
                $('#linkMute').show('slow');
            }
            function hangup() {
                $('#status_txt').text('Hanging up..');
                Plivo.conn.hangup();
                $('#btn-container').hide();
                $('#incoming_callbox').hide();
                $('#status_txt').text('Ready');
            }
            function dtmf(digit) {
                console.log("send dtmf="+digit);
                Plivo.conn.send_dtmf(digit);
            }
            // Initialization 
            $(document).ready(function() {
                Plivo.onWebrtcNotSupported = webrtcNotSupportedAlert;
                Plivo.onReady = onReady;
                Plivo.onLogin = onLogin;
                Plivo.onLoginFailed = onLoginFailed;
                Plivo.onCallTerminated = onCallTerminated;
                Plivo.onIncomingCall = onIncomingCall;
                Plivo.onMediaPermission = onMediaPermission;
                Plivo.init();
            });
        </script>
    </head>
    <body>
        <div class="container-narrow">
            <div class="masthead">
                <img class="muted" src="logo.png">
            </div>
            <div class="row-fluid marketing">
                <div class="span12">
                    <h4>Plivo WebSDK Webphone Demo</h4>
                    <span class="label" id="status_txt">Login</span><br/><br/>
                    </form>
                        <div id="incoming_callbox" style="display: none;" class="call">
                            <a href="#" class="btn main-btn btn-success" onclick="answer()">Answer</a>
                            <a href="#" class="btn main-btn btn-danger" onclick="reject()">Reject</a>
                        </div>
                        <div id="btn-container" style="display: none">
                            <a href="#" id="hangup_call" class="btn main-btn btn-danger" onclick="hangup();">Hangup</a>
                            <a href="#" id="linkMute" class="badge badge-warning" onclick="mute();">Mute</a>
                            <a href="#" id="linkUnmute" class="badge badge-warning" onclick="unmute();" style="display: none">Unmute</a><br/>
                            <a class="btn btn-info" href="#" onclick="dtmf('2');">2</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('3');">3</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('4');">4</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('5');">5</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('6');">6</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('7');">7</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('8');">8</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('9');">9</a>
                        <br/>
                        <a class="btn btn-info" href="#" onclick="dtmf('*');">*</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('0');">0</a>
                        <a class="btn btn-info" href="#" onclick="dtmf('#');"> #</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>

Step 6: Test it out

  • To receive calls with your browser app, load your app URL www.example.com/receive_incoming into a browser (use www.example.com/receive_incoming.php if you built your app using PHP).
  • Enable your computer microphone for the app by clicking "Allow" when prompted by your browser.
  • Plivo Allow Microphone to Receive Incoming
  • Call the phone number or SIP endpoint that you assigned to your application.
  • When there is an incoming call, click "Answer" to answer the call or "Reject" to reject the call.
  • Plivo Receive Incoming Call
  • Once the call is answered, you may "Mute", "Unmute", or "Hangup" the call. During the call, the caller or receiver may also input DTMF numbers to initiate other pre-programmed actions (e.g., call forwarding, send to voice mail, initiate a survey, etc.).
  • Plivo Receive Incoming Call

Next Steps

Learn how to Create Dynamic SIP Endpoints.

  1. Web SDK Quick Start
  2. Make a Call With a Browser to a Phone Number
  3. Make a Call With a Browser to a SIP Endpoint
  4. Hangup the Call
  5. Manually Input Destination Phone Numbers
  6. Pre-program Destination Phone Numbers (Click-to-call)
  7. Modify the Login Interface
  8. Create Dynamic SIP Endpoints