PHP飞信发送类的修正(感谢jjchibin)

ttm1984 2010-03-03 10:29:46
原帖请参考:http://topic.csdn.net/u/20100217/18/a518dce7-dbbd-459e-966c-c398728bef79.html

由于我测试验证不严谨,导致上次发布的PHP飞信类只能给自己发短信,无法给其他飞信好友发送短信。向各位表示抱歉,同时我今天修改了这个问题。关键是两个步骤:1、登录成功后获取用户列表,2、获取用户详细信息,建立手机号码和飞信sip的uri之间的映射关系。
多的不说了,直接贴代码。经测试程序可以群发,单发,给自己发!

<?php
/**
*@desc 飞信短信发送类(Encoded:UTF-8)
*使用方法:
* * $myNewFetion = new myFetion('1381111111', 'password','SELF', '测试消息' ); // 给自己发
* $myNewFetion = new myFetion('1381111111', 'password','1382222222', '测试消息' ); // 给一个人发
* $myNewFetion = new myFetion('1381111111', 'password','1382222222,13833333333,13844444444', '测试消息' ); // 给很多人发
* $myNewFetion = new myFetion('1381111111', 'password','ALL', '测试消息' ); // 给所有飞信好友发

*非常感谢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
*
*@author shadu AT foxmail DOT com /CNOS(http://bbs.ouropen.org)
*@version 2010-03-04
*@copyright 任意拷贝和修改!
*@update 修正了只能给自己发短信的bug,感谢jjchibin的提醒
*@update 增加了群发功能
**/
class myFetion{
private $mobile_no = '1381111111'; // 发送者手机号
private $fetion_no = '738713940' ; // 发送者飞信号,程序自动获取
private $fetion_uri = 'sip:123456789@fetion.com.cn;p=1234'; // 发送者的sip
private $fetion_pwd = 'mypassword' ; // 发送者飞信登录密码
private $cookie_file = 'cookie.txt' ; // 临时存放的cookie文件

public $SMS_RECEIVER = '1382222222' ; // 短信接收者手机号码
public $SMS_TEXT = 'sms test' ; // 短信内容,支持中文

private $fetion_ContactList = "" ;
private $fetion_ContactMapping = array();

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 $curl = NULL ;
private $socket = NULL ;

/**
*从导航网站获取信息
**/
private $REQUEST_CONFIG = "<config><user mobile-no=\"%s\" /><client type=\"PC\" version=\"2.3.0230\" platform=\"W5.1\" /><servers version=\"0\" /><service-no version=\"12\" /><parameters version=\"15\" /><hints version=\"13\" /><http-applications version=\"14\" /><client-config version=\"17\" /></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\" /><caps value=\"simple-im;im-session;temp-group\" /><events value=\"contact;permission;system-message\" /><user-info attributes=\"all\" /><presence><basic value=\"400\" desc=\"\" /></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\" /><caps value=\"simple-im;im-session;temp-group\" /><events value=\"contact;permission;system-message\" /><user-info attributes=\"all\" /><presence><basic value=\"400\" desc=\"\" /></presence></args>";


/**
* 发短信
*/
private $REQUEST_SIPC_SENDSMS = "M %s SIP-C/2.0\r\nF: %s\r\nI: 2\r\nQ: 1 M\r\nT: %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";

/**
* 获取好友列表
**/
private $REQUEST_SIPC_GetContactList = "S %s SIP-C/2.0\r\nF: %s\r\nI: 3\r\nQ: 1 S\r\nN: GetContactList\r\nL: %d\r\n\r\n%s" ;
private $REQUEST_SIPC_GetContactListBody = "<args><contacts><buddy-lists /><buddies attributes=\"all\" /><mobile-buddies attributes=\"all\" /><chat-friends /><blacklist /></contacts></args>";

/**
* 获取好友信息
**/
private $REQUESR_SIPC_GetContactsInfo = "S %s SIP-C/2.0\r\nF: %s\r\nI: 9\r\nQ: 1 S\r\nN: GetContactsInfo\r\nL: %d\r\n\r\n%s";
private $REQUESR_SIPC_GetContactsInfo_body = "<args><contacts attributes=\"provisioning;impresa;mobile-no;nickname;name;gender;portrait-crc;ivr-enabled\" extended-attributes=\"score-level\">%s</contacts></args>" ;
/**
*@param $sender 短信发送者手机号
*@param $passwd 短信发送者密码
*@param $receiver 短信接收者手机号
*@param $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 ;

$this->FetionStart();
}


/**
* 开始Fetion短信发送处理流程
*
*/
private function FetionStart(){
$this->FetionGetConfig(); // 从导航网站443端口获取登录信息
if($this->FetionSocektInit()) // 初始化到SIPC的8080端口socket连接
{
$this->FetionGetSIPCNonce(); // 向服务器注册飞信号,获取关键变量值
if($this->FetionLogin()){ // 发送登录认证命令
if(!$this->FetionGetContactLists()){ // 取飞信用户列表
$this->SMS_RECEIVER == "SELF";
};
$this->FetionGetContactsInfo(); // 建立电话号码到飞信号码的映射
//$this->FetionSendSMS(); // 发短信!
if("ALL" == $this->SMS_RECEIVER){ // 给飞信上所有好友发
foreach($this->fetion_ContactMapping as $sip){
$this->FetionSendSMS($sip);
}
}
elseif("SELF" == $this->SMS_RECEIVER){ // 给自己发
$this->FetionSendSMS($this->fetion_uri);
}
else{ // 发给指定的手机号集合"13811111111,13822222222,13833333333"
$mobile_array = split("," , $this->SMS_RECEIVER);
foreach($mobile_array as $mobile){
$this->FetionSendSMS($this->fetion_ContactMapping["$mobile"]);
}
}
$this->FetionLogout();
}
else
{
echo "登录失败\n";
}
}
else
{
echo "Socket 初始化失败\n";
}
}

/**
*从导航地址获取配置信息
**/
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);
$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:738713940@fetion.com.cn;p=5914"
$this->fetion_uri = $uri ; // 发送者自己的sip
if(preg_match('/^sip:(\d+)@(\S+);.*$/', $uri, $matches)){
$this->fetion_no = $matches[1] ;
$this->domain_fetion = $matches[2] ;
}
}

