首頁 >後端開發 >php教程 >飞信短信发送的PHP类(散分)解决方法

飞信短信发送的PHP类(散分)解决方法

WBOY
WBOY原創
2016-06-13 10:12:441008瀏覽

飞信短信发送的PHP类(散分)
飞信发送API网上有很多,但没有多少是我自己满意的。很多网站提供基于Web的API调用方式向用户提供服务,但是作为使用者我心里还是没底。我总是担心自己的密码会被某些人记录,一直想写一个自己用的PHP版本飞信发送程序。
  因为本人没有任何逆向基础,同时飞信版本变化不同。从nathan在百度上发布《飞信协议分析》到现在也有3年了,且当时分析的是飞信2006版本。这中间变化太多,也使得我在写PHP版本飞信发送程序是走了很多弯路。
  我曾经拜读过superli_198的《让 PHP 程序利用飞信(Fetion)发免费短信》,但是该版本使用的通讯方式目前已经不被飞信支持,且superli_198也没有做新的更新。我也下载过c.young[@]xicabin.com的Openfetion,但是该版本存在明显bug,现在也不能正常使用。无奈只能硬着头皮修改一个C# 版本的飞信发送程序。
  在移植C#版本的飞信发送程序到PHP过程中,我遇到了一个关于MD5加密相关的问题,困了很多天。最后在CSDN论坛ycTIN的帮助下,问题得以解决。非常感谢ycTIN。 以下是我完成的PHP版飞信短信发送类,截止到2010年2月17日下午4点该程序一直能正常工作。技术上没有什么难度,发在这里和大家交流。

