HOW TO BIND USSD TRANSCEIVER USING PHP



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








0















I've been trying to implement USSD using SMPP protocol before I shared my problem, I will talk about what've been able to achieve so far:



  1. I have been able to successfully connect with the Telco via VPN

  2. I have been able to initiate SMPP Connection and returned an appropriate response of Response_Code '0' which is 'OK'

  3. Binding of Receiver, Transceiver & Transmitter with command_id '0x00000001', '0x00000009', '0x00000002' respectively, and they all return expected Response_Code which is 'OK'.

But the following are my problems:



  1. I want to be able to bind, and when the user dials the USSD ShortCode, they should be able to see at least 'Hello World'

  2. Unable to implement 'submit_sm' after successful 'transceiver' bind

  3. My current code implementation is using SMPP to send SMS, of which is running fine, but will like to have another method e.g. $tx->runUSSD() instead of $tx->sendSMS()

Below are my codes, and I believe with this code I should be able to do it, but have been so freaking stress with research and research, I've read and have read a lot, but can't get it working:



transciever.php



<?php
print "<pre>";
require_once "./smpp.php";
$tx=new SMPP('Ip Address',Port);
$tx->debug=true;
$tx->addr_npi=1;
print "open status: ".$tx->state."n";
$tx->bindTransceiver("system_id","password");
$tx->sms_source_addr_npi=0;
$tx->sms_source_addr_ton=5;
$tx->sms_dest_addr_ton=1;
$tx->sms_dest_addr_npi=1;

$status = $tx->sendSMS("Hello","08023828392","Hello World");
$tx->close();
unset($tx);
echo $status;
print "</pre>";
?>


smpp.php



<?php

class SMPP
var $debug = true;
//SMPP bind parameters
//var $system_type="WWW";
var $interface_version=0x34;
var $addr_ton=0;
var $addr_npi=0;
var $address_range="";
//ESME transmitter parameters
var $sms_service_type="";
var $sms_source_addr_ton=0;
var $sms_source_addr_npi=0;
var $sms_dest_addr_ton=0;
var $sms_dest_addr_npi=0;
var $sms_esm_class=0;
var $sms_protocol_id=0;
var $sms_priority_flag=0;
var $sms_schedule_delivery_time="";
var $sms_validity_period="";
var $sms_registered_delivery_flag=0;
var $sms_replace_if_present_flag=0;
var $sms_data_coding=0;
var $sms_sm_default_msg_id=0;

/**
* Constructs the smpp class
* @param $host - SMSC host name or host IP
* @param $port - SMSC port
*/
function SMPP($host, $port=5016)
//internal parameters
$this->sequence_number=1;
$this->debug=false;
$this->pdu_queue=array();
$this->host=$host;
$this->port=$port;
$this->state="closed";
//open the socket
$this->socket=fsockopen($this->host, $this->port, $errno, $errstr, 30);
if($this->socket)$this->state="open";


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transciever...nn";

$status=$this->_bind($login, $pass, 0x00000009);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_trx";
return ($status===0);


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindReceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding receiver...nn";

$status=$this->_bind($login, $pass, 0x00000001);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_rx";
return ($status===0);

/**
* Binds the transmitter. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransmitter($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transmitter...nn";

$status=$this->_bind($login, $pass, 0x00000002);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_tx";
return ($status===0);

/**
* Closes the session on the SMSC server.
*/
function close()
if($this->state=="closed")return;
if($this->debug)
echo "Unbinding...nn";

$status=$this->sendCommand(0x00000006,"");
if($this->debug)
echo "Unbind status : $statusnn";

fclose($this->socket);
$this->state="closed";


/**
* Read USSD response from SMSC.
* @return
*/
function readResponse ()
if($this->state!="bind_trx")return false;

//set command id
$command_id = 0x00000005;

/**
* Read one SMS from SMSC. Can be executed only after bindReceiver() call.
* This method bloks. Method returns on socket timeout or enquire_link signal from SMSC.
* @return sms associative array or false when reading failed or no more sms.
*/
function readSMS()
if($this->state!="bind_rx")return false;
//stream_set_timeout($this->socket, 10);
$command_id=0x00000005;
//check the queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return parseSMS($pdu);


//read pdu
do
if($this->debug)
echo "read sms...nn";

$pdu=$this->readPDU();
//check for enquire link command
if($pdu['id']==0x00000015)
$this->sendPDU(0x80000015, "", $pdu['sn']);
return false;

array_push($this->pdu_queue, $pdu);
while($pdu && $pdu['id']!=$command_id);
if($pdu)
array_pop($this->pdu_queue);
return $this->parseSMS($pdu);

return false;

/**
* Read one SMS from SMSC. Can be executed only after bindTransmitter() call.
* @return true on succesfull send, false if error encountered
*/
function sendSMS($from, $to, $message)

////////////////private functions///////////////

/**
* @private function
* Binds the socket and opens the session on SMSC
* @param $login - ESME system_id
* @param $port - ESME password
* @return bind status or false on error
*/
function _bind($login, $pass, $command_id)
//make PDU
$pdu = pack(
'a'.(strlen($login)+1).
'a'.(strlen($pass)+1).
'a'.(strlen($this->system_type)+1).
'CCCa'.(strlen($this->address_range)+1),
$login, $pass, $this->system_type,
$this->interface_version, $this->addr_ton,
$this->addr_npi, $this->address_range);
$status=$this->sendCommand($command_id,$pdu);
return $status;