/**
*初始化Fetion通讯Socket
**/
private function FetionSocektInit(){
$this->SIPC_PROXY;
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
list($ip_fetion, $port_fetion) = split(':', $this->SIPC_PROXY) ; // "221.176.31.4:8080"
return socket_connect($this->socket, $ip_fetion, $port_fetion) ;
}
...全文
2327 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
ttm1984 2010-12-28
  • 打赏
  • 举报
回复
抱歉,各位!
我很久没来CSDN了,密码也差点忘了。

我是自己锻炼和使用,才写了这个程序。因为工作较忙,加上飞信接口升级,目前这个程序已经不能正常工作,我也没有时间维护。
再次感谢大家!
风声边界 2010-12-18
  • 打赏
  • 举报
回复
test4.xml中数据是啥?给个完整的
谢谢
baizhongwei 2010-12-09
  • 打赏
  • 举报
回复
http://www.oschina.net/p/pafetion
ncyjp 2010-08-20
  • 打赏
  • 举报
回复
飞信升级了
arcsoft_hz 2010-08-18
  • 打赏
  • 举报
回复
前几个都用的好好的,最近无法正常使用了,一直报错:
PHP Fatal error: Call to a member function getAttribute() on a non-object in C:\Inetpub\SolarWinds\fetion\class.myfetionV5.php on line 222

看楼上有人遇到同样的问题,说是密码输错了,但我确信密码是正确的,不知道该怎么解决?
ncyjp 2010-08-16
  • 打赏
  • 举报
回复
又用不了了
namenameq 2010-08-05
  • 打赏
  • 举报
回复
现在又不能用了,老大
swardman2006 2010-03-30
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 swardman2006 的回复:]
Fatal error: Call to a member function getAttribute() on a non-object in D:\Apache2.2\htdocs\topkey_admin\fetion\class.myfetionV5.php on line 222

一測試就出現這個問題是怎麼回事呀?
[/Quote]原來我密碼輸入錯誤了!呵,可以用啊,不錯,謝謝!
swardman2006 2010-03-30
  • 打赏
  • 举报
回复
Fatal error: Call to a member function getAttribute() on a non-object in D:\Apache2.2\htdocs\topkey_admin\fetion\class.myfetionV5.php on line 222

一測試就出現這個問題是怎麼回事呀?
horsley 2010-03-28
  • 打赏
  • 举报
