前不久用了全恒壮的技术博客上的一个php飞信类,用它实现一个小程序。
不过最近发现在向好友发短信的时候总是失败,于是查看程序源码:
源码放在服务器上没动过,以前用都好的,第一反应就是飞信官方对wap页面做了修改(因为该类是通过模拟登录wap飞信来实现)。
果然,在查看了wap飞信网页的相关源代码后发现如下内容:

而原来的代码中并没有csrfToken的值,如下所示:
/**
* 向好友发送飞信
* @param string $uid 飞信ID
* @param string $message 短信内容
* @return string
*/
protected function _toUid($uid, $message) {
$uri = '/im/chat/sendMsg.action?touserid='.$uid;
$data = 'msg='.urlencode($message);
$result = $this->_postWithCookie($uri, $data);
return $result;
}
找到了原因,解决办法就有了,我们只要把csrfToken的值提取出来,再传递给该内部函数,通过POST方式把msg和csrfToken一起提交给飞信wap端就可以了。
修改后的结果如下:
/**
* 向好友发送飞信
* @param string $uid 飞信ID
* @param string $message 短信内容
* @return string
*/
protected function _toUid($uid, $message) {
$uri = '/im/chat/sendMsg.action?touserid='.$uid;
$data = 'msg='.urlencode($message).'&csrfToken='.$this->_getcsrfToken($uid);
$result = $this->_postWithCookie($uri, $data);
return $result;
}
其中用来获取csrfToken值的内部函数_getcsrfToken()如下:
/**
* 获取csrfToken值
* @param string $uid
* @return string
*/
protected function _getcsrfToken($uid) {
$uri = 'im/chat/toinputMsg.action?touserid='.$uid;
$host = 'f.10086.cn';
$result = $this->_getWithCookie($uri, $host);
// 匹配
preg_match('/name="csrfToken" value="(\w+)"/', $result, $matches);
return isset($matches[1]) ? $matches[1] : '';
}
获取时需要用到带cookie的GET方式,我用socket构建了一个内部函数如下:
/**
* 携带Cookie向f.10086.cn发送GET请求
* @param string $uri
* @param string $host
*/
protected function _getWithCookie($uri, $host){
$fp = fsockopen($host, 80) or die("Open ". $uri ." failed");
$header = "GET /".$uri ." HTTP/1.1\r\n";
$header .= "Accept: */*\r\n";
$header .= "Accept-Language: zh-cn\r\n";
$header .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; InfoPath.1; .NET CLR 2.0.50727)\r\n";
$header .= "Host: ". $host ."\r\n";
$header .= "Connection: Keep-Alive\r\n";
$header .= "Cookie: {$this->_cookie}\r\n";
$header .= "Connection: Close\r\n\r\n";
fwrite($fp, $header);
while (!feof($fp)) {
$contents .= fgets($fp, 8192);
}
fclose($fp);
return $contents;
}
经过以上修改,这个飞信类又可以正常地向好友发送短信了。
更新文件点此下载:phpfetion_v1.3.0.zip
2012年7月18日:抱歉啊,下载链接出了点问题,各位请到本博客的 工具|下载 页面中的 源代码 文件夹中下载:
我也将向该类的原作者告知这一BUG,原来的内容参照这里:PHP飞信发送类(PHPFetion)v1.2发布
