Click to Call with PHP-SIP
posted by Chris on 2009-10-07 22:29:27
In this tutorial we will show how to implement "click to call" functionality in a web page using PHP-SIP class, free opensips.org SIP registrar service and Twinkle softphone.
The same principle can be used with any RFC compliant SIP service or your own PBX such as Asterisk or OpenSIPs.
Prerequisites
In order to accomplish scenario shown in a diagram below, you will need the following:
- Basic knowledge of SIP protocol.
- Free SIP account from opensips.org - this will be our SIP Proxy and
sip:user1@sipas shown in the diagram below. Alternatively any SIP compliant SIP service or your own SIP Proxy can be used instead. - PHP (version >= 5) enabled web server.
- Twinkle softphone (on Ubuntu linux can be installed with the following command:
apt-get install twinkle) or any other SIP softphone or normal phone. However we provide detailed instructions for Twinkle only.
SIP Flow diagram

- User submits a form with calling (sip:user1@sip) and called (sip:user2@sip) parties SIP URIs.
- Web Server sends INVITE to sip:user1@sip.
- Once INVITE is accepted by user1, web server immediately sends REFER with sip:user2@sip in "Refer-to" header.
- Web Server terminates "call" by sending BYE to user1.
- As instructed in REFER request sent by a web server, user1 sends INVITE to sip:user2@sip.
1. Create Click to Call web page
Go to your web server root directory and create c2c.php file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><title>PHP-SIP Click to Call</title></head>
<body>
<?php if (isset($_POST['from']) && isset($_POST['to'])) : ?>
<?php require_once('php-sip/PhpSIP.class.php') ?>
<?php $from = $_POST['from']; $to = $_POST['to'] ?>
Trying call from <?php echo $from ?> to <?php echo $to ?> ...<br />
<?php flush() ?>
<pre>
<?php
try{
$api = new PhpSIP();
// if you get "Failed to obtain IP address to bind. Please set bind address manualy."
// error, use the line below instead
// $api = new PhpSIP('you_server_IP_address');
$api->setDebug(true);
// if your SIP service doesn't accept anonymous inbound calls uncomment two lines below
//$api->setUsername('auth_username');
//$api->setPassword('auth_password');
$api->addHeader('Subject: click2call');
$api->setMethod('INVITE');
$api->setFrom('sip:c2c@'.$api->getSrcIp());
$api->setUri($from);
$res = $api->send();
if ($res == 200)
{
$api->setMethod('REFER');
$api->addHeader('Refer-to: '.$to);
$api->addHeader('Referred-By: sip:c2c@'.$api->getSrcIp());
$api->send();
$api->setMethod('BYE');
$api->send();
$api->listen('NOTIFY');
$api->reply(481,'Call Leg/Transaction Does Not Exist');
}
if ($res == 'No final response in 5 seconds.')
{
$api->setMethod('CANCEL');
$res = $api->send();
}
echo $res;
} catch (Exception $e) {
echo "Opps... Caught exception:";
echo $e;
}
?>
</pre>
<hr />
<a href="<?php echo $_SERVER['PHP_SELF']; ?>">Back</a>
<?php else : ?>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
<fieldset>
From: <input type="text" name="from" size="25" value="" />
To: <input type="text" name="to" size="25" value="sip:enum-test@sip.nemox.net" />
<input type="submit" value="Call" />
</fieldset>
</form>
<?php endif ?>
</body>
</html>
Next we need to download PHP-SIP class from code.google.com/p/php-sip/downloads/list and extract it into your web server root directory, so it looks as shown below:
/web-root/c2c.php /web-root/php-sip/PhpSIP.class.php /web-root/php-sip/PhpSIP.Exception.php /web-root/php-sip/README
Now open the web browser and navigate to http://you_web_server/c2c.php which should show a form similar to:

2. Register SIP Phone
For the purpose of this tutorial we assume our test account at opensips.org is jsmith and softphone used for our test will be Twinkle. However you can use any other SIP proxy and software or normal SIP phone.
Once your SIP account at opensips.org is set up, start Twinkle, select Edit => User profile... and enter your SIP account details as shown below:

- enter your username into fields
(1) (2) and (5) - enter
opensips.orginto fields(3) and (4) - enter your password into field
(6) - select
SIP servertab(7)and enteropensips.orginto field(8) - select
SIP protocoltab(9)and deselectAsk user permission for transfercheck box
...finally click OK button and if everything went well your Twinkle will display:
opensips.org, registration succeeded (expires = 3600 secods)
3. Testing
Open a web browser and navigate to our "Click to Call" page. Enter sip:your_username@opensips.org into From field, leave default sip:enum-test@sip.nemox.net in To field and click Call button. Twinkle should indicate incoming call...

...click Answer and your phone will be automatically connected to sip:enum-test@sip.nemox.net which is a public ENUM test service provided by nemox.net group.
Congratulations! Your Click to Call web page works!
Summary
The above illustrates the simplest possible scenario. In a real life applications you may want to use fancy Ajax instead of standard HTML form. Fetch From and/or To SIP URIs from database or do number of even more exciting things.
Comments
Leave Your Comment
All submitted reviews/comments become the licensed property of Level 7 Systems Ltd.

Subscribe with in your feed reader
How can I place an outbound call and then connect it with my extension?
I try to do as following:
from: sip:91112233@my-asterisk.ip.com
to: sip:1000@my-asterisk.ip.com
where 91112233 is number 111-2233 called via 9-trunk
and 1000 - my extension.
but it does not call anywhere...
can somebody tell me if my task is reachable with phpsip ?
thanx for help!
Hi Dmitry, thanks for your interest in PHP-SIP project.
Yes, your scenario is possible. You will need to download the latest version (>= 0.3.1) of php-sip and make modifications to c2c.php as shown below:
Uncomment:
$api->setUsername('1000');
$api->setPassword('auth_password');
and replace auth_password as defined in your sip.conf for user 1000.
Replace:
$api->setFrom('sip:c2c@'.$api->getSrcIp());
with:
$api->setFrom('sip:1000@asterisk_ip');
Replace:
$api->addHeader('Referred-By: sip:c2c@'.$api->getSrcIp());
with:
$api->addHeader('Referred-By: sip:1000@asterisk_ip');
Add:
usleep(500000);
before:
$api->setMethod('REFER');
Thanks for useful information. I am making outbound call thru c2c.php. For that i m putting
From : 19782232254@192.168.1.10
To: 1000@192.168.1.10
I did below changes in c2c.php:
$api->setUsername('1000');
$api->setPassword('1234');
$api->setFrom('sip:1000@192.168.1.10');
$api->addHeader('Referred-By: sip:1000@192.168.1.10');
After doing this when i m clicking on call it is giving me below error.
=============================================
Trying call from 19782232254@192.168.1.10 to sip:1000@192.168.1.10 ...
Fatal error: Call to undefined function sys_get_temp_dir() in /var/www/html/php-sip/PhpSIP.class.php on line 247
==============================================
What could be the issue...
Thanks
Hi Mehul,
It seems to me you are running PHP version 4.x, and it is missing sys_get_temp_dir() function.
You will need to use PHP version >= 5.2 with PhpSIP.
Hi,
This is a great script. I have a small problem that maybe you could help me with. I am trying to use the class to make an outgoing call from a webpage. I have done all the things above you stated to do. No matter what configuration or port options I set, I always get No Final Response in 5 seconds.
My sip listens on port 5090
My client softphone listens on port 5060
Call from:
sip:[mynum]*[ext]@[sip.provider.com]
Call to:
sip:[phonenum]@[sip.provider.com]
I have put in my user and password in the c2c.php file.
Any help would be great, Thanks
Hi Kathy, I will try to help, but can you please let me know the following:
1. What OS do you use? Window/Linux
2. What version of PHP do you use?
3. What is your network layout? Is the web server hosting c2c.php on
the same network as your softphone? Is it a private LAN or public
internet?
Could you please email the above info to chris [at-sign-here] level7systems [dot] co [dot] uk
hello Level7,
is php-sip can be used to as user management (create, modify, credits etc..) ? also is it possible to use pstn phone number format ?
sorry for my newbie question, I'm fairly new in SIP world
Thanks
Hi Franck,
No, unfortunately you can't manage user accounts with php-sip. You would need SIP registrar/proxy server and database back end for this.
I can recommend openSIPs software: http://opensips.org
hello level7
I use ubuntu 9.01 and i have some problem withe the installation and i have this message that i don't resolve please help me to understand :
Trying call from sip:kloulamoez@opensips.org to sip:enum-test@sip.nemox.net ...
Opps... Caught exception:exception 'Exception' with message 'Invalid argument' in /opt/lampp/htdocs/php-sip/PhpSIP.class.php:730
Stack trace:
#0 /opt/lampp/htdocs/php-sip/PhpSIP.class.php(664): PhpSIP->sendData('INVITE sip:klou...')
#1 /opt/lampp/htdocs/c2c.php(39): PhpSIP->send()
#2 {main
Hi,
Try replacing:
$api = new PhpSIP();
with
$api = new PhpSIP('you_server_IP_address');
it worked very well... mmm... i tried this one many time without any success, until i tried a different PC... i'm still wondering why it didn't work in my laptop but my desktop PC. Important: i tried using the X-Lite and it worked as well as in a linux based PC using Twinkle. Thanks bro...
I think this is just what I was looking for!
I'm just reading through the class now, any chance that I could read a hint status i.e. BLF button to show presence on the web page?
Hi Peter. I am afraid you will not be able read BLF status with PHP-SIP. What you need is to SUBSCRIBE to phone BLF events sent via NOTIFY packets. To do this you will need a SIP server listening all the time in the background. This is currently not supported by PHP-SIP.
How can I make external calls betwwen two external phone numbers?
I try to use my SIP server, but:
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to bind my.sip.net:23 Invalid argument' in /www/php-sip/PhpSIP.class.php:1311
Stack trace:
#0 /www/php-sip/PhpSIP.class.php(256): PhpSIP->createSocket()
#1 /www/php-sip/c2c.php(23): PhpSIP->__construct('my.sip.net')
#2 {main}
Hi Tigran, try using your server IP address, instead of domain name. For example:
$api = new PhpSIP('10.10.10.12');
instead of:
$api = new PhpSIP('my.sip.net');
I can modify this script to call 2 phone numbers? (not 2 sip users)
@RobiGo - If your SIP server is a PSTN gateway at the same time, you can call phone numbers with this script.
my php is 5
I try with other sip, and then with opensips.org and I get the message below.
Whats the problem?
Trying call from sip:-----@opensips.org to sip:enum-test@sip.nemox.net ...
Opps... Caught exception:exception 'PhpSIPException' with message 'socket_create() function missing.' in /home/www/----/php-sip/PhpSIP.class.php:228
Stack trace:
#0 /home/www/----/c2c.php(23): PhpSIP->__construct()
#1 {main}
@Ricardo - Your PHP does not support "sockets".
On Linux platform you need to
compile PHP with "--enable-sockets"
On Windows add
"extension=php_sockets.dll" to your php.ini
I again, I am trying in another host now, I get this message?
Trying call from sip:----@opensips.org to sip:enum-test@sip.nemox.net ...
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to send data. Operation not permitted' in /home/injernet/www/c2c/php-sip/PhpSIP.class.php:737
Stack trace:
#0 /home/injernet/www/c2c/php-sip/PhpSIP.class.php(671): PhpSIP->sendData('INVITE sip:---...')
#1 /home/injernet/www/c2c/c2c.php(39): PhpSIP->send()
#2 {main}
Hi:-)
I like, if my server call me on events. I have more voip numbers and access in my sip provider.
Try the c2c.php (PHP5, linux), and output:
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to bind sip.provider.com:24 Cannot assign requested address' in /var/www/php-sip/PhpSIP.class.php:1327
Stack trace:
#0 /var/www/php-sip/PhpSIP.class.php(272): PhpSIP->createSocket()
#1 /var/www/php-sip/c2c.php(23): PhpSIP->__construct('sip.provider.com')
#2 {main}
What is the problem? :-)
@Balfi - you need to use:
$api = new PhpSIP('you_server_IP_address');
for example: $api = new PhpSIP('10.10.2.2');
and NOT:
$api = new PhpSIP('sip.provider.com');
Hi I'm getting the following error:
Trying call from sip:095xxxxxxx@freephonie.net to sip:enum-test@sip.nemox.net ...
--> INVITE sip:095xxxxxxx@freephonie.net SIP/2.0
No final response in fr_timer seconds.
any idea why ?
Thanks.
Hi
I am getting the following error:
Trying call from sip:966xxxx@sip.inphonex.com to sip:enum-test@sip.nemox.net ...
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to bind 207.45.189.184:6 Permission denied' in /home/novtel/public_html/test/php-sip/PhpSIP.class.php:1311
Stack trace:
Can you help in this regard?
Tanks
#0 /home/novtel10/public_html/test/php-sip/PhpSIP.class.php(256): PhpSIP->createSocket()
#1 /home/novtel10/public_html/test/c2c.php(23): PhpSIP->__construct()
#2 {main}
My Problem:
Trying call from sip:10001@95.156.208.50 to sip:10002@95.156.208.50 ...
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to open lock file /tmp/phpSIP.lock' in /var/www/web1/html/kastius/sip/php-sip/PhpSIP.class.php:303
Stack trace:
#0 /var/www/web1/html/kastius/sip/php-sip/PhpSIP.class.php(1295): PhpSIP->getPort()
#1 /var/www/web1/html/kastius/sip/php-sip/PhpSIP.class.php(256): PhpSIP->createSocket()
#2 /var/www/web1/html/kastius/sip/c2c.php(23): PhpSIP->__construct('95.156.208.50')
#3 {main}
@Christoph - looks like your PHP process is not allowed to write to /tmp directory.
You can change location of "phpSIP.lock" file in PhpSIP.class.php - line 58.
Line 58: private $lock_file;
What write i here?
@Christoph - a path to any directory that is writeable by your web server + "phpSIP.lock". So for example if your web server can write to "/var/www/rw" directory, your Line 58 will look like:
private $lock_file = "/var/www/rw/phpSIP.lock";
Hi Chris,
This script works like magic. Great work!! Thank you. I managed to call my mobile from my asterisk box using this script.
Could we also send/add an automated message to the receiver (after the system calls the given number)? Basically auto-dialing a number and playing a pre-recorded message to the receiver.
Is it possible?
Thanking you in advance.
@Richa - Thanks for your interest in our project.
Unfortunately it is not possible to send any Audio streams with PHP-SIP at the moment.
Only SIP signaling is implemented - no RTP (Real Time Protocol) stack is present at this time.
We are planning to add Audio (RTP) support (possibly with an external library) in the future.
Thank you for your quick reply.
I appreciate the thought of your script supporting audio as well.
As a workaround, I was thinking whether I could do it by setting "exten" parameters in the extensions.conf file. So internally, when an extension is called it can trigger the voice message. Any ideas?
It would be good to see your script working with some few tweaking in the config files for RTP as well.
SIP server :10.6.3.29 with php 5.2.10
Register 1001 and 1002 with X-lite on two XP system .
After I copy the source code from this page.
It shows like below and stop.
Trying call from sip:1001@10.6.3.29 to sip:1002@10.6.3.29 ...
The two X-lite system seems like nothing happened.
Is there something wrong ?
Hello, great library, it is working very well for me, only a couple of questions, how can in make it rings more than once? because it rings once, if you dont answer it can be ringing more but when you answer it doesnt connect you to the other party, you are only able to connect to other person in the first ringing, 2nd question, once it is ringing res:180 or call connected res:200 , how can i hang up the call from the page, i created a button with the following code
api->setmethod('BYE');
api->send();
but it doesn work, thanks in advance for your help
@omar - to make it ring longer you will need to edit "Final Response Timer", around line 53:
private $fr_timer = 10;
Default is 10 seconds only.
To terminate unanswered call you can do:
api->setmethod('CANCEL');
api->send();
Terminating already established calls with BYE is more complicated. The reason for that is $api object exists only until call is set up (or terminated with CANCEL). You will need to use database (or other persistent storage) to save Call-Id of call you want to terminate, and use this in your BYE request.
Hi thanks for your answer, before you answered me i was testing some changes in the script, at the begining i was using
$api = new PhpSIP();
$api->setUsername('user');
$api->setPassword('password');
only and it was working very well, after that i commented these 2 lines
$api->setUsername('user');
$api->setPassword('password');
and then this error shows up
Opps... Caught exception:exception 'PhpSIPException' with message 'Failed to bind xxx.xxx.xxx.xxx:38 Permission denied' in /var/www/html/php-sip/PhpSIP.class.php:1311
Stack trace:
#0 /var/www/html/php-sip/PhpSIP.class.php(256): PhpSIP->createSocket()
#1 /var/www/html/c2cold.php(21): PhpSIP->__construct()
i changed $api = new PhpSIP('myip');and all changs you can guess and it is not working anymore , im running this page using https because it is working in the same box as asterisk
any idea?
Hi there,
I´m glad to find PHP-SIP but can´t get along yet.
Maybe someone wants to help and give me a hand.
I just want to check the status of several PBX´s in a PHP script like this:
---
$url_array[0] = "10.11.12.13";
...
foreach $url_array as $i => $url
{
try
{
$api = new PhpSIP();
$api->setMethod('OPTIONS');
$api->setFrom('sip:'.$i.'@'.$url);
$api->setUri('sip:'.$i.'@'.$url);
$res = $api->send();
echo "res1: $res\n";
}
catch (Exception $e)
{
echo $e->getMessage()."\n";
}
}
---
It works once, and then ERROR: ...failed to bind ,[...], socket used twice (german: Normalerweise darf jede Socketadresse (Protokoll, Netzwerkadresse oder Anschluss) nur jeweils einmal verwendet werden.)
Any idea?
I`m trying to call from registered sip to phone number ( no sip ).. I didn`t saw any comment about this ..
it is possible ? how ?
i`m using XP pro with WAMP (php 5+)
thank u in advance
@Cosmin, you can't call any PSTN number directly using SIP protocol (with this script or any other way). You will need SIP => PSTN gateway which will translate SIP to old PSTN protocol.
This library is really great and useful. But it would be better if we can execute any extension with playback options etc.. For ex. before bridging two calls, the first side hears a voice file and then after the answer of other side, it plays another voice file. after end of the voices, the calls are bridged...
Any idea of a PHP class that can implement RTP? From here to a predictive dialer is not that long way and a simple predictive dialer is what is currently missing to all of us. Any thoughts, please?
@ondercsn and @gReg - it would be extremely difficult to implement RTP stack in a pure PHP. This class aims at providing SIP signalling only, leaving media (RTP streams) to a software which is much better suited for the job (eg. Asterisk).
We have SIP a hosted SIP server. I use Blink on my Mac and it works fine. Adding:
$api->setProxy('proxy_ip');
Get's me close, but I think I need to login, I get the following error:
Trying call from sip:tnelson@starpoint.com to sip:enum-test@sip.nemox.net ...
--> INVITE sip:tnelson@starpoint.com SIP/2.0
<-- SIP/2.0 100 Trying
<-- SIP/2.0 487 LR2 - User not registered on this client
--> ACK sip:tnelson@starpoint.com SIP/2.0
487
Thanks for any help in advance.
In the manner of a predictive dialer that sends an audio file it should not be difficult even by means of pure PHP.
Also the opposite should be all right, meaning a list of numbers sending an audio file to one number, that will make happy many.
As it is your class is very basic, at most it can be used for a scanner or a basic brute force script. I don't want to minimize your work, but as it is it's not more than a skype call me button. Serious stuff is ahead and the two options above can be implemented and I will probably do it.
Anyway, I didn't meant it without external support. (Your favorite SIP SDK here) is a good example of SDK and it does a lot. The UI and related are javascript, but the core is indeed in some serious program language.