PHP code
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--><?php /** [email&#160;protected] 飞信短信发送类(Encoded:UTF-8) *使用方法:$myNewFetion = new myFetion('1381111111', 'password','1382222222', '测试消息' ); *非常感谢CSDN论坛ycTIN在MD5加密部分的帮助! *本程序未做容错处理,为防止诈骗短信乱发,程序不提供添加好友功能 *测试URL:http://i.isclab.org/tools/fetion.php * *程序运行条件: *1.服务器能够访问飞信服务器nav.fetion.com.cn的443端口(https) *2.服务器端PHP程序能够创建socket访问221.176.31.4的8080端口 * *关键技术: *1.CURL + SSL通讯 *2.PHP Socket编程 *3.PHP MD5函数的深入理解 *4.PHP DOM处理XML * [email&#160;protected] shadu AT foxmail DOT com /CNOS(http://bbs.ouropen.org) [email&#160;protected] 2010-02-17 [email&#160;protected] 任意拷贝和修改! **/class myFetion{    private $mobile_no   = '1381111111'; // 发送者手机号    private $fetion_no   = '738713940' ; // 发送者飞信号,程序自动获取    private $fetion_pwd  = 'mypassword' ; // 发送者飞信登录密码    private $cookie_file = 'cookie.txt' ; // 临时存放的cookie文件        public $SMS_RECEIVER = '1382222222' ; //  短信接收者手机号码     public $SMS_TEXT     = 'sms test' ; // 短信内容,支持中文        private $NONCE       = 'AAB3238922BCC25A6F606EB525FFDC56' ; // SIPC服务器返回,每次不同    private $C_NONCE     = 'AAB3238922BCC25A6F606EB525FFDC56' ; // 是随机的,但是固定值也没关系    private $SSIC        = '' ; // cookie中提取的变量    private $RESPONSE    = '' ; // 加密后的密钥串        private $url_nav            = 'https://nav.fetion.com.cn/nav/getsystemconfig.aspx' ; // 443端口获取导航信息    private $domain_fetion      = 'fetion.com.cn' ; // 飞信服务器的域名        private $SIPC_PROXY         = '221.176.31.4:8080';  //  8080端口飞信通讯占用     private $SSI_PROXY_SIGN_IN  = 'https://uid.fetion.com.cn/ssiportal/SSIAppSignIn.aspx' ; // 登录URL    private $SSI_PROXY_SIGH_OUT = 'http://ssi.fetion.com.cn/ssiportal/SSIAppSignOut.aspx' ; // 登出URL        private $proxy_http = 'proxy.example.com:8080' ; // HTTP代理服务器地址    private $curl = NULL ;    private $socket = NULL ;        /**     *从导航网站获取信息     **/    private $REQUEST_CONFIG = "<config><user mobile-no='\"%s\"'></user><client type='\"PC\"' version='\"2.3.0230\"' platform='\"W5.1\"'></client><servers version='\"0\"'></servers><service-no version='\"12\"'></service-no><parameters version='\"15\"'></parameters><hints version='\"13\"'></hints><http-applications version='\"14\"'></http-applications><client-config version='\"17\"'></client-config>";        /**     *使用手机号码和密码向服务器获取对应的飞信号码信息     **/    private $REQUEST_SSI_SIGN  = "mobileno=%s&pwd=%s" ;        /**     *使用飞信号码向SIPC服务器注册,获取临时变量NONCE和SSIC的值     **/    private $REQUEST_SIPC_SIGN_NONCE      = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 1 R\r\nL: %d\r\n\r\n%s" ;    private $REQUEST_SIPC_SIGN_NONCE_BODY = "<args><device type='\"PC\"' version='\"6\"' client-version='\"2.3.0230\"'></device><caps value='\"simple-im;im-session;temp-group\"'></caps><events value='\"contact;permission;system-message\"'></events><user-info attributes='\"all\"'></user-info><presence><basic value='\"400\"' desc='\"\"'></basic></presence></args>";        /**     *使用飞信号码和加密的密码登录飞信SIPC服务器     **/    private $REQUEST_SIPC_LOGIN           = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 2 R\r\nA: Digest response=\"%s\",cnonce=\"%s\"\r\nL: %d\r\n\r\n%s";    private $REQUEST_SIPC_LOGIN_BODY      = "<args><device type='\"PC\"' version='\"6\"' client-version='\"2.3.0230\"'></device><caps value='\"simple-im;im-session;temp-group\"'></caps><events value='\"contact;permission;system-message\"'></events><user-info attributes='\"all\"'></user-info><presence><basic value='\"400\"' desc='\"\"'></basic></presence></args>";        private $REQUEST_SIPC_SENDSMS         = "M %s SIP-C/2.0\r\nF: %s\r\nI: 2\r\nQ: 1 M\r\nT: tel:%s\r\nN: SendSMS\r\nL: %d\r\n\r\n%s";        private $REQUEST_SIPC_LOGOUT          = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1 \r\nQ: 3 R\r\nX: 0\r\n\r\n";        /**     [email protected] $sender 短信发送者手机号     [email protected] $passwd 短信发送者密码     [email protected] $receiver 短信接收者手机号     [email protected] $msg 短信内容     **/    public function __construct($sender, $passwd, $receiver, $msg){        $this->mobile_no    = $sender ;        $this->fetion_pwd   = $passwd;        $this->SMS_RECEIVER = $receiver;        $this->SMS_TEXT     = $msg;        $this->cookie_file  = $this->mobile_no . $this->cookie_file ;        file_put_contents($this->cookie_file, '') ;                $this->FetionGetConfig(); // 从导航网站443端口获取登录信息        $this->FetionSocektInit(); // 初始化到SIPC的8080端口socket连接        $this->FetionGetSIPCNonce(); // 向服务器注册飞信号,获取关键变量值        if($this->FetionLogin()){    // 发送登录认证命令            $this->FetionSendSMS(); // 发送短信发送命令            $this->FetionLogout();        }            }            /**     *从导航地址获取配置信息     **/    private function FetionGetConfig(){        $this->REQUEST_CONFIG = sprintf($this->REQUEST_CONFIG,                                        $this->mobile_no);        $this->curl = curl_init();        curl_setopt($this->curl, CURLOPT_URL, $this->url_nav);        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);        curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookie_file);        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1);        curl_setopt($this->curl, CURLOPT_POST, 1);        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->REQUEST_CONFIG);        //curl_setopt($this->curl, CURLOPT_PROXY, $this->proxy_http); // 设置代理服务器        $xml_config = curl_exec($this->curl);                // 以下是从导航页面返回的XML里取相关信息        file_put_contents("test3.xml", $xml_config) ;        $xmlDom = new DOMDocument() ;        $xmlDom->loadXML($xml_config);        $fetion_server = $xmlDom->getElementsByTagName('servers');        $fetion_server->item(0)->getElementsByTagName('sipc-proxy')->item(0)->nodeValue;        $this->SSI_PROXY_SIGN_IN  = $fetion_server->item(0)->getElementsByTagName('ssi-app-sign-in')->item(0)->nodeValue;        $this->SSI_PROXY_SIGH_OUT = $fetion_server->item(0)->getElementsByTagName('ssi-app-sign-out')->item(0)->nodeValue;        $this->SSI_PROXY_SIGN_IN;                // 以下获取手机号对应的飞信号        sprintf($this->REQUEST_SSI_SIGN, $this->mobile_no, $this->fetion_pwd) ;        curl_setopt($this->curl, CURLOPT_URL, $this->SSI_PROXY_SIGN_IN);        curl_setopt($this->curl, CURLOPT_POSTFIELDS, sprintf($this->REQUEST_SSI_SIGN, $this->mobile_no, $this->fetion_pwd));        $Result = curl_exec($this->curl);        curl_close($this->curl);        file_put_contents("test4.xml", $Result) ;        $xmlDom->loadXML($Result);        $uri = $xmlDom->getElementsByTagName("user")->item(0)->getAttribute("uri");        //"sip:[email protected];p=5914"        if(preg_match('/^sip:(\d+)@(\S+);.*$/', $uri, $matches)){            $this->fetion_no = $matches[1] ;            $this->domain_fetion = $matches[2] ;        }            }        /**     *初始化Fetion通讯Socket     **/    private function FetionSocektInit(){        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);        list($ip_fetion, $port_fetion) = split(':', $this->SIPC_PROXY) ; // "221.176.31.4:8080"        socket_connect($this->socket, $ip_fetion, $port_fetion) ;    }        /**     *注册飞信号码并获取临时变量NONCE和SSIC     **/    private function FetionGetSIPCNonce(){        $REQUEST_SIPC_SIGN_NONCE = sprintf($this->REQUEST_SIPC_SIGN_NONCE, $this->domain_fetion,                                           $this->fetion_no, strlen($this->REQUEST_SIPC_SIGN_NONCE_BODY),                                           $this->REQUEST_SIPC_SIGN_NONCE_BODY) ;        $sock_data = socket_write($this->socket, $REQUEST_SIPC_SIGN_NONCE);        $buf = '' ;        if (false == ($buf = socket_read($this->socket, 1000))) {            echo "Line:" . __LINE__ . "socket_read() failed; reason: " . socket_strerror(socket_last_error($this->socket)) . "\n";        }        $regex_ssic = '/.*nonce=\"(\\w+)\".*/s' ;        if(!preg_match($regex_ssic, $buf, $matches)){            echo "Fetion Error: No nonce found in socket\n";        }        $this->NONCE = strtoupper(trim($matches[1]));        $regex_ssic = '/ssic\s+(.*)/s';        if (!preg_match($regex_ssic, file_get_contents($this->cookie_file), $matches)) {            echo "Fetion Error: No ssic found in cookie\n";        }        $this->SSIC = trim($matches[1]);    }<div class="clear">
                 
              
              
        
            </div>
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn