如何绑定美元收发器

问题描述 投票:0回答:1

在分享我的问题之前,我一直在尝试使用SMPP协议来实现USSD,我将谈论到目前为止已经取得的成就:

  1. 我已经能够通过VPN成功连接到电信公司

  2. 我已经能够启动SMPP连接并返回Response_Code'0'的适当响应,即'OK'

  3. 分别具有command_id'0x00000001','0x00000009','0x00000002'的接收器,收发器和发送器的绑定,它们都返回预期的Response_Code,即'OK'。

但是以下是我的问题:

  1. 我希望能够绑定,并且当用户拨打USSD短代码时,他们应该至少能够看到'Hello World'

  2. 成功完成'收发器'绑定后无法实现'submit_sm'

  3. runUSSD()代替$ tx-> sendSMS()
  • 下面是我的代码,我相信使用此代码我应该能够做到,但是由于研究工作压力很大,我已经阅读了很多,但无法使它正常工作:

    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...\n\n";
            }
            $status=$this->_bind($login, $pass, 0x00000009);
            if($this->debug){
                echo "Binding status  : $status\n\n";
            }
            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...\n\n";
            }
            $status=$this->_bind($login, $pass, 0x00000001);
            if($this->debug){
                echo "Binding status  : $status\n\n";
            }
            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...\n\n";
            }
            $status=$this->_bind($login, $pass, 0x00000002);
            if($this->debug){
                echo "Binding status  : $status\n\n";
            }
            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...\n\n";
            }
            $status=$this->sendCommand(0x00000006,"");
            if($this->debug){
                echo "Unbind status   : $status\n\n";
            }
            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...\n\n";
                }
                $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){
            if (strlen($from)>20 || strlen($to)>20)return false;
            if($this->state!="bind_tx")return false;
            $short_message = $message;
            //*
    //      echo "test is just test ".$from;
    
            if(strlen($message) > 160){
    
                $length = 153;
                $max = 153;
    
                $msgs = array();
    
                array_push($msgs, substr($message, 0, $max));
    
                //echo $message." just me";
                while(true){
    
                   if(strlen($message) - $length > $max){
    
                        array_push($msgs, substr($message, $length, $max));
    
                        $length = $length + $max;
                //echo "always here";
                        // msgs.add(message.substring(tempCount, max));
                        // tempCount += max;
                    }else{
                        //echo "always here still";
                        array_push($msgs, substr($message, $length));
    
                       //$msgs.add(message.substring(tempCount));
    
                       break;
                   }
                }
                //echo count($msgs)." count\n";
                if(count($msgs) > 0){
    
                    for($i = 0; $i < count($msgs); $i++){
                        $short_message = $msgs[$i];
                        //*
                    //  echo "\n".$short_message.": ".$i ;
                        $pdu = pack('a1cca'.(strlen($from)+1).'cca'.(strlen($to)+1).'ccca1a1ccccca'.(strlen($short_message)+1),
                            $this->sms_service_type,
                            $this->sms_source_addr_ton,
                            $this->sms_source_addr_npi,
                            $from,//source_addr
                            $this->sms_dest_addr_ton,
                            $this->sms_dest_addr_npi,
                            $to,//destination_addr
                            $this->sms_esm_class,
                            $this->sms_protocol_id,
                            $this->sms_priority_flag,
                            $this->sms_schedule_delivery_time,
                            $this->sms_validity_period,
                            $this->sms_registered_delivery_flag,
                            $this->sms_replace_if_present_flag,
                            $this->sms_data_coding,
                            $this->sms_sm_default_msg_id,
                            strlen($short_message),//sm_length
                            $short_message//short_message
                        );
                        $status=$this->sendCommand(0x00000004,$pdu);
                    //  echo "\n".$status."final\n";
                    }
    
                    // return $status === 0;
                }
    
    
    
            }else{
                $short_message = $message;
                //*
                $pdu = pack('a1cca'.(strlen($from)+1).'cca'.(strlen($to)+1).'ccca1a1ccccca'.(strlen($message)+1),
                    $this->sms_service_type,
                    $this->sms_source_addr_ton,
                    $this->sms_source_addr_npi,
                    $from,//source_addr
                    $this->sms_dest_addr_ton,
                    $this->sms_dest_addr_npi,
                    $to,//destination_addr
                    $this->sms_esm_class,
                    $this->sms_protocol_id,
                    $this->sms_priority_flag,
                    $this->sms_schedule_delivery_time,
                    $this->sms_validity_period,
                    $this->sms_registered_delivery_flag,
                    $this->sms_replace_if_present_flag,
                    $this->sms_data_coding,
                    $this->sms_sm_default_msg_id,
                    strlen($message),//sm_length
                    $message//short_message
                );
                $status=$this->sendCommand(0x00000004,$pdu);
            }
            //*/
            // return $status;
            //echo $status."This is a test";
            return ($status == 0);
        }
    
        ////////////////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, "\0", $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 bytes\n";
                $this->printHex($header.$pdu);
                echo "command_id      : ".$command_id."\n";
                echo "sequence number : $seq_number\n\n";
            }
            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){
            //create responce id
            $command_id=$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 || $pdu['id']!=$command_id));
            //remove responce from queue
            if($pdu){
                array_pop($this->pdu_queue);
                return $pdu['status'];
            }
            return false;
        }
        /**
         * @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 bytes\n";
                $this->printHex($tmp.$tmp2.$body);
                echo "body len        : " . strlen($body) . "\n";
                echo "Command id      : $command_id\n";
                echo "Command status  : $command_status\n";
                echo "sequence number : $sequence_number\n\n";
            }
            $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";
        }
    }
    ?>
    
  • php smpp ussd pdu
    1个回答
    0
    投票
    因此,您应该相应地对待SMSC网关。您是否想拥有交互式菜单,那么您应该考虑“会话”,因为通过SMPP实现这种交互是很困难的。
    © www.soinside.com 2019 - 2024. All rights reserved.