前不久用了全恒壮的技术博客上的一个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发布