回复
新的可以用了 非常感谢
cs99619 2010-03-27
  • 打赏
  • 举报
回复
private function FetionGetContactsInfo(){
$this->REQUESR_SIPC_GetContactsInfo_body = sprintf($this->REQUESR_SIPC_GetContactsInfo_body, $this->fetion_ContactList);
$REQUESR_SIPC_GetContactsInfo = sprintf($this->REQUESR_SIPC_GetContactsInfo,
$this->domain_fetion,
$this->fetion_no,
strlen($this->REQUESR_SIPC_GetContactsInfo_body),
$this->REQUESR_SIPC_GetContactsInfo_body
);
$sock_data = socket_write($this->socket, $REQUESR_SIPC_GetContactsInfo);
if (false == ($buf = socket_read($this->socket, 1024*10))) {
echo "\nLine:" . __LINE__ . " socket_read() failed; reason: " . socket_strerror(socket_last_error($this->socket)) . "\n";
}
//echo $buf,"\n\n";
file_put_contents("GetContactsInfo.txt",$buf);
if(preg_match_all('/<contact uri=\"(.*?)\".*?mobile\-no=\"(.*?)\".*?\/contact>/s',$buf,$matches)){
$total = count($matches[1]);
for($i=0; $i<$total; $i++){
$uri = $matches[1][$i];
$mobile = $matches[2][$i];
$this->fetion_ContactMapping["$mobile"] = $uri ; // "13811111111" => "sip:912534014@fetion.com.cn;p=9272"
}
return true;
}
else{
return false;
}
}

这个函数能否修改成curl版的?
自己修改了,但是测试失败。。取到的内容为空
ygmpkk 2010-03-24
  • 打赏
  • 举报
回复
Fatal error: Call to a member function getAttribute() on a non-object in D:\Software\PHPnow\htdocs\fetion\class.myfetionV5.php on line 224

一运行就这样,是怎么回事呢?
ttm1984 2010-03-22
  • 打赏
  • 举报
回复
请各位重新下载测试程序,我做了更新。

http://i.isclab.org/tools/fetion.zip

*@author shadu AT foxmail DOT com
*@copyright 任意拷贝和修改!
*@version 2010-03-22
*@update 采用联系方式缓存技术,加速短信发送速度(程序所在目录需要给写权限,第一次使用该程序可能有点慢)
* ----
*@version 2010-03-16
*@update 失败后重新登录(最多三次),减少了漏发现象。现在几乎没有了。
*@update 设置超时等待时间为2秒,减少了白屏现象
*@update 对socket做了优化,联系人较多的时候也能处理
*@update 使用fsockopen方式发短息,取消了原来直接使用socket模块的方式。有些虚拟主机禁用了socket函数。
*@update 给自己发短信可以不用SELF了,直接输入手机号码

horsley 2010-03-21
  • 打赏
  • 举报
回复
不知道为什么 那个测试页 会弄出来 http 500 错误
地址:http://m.jianhome.cn/f/fetion.php

检查空间 有 2个xml 能成功生成 不知道 哪里出的问题
ttm1984 2010-03-18
  • 打赏
  • 举报
回复
8080端口是飞信服务器的端口。
IP地址是从导航网站的XML中获取的,非第三方服务器。代码里也没有直接使用这个IP。
开源就是为了安全,请放心使用。
wrscn 2010-03-17
  • 打赏
  • 举报
回复
221.176.31.4
这个IP是移动官方的,还是第三方的?是否安全?

private $SIPC_PROXY = '221.176.31.4:8080'; // 8080端口飞信通讯使用
hotdigger 2010-03-17
  • 打赏
  • 举报
回复
太好了.感谢分享.
jerryrat1984 2010-03-16
  • 打赏
  • 举报
回复
显示错误

好友还是发送不成功

Fetion Error: No ssic found in cookie
bhenpeigmail 2010-03-15
  • 打赏
  • 举报
回复
为什么会显示错误呢?
Fatal error: Call to a member function getAttribute() on a non-object in C:\wamp\www\fetion\class.myfetion.php on line 196
ruanchao 2010-03-04
  • 打赏
  • 举报
回复
引用 3 楼 ylw1230 的回复:
回去测试一下,感谢分享!


值得借鉴,多谢分享!
加载更多回复(6)

21,887

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