/**
* @private function
* Parse deliver PDU from SMSC.
* @param $pdu - deliver PDU from SMSC.
* @return parsed PDU as array.
*/
function parseSMS($pdu)
//check command id
if($pdu['id']!=0x00000005)return false;
//unpack PDU
$ar=unpack("C*",$pdu['body']);
$sms=array('service_type'=>$this->getString($ar,6),
'source_addr_ton'=>array_shift($ar),
'source_addr_npi'=>array_shift($ar),
'source_addr'=>$this->getString($ar,21),
'dest_addr_ton'=>array_shift($ar),
'dest_addr_npi'=>array_shift($ar),
'destination_addr'=>$this->getString($ar,21),
'esm_class'=>array_shift($ar),
'protocol_id'=>array_shift($ar),
'priority_flag'=>array_shift($ar),
'schedule_delivery_time'=>array_shift($ar),
'validity_period'=>array_shift($ar),
'registered_delivery'=>array_shift($ar),
'replace_if_present_flag'=>array_shift($ar),
'data_coding'=>array_shift($ar),
'sm_default_msg_id'=>array_shift($ar),
'sm_length'=>array_shift($ar),
'short_message'=>$this->getString($ar,255)
);
if($this->debug)
echo "Delivered sms:n";
print_r($sms);
echo "n";

//send responce of recieving sms
$this->sendPDU(0x80000005, "", $pdu['sn']);
return $sms;

/**
* @private function
* Sends the PDU command to the SMSC and waits for responce.
* @param $command_id - command ID
* @param $pdu - PDU body
* @return PDU status or false on error
*/
function sendCommand($command_id, $pdu)
if($this->state=="closed")return false;
$this->sendPDU($command_id, $pdu, $this->sequence_number);
$status=$this->readPDU_resp($this->sequence_number, $command_id);
$this->sequence_number=$this->sequence_number+1;
return $status;

/**
* @private function
* Prepares and sends PDU to SMSC.
* @param $command_id - command ID
* @param $pdu - PDU body
* @param $seq_number - PDU sequence number
*/
function sendPDU($command_id, $pdu, $seq_number)
$length=strlen($pdu) + 16;
$header=pack("NNNN", $length, $command_id, 0, $seq_number);
if($this->debug)
echo "Send PDU : $length bytesn";
$this->printHex($header.$pdu);
echo "command_id : ".$command_id."n";
echo "sequence number : $seq_numbernn";

fwrite($this->socket, $header.$pdu, $length);

/**
* @private function
* Waits for SMSC responce on specific PDU.
* @param $seq_number - PDU sequence number
* @param $command_id - PDU command ID
* @return PDU status or false on error
*/
function readPDU_resp($seq_number, $command_id)0x80000000;
//check queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['sn']==$seq_number && $pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return $pdu['status'];


//read pdu
do
$pdu=$this->readPDU();
if($pdu)array_push($this->pdu_queue, $pdu);
while($pdu && ($pdu['sn']!=$seq_number
/**
* @private function
* Reads incoming PDU from SMSC.
* @return readed PDU or false on error.
*/
function readPDU()
//read PDU length
$tmp=fread($this->socket, 4);
if(!$tmp)return false;
extract(unpack("Nlength", $tmp));
//read PDU headers
$tmp2=fread($this->socket, 12);
if(!$tmp2)return false;
extract(unpack("Ncommand_id/Ncommand_status/Nsequence_number", $tmp2));
//read PDU body
if($length-16>0)
$body=fread($this->socket, $length-16);
if(!$body)return false;
else
$body="";

if($this->debug)
echo "Read PDU : $length bytesn";
$this->printHex($tmp.$tmp2.$body);
echo "body len : " . strlen($body) . "n";
echo "Command id : $command_idn";
echo "Command status : $command_statusn";
echo "sequence number : $sequence_numbernn";

$pdu=array(
'id'=>$command_id,
'status'=>$command_status,
'sn'=>$sequence_number,
'body'=>$body);
return $pdu;

/**
* @private function
* Reads C style zero padded string from the char array.
* @param $ar - input array
* @param $maxlen - maximum length to read.
* @return readed string.
*/
function getString(&$ar, $maxlen=255)
$s="";
$i=0;
do
$c=array_shift($ar);
if($c!=0)$s.=chr($c);
$i++;
while($i<$maxlen && $c!=0);
return $s;

/**
* @private function
* Prints the binary string as hex bytes.
* @param $maxlen - maximum length to read.
*/
function printHex($pdu)
$ar=unpack("C*",$pdu);
foreach($ar as $v)
$s=dechex($v);
if(strlen($s)<2)$s="0$s";
print "$s ";

print "n";


?>


I hope to hear from you guys.
Thank you in advance.










share|improve this question
























  • I cannot believe that no one has given any comment.

    – Emmanuel Osinnowo
    Dec 5 '18 at 18:32

















0















I've been trying to implement USSD using SMPP protocol before I shared my problem, I will talk about what've been able to achieve so far:



  1. I have been able to successfully connect with the Telco via VPN

  2. I have been able to initiate SMPP Connection and returned an appropriate response of Response_Code '0' which is 'OK'

  3. Binding of Receiver, Transceiver & Transmitter with command_id '0x00000001', '0x00000009', '0x00000002' respectively, and they all return expected Response_Code which is 'OK'.

But the following are my problems:



  1. I want to be able to bind, and when the user dials the USSD ShortCode, they should be able to see at least 'Hello World'

  2. Unable to implement 'submit_sm' after successful 'transceiver' bind

  3. My current code implementation is using SMPP to send SMS, of which is running fine, but will like to have another method e.g. $tx->runUSSD() instead of $tx->sendSMS()

Below are my codes, and I believe with this code I should be able to do it, but have been so freaking stress with research and research, I've read and have read a lot, but can't get it working:



transciever.php



<?php
print "<pre>";
require_once "./smpp.php";
$tx=new SMPP('Ip Address',Port);
$tx->debug=true;
$tx->addr_npi=1;
print "open status: ".$tx->state."n";
$tx->bindTransceiver("system_id","password");
$tx->sms_source_addr_npi=0;
$tx->sms_source_addr_ton=5;
$tx->sms_dest_addr_ton=1;
$tx->sms_dest_addr_npi=1;

$status = $tx->sendSMS("Hello","08023828392","Hello World");
$tx->close();
unset($tx);
echo $status;
print "</pre>";
?>


smpp.php



<?php

class SMPP
var $debug = true;
//SMPP bind parameters
//var $system_type="WWW";
var $interface_version=0x34;
var $addr_ton=0;
var $addr_npi=0;
var $address_range="";
//ESME transmitter parameters
var $sms_service_type="";
var $sms_source_addr_ton=0;
var $sms_source_addr_npi=0;
var $sms_dest_addr_ton=0;
var $sms_dest_addr_npi=0;
var $sms_esm_class=0;
var $sms_protocol_id=0;
var $sms_priority_flag=0;
var $sms_schedule_delivery_time="";
var $sms_validity_period="";
var $sms_registered_delivery_flag=0;
var $sms_replace_if_present_flag=0;
var $sms_data_coding=0;
var $sms_sm_default_msg_id=0;

/**
* Constructs the smpp class
* @param $host - SMSC host name or host IP
* @param $port - SMSC port
*/
function SMPP($host, $port=5016)
//internal parameters
$this->sequence_number=1;
$this->debug=false;
$this->pdu_queue=array();
$this->host=$host;
$this->port=$port;
$this->state="closed";
//open the socket
$this->socket=fsockopen($this->host, $this->port, $errno, $errstr, 30);
if($this->socket)$this->state="open";


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transciever...nn";

$status=$this->_bind($login, $pass, 0x00000009);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_trx";
return ($status===0);


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindReceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding receiver...nn";

$status=$this->_bind($login, $pass, 0x00000001);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_rx";
return ($status===0);

/**
* Binds the transmitter. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransmitter($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transmitter...nn";

$status=$this->_bind($login, $pass, 0x00000002);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_tx";
return ($status===0);

/**
* Closes the session on the SMSC server.
*/
function close()
if($this->state=="closed")return;
if($this->debug)
echo "Unbinding...nn";

$status=$this->sendCommand(0x00000006,"");
if($this->debug)
echo "Unbind status : $statusnn";

fclose($this->socket);
$this->state="closed";


/**
* Read USSD response from SMSC.
* @return
*/
function readResponse ()
if($this->state!="bind_trx")return false;

//set command id
$command_id = 0x00000005;

/**
* Read one SMS from SMSC. Can be executed only after bindReceiver() call.
* This method bloks. Method returns on socket timeout or enquire_link signal from SMSC.
* @return sms associative array or false when reading failed or no more sms.
*/
function readSMS()
if($this->state!="bind_rx")return false;
//stream_set_timeout($this->socket, 10);
$command_id=0x00000005;
//check the queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return parseSMS($pdu);


//read pdu
do
if($this->debug)
echo "read sms...nn";

$pdu=$this->readPDU();
//check for enquire link command
if($pdu['id']==0x00000015)
$this->sendPDU(0x80000015, "", $pdu['sn']);
return false;

array_push($this->pdu_queue, $pdu);
while($pdu && $pdu['id']!=$command_id);
if($pdu)
array_pop($this->pdu_queue);
return $this->parseSMS($pdu);

return false;

/**
* Read one SMS from SMSC. Can be executed only after bindTransmitter() call.
* @return true on succesfull send, false if error encountered
*/
function sendSMS($from, $to, $message)

////////////////private functions///////////////

/**
* @private function
* Binds the socket and opens the session on SMSC
* @param $login - ESME system_id
* @param $port - ESME password
* @return bind status or false on error
*/
function _bind($login, $pass, $command_id)
//make PDU
$pdu = pack(
'a'.(strlen($login)+1).
'a'.(strlen($pass)+1).
'a'.(strlen($this->system_type)+1).
'CCCa'.(strlen($this->address_range)+1),
$login, $pass, $this->system_type,
$this->interface_version, $this->addr_ton,
$this->addr_npi, $this->address_range);
$status=$this->sendCommand($command_id,$pdu);
return $status;


/**
* @private function
* Parse deliver PDU from SMSC.
* @param $pdu - deliver PDU from SMSC.
* @return parsed PDU as array.
*/
function parseSMS($pdu)
//check command id
if($pdu['id']!=0x00000005)return false;
//unpack PDU
$ar=unpack("C*",$pdu['body']);
$sms=array('service_type'=>$this->getString($ar,6),
'source_addr_ton'=>array_shift($ar),
'source_addr_npi'=>array_shift($ar),
'source_addr'=>$this->getString($ar,21),
'dest_addr_ton'=>array_shift($ar),
'dest_addr_npi'=>array_shift($ar),
'destination_addr'=>$this->getString($ar,21),
'esm_class'=>array_shift($ar),
'protocol_id'=>array_shift($ar),
'priority_flag'=>array_shift($ar),
'schedule_delivery_time'=>array_shift($ar),
'validity_period'=>array_shift($ar),
'registered_delivery'=>array_shift($ar),
'replace_if_present_flag'=>array_shift($ar),
'data_coding'=>array_shift($ar),
'sm_default_msg_id'=>array_shift($ar),
'sm_length'=>array_shift($ar),
'short_message'=>$this->getString($ar,255)
);
if($this->debug)
echo "Delivered sms:n";
print_r($sms);
echo "n";

//send responce of recieving sms
$this->sendPDU(0x80000005, "", $pdu['sn']);
return $sms;

/**
* @private function
* Sends the PDU command to the SMSC and waits for responce.
* @param $command_id - command ID
* @param $pdu - PDU body
* @return PDU status or false on error
*/
function sendCommand($command_id, $pdu)
if($this->state=="closed")return false;
$this->sendPDU($command_id, $pdu, $this->sequence_number);
$status=$this->readPDU_resp($this->sequence_number, $command_id);
$this->sequence_number=$this->sequence_number+1;
return $status;

/**
* @private function
* Prepares and sends PDU to SMSC.
* @param $command_id - command ID
* @param $pdu - PDU body
* @param $seq_number - PDU sequence number
*/
function sendPDU($command_id, $pdu, $seq_number)
$length=strlen($pdu) + 16;
$header=pack("NNNN", $length, $command_id, 0, $seq_number);
if($this->debug)
echo "Send PDU : $length bytesn";
$this->printHex($header.$pdu);
echo "command_id : ".$command_id."n";
echo "sequence number : $seq_numbernn";

fwrite($this->socket, $header.$pdu, $length);

/**
* @private function
* Waits for SMSC responce on specific PDU.
* @param $seq_number - PDU sequence number
* @param $command_id - PDU command ID
* @return PDU status or false on error
*/
function readPDU_resp($seq_number, $command_id)0x80000000;
//check queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['sn']==$seq_number && $pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return $pdu['status'];


//read pdu
do
$pdu=$this->readPDU();
if($pdu)array_push($this->pdu_queue, $pdu);
while($pdu && ($pdu['sn']!=$seq_number
/**
* @private function
* Reads incoming PDU from SMSC.
* @return readed PDU or false on error.
*/
function readPDU()
//read PDU length
$tmp=fread($this->socket, 4);
if(!$tmp)return false;
extract(unpack("Nlength", $tmp));
//read PDU headers
$tmp2=fread($this->socket, 12);
if(!$tmp2)return false;
extract(unpack("Ncommand_id/Ncommand_status/Nsequence_number", $tmp2));
//read PDU body
if($length-16>0)
$body=fread($this->socket, $length-16);
if(!$body)return false;
else
$body="";

if($this->debug)
echo "Read PDU : $length bytesn";
$this->printHex($tmp.$tmp2.$body);
echo "body len : " . strlen($body) . "n";
echo "Command id : $command_idn";
echo "Command status : $command_statusn";
echo "sequence number : $sequence_numbernn";

$pdu=array(
'id'=>$command_id,
'status'=>$command_status,
'sn'=>$sequence_number,
'body'=>$body);
return $pdu;

/**
* @private function
* Reads C style zero padded string from the char array.
* @param $ar - input array
* @param $maxlen - maximum length to read.
* @return readed string.
*/
function getString(&$ar, $maxlen=255)
$s="";
$i=0;
do
$c=array_shift($ar);
if($c!=0)$s.=chr($c);
$i++;
while($i<$maxlen && $c!=0);
return $s;

/**
* @private function
* Prints the binary string as hex bytes.
* @param $maxlen - maximum length to read.
*/
function printHex($pdu)
$ar=unpack("C*",$pdu);
foreach($ar as $v)
$s=dechex($v);
if(strlen($s)<2)$s="0$s";
print "$s ";

print "n";


?>


I hope to hear from you guys.
Thank you in advance.










share|improve this question
























  • I cannot believe that no one has given any comment.

    – Emmanuel Osinnowo
    Dec 5 '18 at 18:32













0












0








0








I've been trying to implement USSD using SMPP protocol before I shared my problem, I will talk about what've been able to achieve so far:



  1. I have been able to successfully connect with the Telco via VPN

  2. I have been able to initiate SMPP Connection and returned an appropriate response of Response_Code '0' which is 'OK'

  3. Binding of Receiver, Transceiver & Transmitter with command_id '0x00000001', '0x00000009', '0x00000002' respectively, and they all return expected Response_Code which is 'OK'.

But the following are my problems:



  1. I want to be able to bind, and when the user dials the USSD ShortCode, they should be able to see at least 'Hello World'

  2. Unable to implement 'submit_sm' after successful 'transceiver' bind

  3. My current code implementation is using SMPP to send SMS, of which is running fine, but will like to have another method e.g. $tx->runUSSD() instead of $tx->sendSMS()

Below are my codes, and I believe with this code I should be able to do it, but have been so freaking stress with research and research, I've read and have read a lot, but can't get it working:



transciever.php



<?php
print "<pre>";
require_once "./smpp.php";
$tx=new SMPP('Ip Address',Port);
$tx->debug=true;
$tx->addr_npi=1;
print "open status: ".$tx->state."n";
$tx->bindTransceiver("system_id","password");
$tx->sms_source_addr_npi=0;
$tx->sms_source_addr_ton=5;
$tx->sms_dest_addr_ton=1;
$tx->sms_dest_addr_npi=1;

$status = $tx->sendSMS("Hello","08023828392","Hello World");
$tx->close();
unset($tx);
echo $status;
print "</pre>";
?>


smpp.php



<?php

class SMPP
var $debug = true;
//SMPP bind parameters
//var $system_type="WWW";
var $interface_version=0x34;
var $addr_ton=0;
var $addr_npi=0;
var $address_range="";
//ESME transmitter parameters
var $sms_service_type="";
var $sms_source_addr_ton=0;
var $sms_source_addr_npi=0;
var $sms_dest_addr_ton=0;
var $sms_dest_addr_npi=0;
var $sms_esm_class=0;
var $sms_protocol_id=0;
var $sms_priority_flag=0;
var $sms_schedule_delivery_time="";
var $sms_validity_period="";
var $sms_registered_delivery_flag=0;
var $sms_replace_if_present_flag=0;
var $sms_data_coding=0;
var $sms_sm_default_msg_id=0;

/**
* Constructs the smpp class
* @param $host - SMSC host name or host IP
* @param $port - SMSC port
*/
function SMPP($host, $port=5016)
//internal parameters
$this->sequence_number=1;
$this->debug=false;
$this->pdu_queue=array();
$this->host=$host;
$this->port=$port;
$this->state="closed";
//open the socket
$this->socket=fsockopen($this->host, $this->port, $errno, $errstr, 30);
if($this->socket)$this->state="open";


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transciever...nn";

$status=$this->_bind($login, $pass, 0x00000009);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_trx";
return ($status===0);


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindReceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding receiver...nn";

$status=$this->_bind($login, $pass, 0x00000001);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_rx";
return ($status===0);

/**
* Binds the transmitter. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransmitter($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transmitter...nn";

$status=$this->_bind($login, $pass, 0x00000002);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_tx";
return ($status===0);

/**
* Closes the session on the SMSC server.
*/
function close()
if($this->state=="closed")return;
if($this->debug)
echo "Unbinding...nn";

$status=$this->sendCommand(0x00000006,"");
if($this->debug)
echo "Unbind status : $statusnn";

fclose($this->socket);
$this->state="closed";


/**
* Read USSD response from SMSC.
* @return
*/
function readResponse ()
if($this->state!="bind_trx")return false;

//set command id
$command_id = 0x00000005;

/**
* Read one SMS from SMSC. Can be executed only after bindReceiver() call.
* This method bloks. Method returns on socket timeout or enquire_link signal from SMSC.
* @return sms associative array or false when reading failed or no more sms.
*/
function readSMS()
if($this->state!="bind_rx")return false;
//stream_set_timeout($this->socket, 10);
$command_id=0x00000005;
//check the queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return parseSMS($pdu);


//read pdu
do
if($this->debug)
echo "read sms...nn";

$pdu=$this->readPDU();
//check for enquire link command
if($pdu['id']==0x00000015)
$this->sendPDU(0x80000015, "", $pdu['sn']);
return false;

array_push($this->pdu_queue, $pdu);
while($pdu && $pdu['id']!=$command_id);
if($pdu)
array_pop($this->pdu_queue);
return $this->parseSMS($pdu);

return false;

/**
* Read one SMS from SMSC. Can be executed only after bindTransmitter() call.
* @return true on succesfull send, false if error encountered
*/
function sendSMS($from, $to, $message)

////////////////private functions///////////////

/**
* @private function
* Binds the socket and opens the session on SMSC
* @param $login - ESME system_id
* @param $port - ESME password
* @return bind status or false on error
*/
function _bind($login, $pass, $command_id)
//make PDU
$pdu = pack(
'a'.(strlen($login)+1).
'a'.(strlen($pass)+1).
'a'.(strlen($this->system_type)+1).
'CCCa'.(strlen($this->address_range)+1),
$login, $pass, $this->system_type,
$this->interface_version, $this->addr_ton,
$this->addr_npi, $this->address_range);
$status=$this->sendCommand($command_id,$pdu);
return $status;


/**
* @private function
* Parse deliver PDU from SMSC.
* @param $pdu - deliver PDU from SMSC.
* @return parsed PDU as array.
*/
function parseSMS($pdu)
//check command id
if($pdu['id']!=0x00000005)return false;
//unpack PDU
$ar=unpack("C*",$pdu['body']);
$sms=array('service_type'=>$this->getString($ar,6),
'source_addr_ton'=>array_shift($ar),
'source_addr_npi'=>array_shift($ar),
'source_addr'=>$this->getString($ar,21),
'dest_addr_ton'=>array_shift($ar),
'dest_addr_npi'=>array_shift($ar),
'destination_addr'=>$this->getString($ar,21),
'esm_class'=>array_shift($ar),
'protocol_id'=>array_shift($ar),
'priority_flag'=>array_shift($ar),
'schedule_delivery_time'=>array_shift($ar),
'validity_period'=>array_shift($ar),
'registered_delivery'=>array_shift($ar),
'replace_if_present_flag'=>array_shift($ar),
'data_coding'=>array_shift($ar),
'sm_default_msg_id'=>array_shift($ar),
'sm_length'=>array_shift($ar),
'short_message'=>$this->getString($ar,255)
);
if($this->debug)
echo "Delivered sms:n";
print_r($sms);
echo "n";

//send responce of recieving sms
$this->sendPDU(0x80000005, "", $pdu['sn']);
return $sms;

/**
* @private function
* Sends the PDU command to the SMSC and waits for responce.
* @param $command_id - command ID
* @param $pdu - PDU body
* @return PDU status or false on error
*/
function sendCommand($command_id, $pdu)
if($this->state=="closed")return false;
$this->sendPDU($command_id, $pdu, $this->sequence_number);
$status=$this->readPDU_resp($this->sequence_number, $command_id);
$this->sequence_number=$this->sequence_number+1;
return $status;

/**
* @private function
* Prepares and sends PDU to SMSC.
* @param $command_id - command ID
* @param $pdu - PDU body
* @param $seq_number - PDU sequence number
*/
function sendPDU($command_id, $pdu, $seq_number)
$length=strlen($pdu) + 16;
$header=pack("NNNN", $length, $command_id, 0, $seq_number);
if($this->debug)
echo "Send PDU : $length bytesn";
$this->printHex($header.$pdu);
echo "command_id : ".$command_id."n";
echo "sequence number : $seq_numbernn";

fwrite($this->socket, $header.$pdu, $length);

/**
* @private function
* Waits for SMSC responce on specific PDU.
* @param $seq_number - PDU sequence number
* @param $command_id - PDU command ID
* @return PDU status or false on error
*/
function readPDU_resp($seq_number, $command_id)0x80000000;
//check queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['sn']==$seq_number && $pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return $pdu['status'];


//read pdu
do
$pdu=$this->readPDU();
if($pdu)array_push($this->pdu_queue, $pdu);
while($pdu && ($pdu['sn']!=$seq_number
/**
* @private function
* Reads incoming PDU from SMSC.
* @return readed PDU or false on error.
*/
function readPDU()
//read PDU length
$tmp=fread($this->socket, 4);
if(!$tmp)return false;
extract(unpack("Nlength", $tmp));
//read PDU headers
$tmp2=fread($this->socket, 12);
if(!$tmp2)return false;
extract(unpack("Ncommand_id/Ncommand_status/Nsequence_number", $tmp2));
//read PDU body
if($length-16>0)
$body=fread($this->socket, $length-16);
if(!$body)return false;
else
$body="";

if($this->debug)
echo "Read PDU : $length bytesn";
$this->printHex($tmp.$tmp2.$body);
echo "body len : " . strlen($body) . "n";
echo "Command id : $command_idn";
echo "Command status : $command_statusn";
echo "sequence number : $sequence_numbernn";

$pdu=array(
'id'=>$command_id,
'status'=>$command_status,
'sn'=>$sequence_number,
'body'=>$body);
return $pdu;

/**
* @private function
* Reads C style zero padded string from the char array.
* @param $ar - input array
* @param $maxlen - maximum length to read.
* @return readed string.
*/
function getString(&$ar, $maxlen=255)
$s="";
$i=0;
do
$c=array_shift($ar);
if($c!=0)$s.=chr($c);
$i++;
while($i<$maxlen && $c!=0);
return $s;

/**
* @private function
* Prints the binary string as hex bytes.
* @param $maxlen - maximum length to read.
*/
function printHex($pdu)
$ar=unpack("C*",$pdu);
foreach($ar as $v)
$s=dechex($v);
if(strlen($s)<2)$s="0$s";
print "$s ";

print "n";


?>


I hope to hear from you guys.
Thank you in advance.










share|improve this question
















I've been trying to implement USSD using SMPP protocol before I shared my problem, I will talk about what've been able to achieve so far:



  1. I have been able to successfully connect with the Telco via VPN

  2. I have been able to initiate SMPP Connection and returned an appropriate response of Response_Code '0' which is 'OK'

  3. Binding of Receiver, Transceiver & Transmitter with command_id '0x00000001', '0x00000009', '0x00000002' respectively, and they all return expected Response_Code which is 'OK'.

But the following are my problems:



  1. I want to be able to bind, and when the user dials the USSD ShortCode, they should be able to see at least 'Hello World'

  2. Unable to implement 'submit_sm' after successful 'transceiver' bind

  3. My current code implementation is using SMPP to send SMS, of which is running fine, but will like to have another method e.g. $tx->runUSSD() instead of $tx->sendSMS()

Below are my codes, and I believe with this code I should be able to do it, but have been so freaking stress with research and research, I've read and have read a lot, but can't get it working:



transciever.php



<?php
print "<pre>";
require_once "./smpp.php";
$tx=new SMPP('Ip Address',Port);
$tx->debug=true;
$tx->addr_npi=1;
print "open status: ".$tx->state."n";
$tx->bindTransceiver("system_id","password");
$tx->sms_source_addr_npi=0;
$tx->sms_source_addr_ton=5;
$tx->sms_dest_addr_ton=1;
$tx->sms_dest_addr_npi=1;

$status = $tx->sendSMS("Hello","08023828392","Hello World");
$tx->close();
unset($tx);
echo $status;
print "</pre>";
?>


smpp.php



<?php

class SMPP
var $debug = true;
//SMPP bind parameters
//var $system_type="WWW";
var $interface_version=0x34;
var $addr_ton=0;
var $addr_npi=0;
var $address_range="";
//ESME transmitter parameters
var $sms_service_type="";
var $sms_source_addr_ton=0;
var $sms_source_addr_npi=0;
var $sms_dest_addr_ton=0;
var $sms_dest_addr_npi=0;
var $sms_esm_class=0;
var $sms_protocol_id=0;
var $sms_priority_flag=0;
var $sms_schedule_delivery_time="";
var $sms_validity_period="";
var $sms_registered_delivery_flag=0;
var $sms_replace_if_present_flag=0;
var $sms_data_coding=0;
var $sms_sm_default_msg_id=0;

/**
* Constructs the smpp class
* @param $host - SMSC host name or host IP
* @param $port - SMSC port
*/
function SMPP($host, $port=5016)
//internal parameters
$this->sequence_number=1;
$this->debug=false;
$this->pdu_queue=array();
$this->host=$host;
$this->port=$port;
$this->state="closed";
//open the socket
$this->socket=fsockopen($this->host, $this->port, $errno, $errstr, 30);
if($this->socket)$this->state="open";


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transciever...nn";

$status=$this->_bind($login, $pass, 0x00000009);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_trx";
return ($status===0);


/**
* Binds the receiver. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindReceiver($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding receiver...nn";

$status=$this->_bind($login, $pass, 0x00000001);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_rx";
return ($status===0);

/**
* Binds the transmitter. One object can be bound only as receiver or only as trancmitter.
* @param $login - ESME system_id
* @param $port - ESME password
* @return true when bind was successful
*/
function bindTransmitter($login, $pass)
if($this->state!="open")return false;
if($this->debug)
echo "Binding transmitter...nn";

$status=$this->_bind($login, $pass, 0x00000002);
if($this->debug)
echo "Binding status : $statusnn";

if($status===0)$this->state="bind_tx";
return ($status===0);

/**
* Closes the session on the SMSC server.
*/
function close()
if($this->state=="closed")return;
if($this->debug)
echo "Unbinding...nn";

$status=$this->sendCommand(0x00000006,"");
if($this->debug)
echo "Unbind status : $statusnn";

fclose($this->socket);
$this->state="closed";


/**
* Read USSD response from SMSC.
* @return
*/
function readResponse ()
if($this->state!="bind_trx")return false;

//set command id
$command_id = 0x00000005;

/**
* Read one SMS from SMSC. Can be executed only after bindReceiver() call.
* This method bloks. Method returns on socket timeout or enquire_link signal from SMSC.
* @return sms associative array or false when reading failed or no more sms.
*/
function readSMS()
if($this->state!="bind_rx")return false;
//stream_set_timeout($this->socket, 10);
$command_id=0x00000005;
//check the queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return parseSMS($pdu);


//read pdu
do
if($this->debug)
echo "read sms...nn";

$pdu=$this->readPDU();
//check for enquire link command
if($pdu['id']==0x00000015)
$this->sendPDU(0x80000015, "", $pdu['sn']);
return false;

array_push($this->pdu_queue, $pdu);
while($pdu && $pdu['id']!=$command_id);
if($pdu)
array_pop($this->pdu_queue);
return $this->parseSMS($pdu);

return false;

/**
* Read one SMS from SMSC. Can be executed only after bindTransmitter() call.
* @return true on succesfull send, false if error encountered
*/
function sendSMS($from, $to, $message)

////////////////private functions///////////////

/**
* @private function
* Binds the socket and opens the session on SMSC
* @param $login - ESME system_id
* @param $port - ESME password
* @return bind status or false on error
*/
function _bind($login, $pass, $command_id)
//make PDU
$pdu = pack(
'a'.(strlen($login)+1).
'a'.(strlen($pass)+1).
'a'.(strlen($this->system_type)+1).
'CCCa'.(strlen($this->address_range)+1),
$login, $pass, $this->system_type,
$this->interface_version, $this->addr_ton,
$this->addr_npi, $this->address_range);
$status=$this->sendCommand($command_id,$pdu);
return $status;


/**
* @private function
* Parse deliver PDU from SMSC.
* @param $pdu - deliver PDU from SMSC.
* @return parsed PDU as array.
*/
function parseSMS($pdu)
//check command id
if($pdu['id']!=0x00000005)return false;
//unpack PDU
$ar=unpack("C*",$pdu['body']);
$sms=array('service_type'=>$this->getString($ar,6),
'source_addr_ton'=>array_shift($ar),
'source_addr_npi'=>array_shift($ar),
'source_addr'=>$this->getString($ar,21),
'dest_addr_ton'=>array_shift($ar),
'dest_addr_npi'=>array_shift($ar),
'destination_addr'=>$this->getString($ar,21),
'esm_class'=>array_shift($ar),
'protocol_id'=>array_shift($ar),
'priority_flag'=>array_shift($ar),
'schedule_delivery_time'=>array_shift($ar),
'validity_period'=>array_shift($ar),
'registered_delivery'=>array_shift($ar),
'replace_if_present_flag'=>array_shift($ar),
'data_coding'=>array_shift($ar),
'sm_default_msg_id'=>array_shift($ar),
'sm_length'=>array_shift($ar),
'short_message'=>$this->getString($ar,255)
);
if($this->debug)
echo "Delivered sms:n";
print_r($sms);
echo "n";

//send responce of recieving sms
$this->sendPDU(0x80000005, "", $pdu['sn']);
return $sms;

/**
* @private function
* Sends the PDU command to the SMSC and waits for responce.
* @param $command_id - command ID
* @param $pdu - PDU body
* @return PDU status or false on error
*/
function sendCommand($command_id, $pdu)
if($this->state=="closed")return false;
$this->sendPDU($command_id, $pdu, $this->sequence_number);
$status=$this->readPDU_resp($this->sequence_number, $command_id);
$this->sequence_number=$this->sequence_number+1;
return $status;

/**
* @private function
* Prepares and sends PDU to SMSC.
* @param $command_id - command ID
* @param $pdu - PDU body
* @param $seq_number - PDU sequence number
*/
function sendPDU($command_id, $pdu, $seq_number)
$length=strlen($pdu) + 16;
$header=pack("NNNN", $length, $command_id, 0, $seq_number);
if($this->debug)
echo "Send PDU : $length bytesn";
$this->printHex($header.$pdu);
echo "command_id : ".$command_id."n";
echo "sequence number : $seq_numbernn";

fwrite($this->socket, $header.$pdu, $length);

/**
* @private function
* Waits for SMSC responce on specific PDU.
* @param $seq_number - PDU sequence number
* @param $command_id - PDU command ID
* @return PDU status or false on error
*/
function readPDU_resp($seq_number, $command_id)0x80000000;
//check queue
for($i=0;$i<count($this->pdu_queue);$i++)
$pdu=$this->pdu_queue[$i];
if($pdu['sn']==$seq_number && $pdu['id']==$command_id)
//remove responce
array_splice($this->pdu_queue, $i, 1);
return $pdu['status'];


//read pdu
do
$pdu=$this->readPDU();
if($pdu)array_push($this->pdu_queue, $pdu);
while($pdu && ($pdu['sn']!=$seq_number
/**
* @private function
* Reads incoming PDU from SMSC.
* @return readed PDU or false on error.
*/
function readPDU()
//read PDU length
$tmp=fread($this->socket, 4);
if(!$tmp)return false;
extract(unpack("Nlength", $tmp));
//read PDU headers
$tmp2=fread($this->socket, 12);
if(!$tmp2)return false;
extract(unpack("Ncommand_id/Ncommand_status/Nsequence_number", $tmp2));
//read PDU body
if($length-16>0)
$body=fread($this->socket, $length-16);
if(!$body)return false;
else
$body="";

if($this->debug)
echo "Read PDU : $length bytesn";
$this->printHex($tmp.$tmp2.$body);
echo "body len : " . strlen($body) . "n";
echo "Command id : $command_idn";
echo "Command status : $command_statusn";
echo "sequence number : $sequence_numbernn";

$pdu=array(
'id'=>$command_id,
'status'=>$command_status,
'sn'=>$sequence_number,
'body'=>$body);
return $pdu;

/**
* @private function
* Reads C style zero padded string from the char array.
* @param $ar - input array
* @param $maxlen - maximum length to read.
* @return readed string.
*/
function getString(&$ar, $maxlen=255)
$s="";
$i=0;
do
$c=array_shift($ar);
if($c!=0)$s.=chr($c);
$i++;
while($i<$maxlen && $c!=0);
return $s;

/**
* @private function
* Prints the binary string as hex bytes.
* @param $maxlen - maximum length to read.
*/
function printHex($pdu)
$ar=unpack("C*",$pdu);
foreach($ar as $v)
$s=dechex($v);
if(strlen($s)<2)$s="0$s";
print "$s ";

print "n";


?>


I hope to hear from you guys.
Thank you in advance.







php smpp ussd pdu






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 8:28







Emmanuel Osinnowo

















asked Nov 15 '18 at 8:19









Emmanuel OsinnowoEmmanuel Osinnowo

65




65












  • I cannot believe that no one has given any comment.

    – Emmanuel Osinnowo
    Dec 5 '18 at 18:32

















  • I cannot believe that no one has given any comment.

    – Emmanuel Osinnowo
    Dec 5 '18 at 18:32
















I cannot believe that no one has given any comment.

– Emmanuel Osinnowo
Dec 5 '18 at 18:32





I cannot believe that no one has given any comment.

– Emmanuel Osinnowo
Dec 5 '18 at 18:32












0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53315058%2fhow-to-bind-ussd-transceiver-using-php%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53315058%2fhow-to-bind-ussd-transceiver-using-php%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Use pre created SQLite database for Android project in kotlin

Darth Vader #20

Ondo