/** * User: didiaoyu * Date: 13-10-18 * Time: 下午10:05 * 微信login */ class Weixinautologin { private $token; // 公共平台申请时填写的token private $account; private $password; // 每次登录后将cookie, webToken缓存起来, 调用其它api时直接使用 // 注: webToken与token不一样, webToken是指每次登录后动态生成的token, 供难证用户是否登录而用 private $cookiePath; // 保存cookie的文件路径 private $webTokenPath; // 保存webToken的文路径 // 缓存的值 private $webToken; // 登录后每个链接后都要加token private $cookie; // 构造函数 public function __construct($account, $passwd, $use_cache=true) { // 配置初始化 $this->account = $account; $this->password = $passwd; $this->cookiePath = dirname(__FILE__).'/cache/cookie'; $this->webTokenPath = dirname(__FILE__).'/cache/webToken'; // 从缓存中读取cookie, webToken 判断是否已经登录(未登录则执行登录操作) $this->getCookieAndWebToken($use_cache); } /** * 从缓存中得到cookie和webToken * @param $use_cache 是否使用cookie文件缓存 * @return mix */ public function getCookieAndWebToken($use_cache) { $this->cookie = file_exists($this->cookiePath)?file_get_contents($this->cookiePath):''; $this->webToken = file_exists($this->webTokenPath)?file_get_contents($this->webTokenPath):''; // 如果有缓存信息, 则验证下有没有过时, 此时只需要访问一个api即可判断 if($use_cache && $this->cookie && $this->webToken) { $re = $this->getUserInfo('1'); if(is_array($re)) { return true; }else{ return $this->login(); } } else { return $this->login(); } } /** * 模拟登录获取cookie和webToken */ public function login() { $url = "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN"; $post["username"] = $this->account; $post["pwd"] = md5($this->password); $post["f"] = "json"; $re = $this->submit($url, $post); // 保存cookie $this->cookie = $re['cookie']; file_put_contents($this->cookiePath, $this->cookie); // 得到token $this->getWebToken($re['body']); return true; } /** * 获取粉丝的用户信息 * @param string $fakeId 用户的fakeId * @return mix 返回用于信息 */ public function getUserInfo($fakeId) { $url = "https://mp.weixin.qq.com/cgi-bin/getcontactinfo?t=ajax-getcontactinfo&lang=zh_CN&token={$this->webToken}&fakeid=$fakeId"; $re = $this->submit($url, array(), $this->cookie); $result = json_decode($re['body'], 1); /** * array (size=1) 'base_resp' => array (size=2) 'ret' => int -3 'err_msg' => string 'invalid session' (length=15) */ if(!$result || (!empty($result['base_resp']) && $result['base_resp']['ret']==-3)) { $this->login(); } return $result; } public function getBossInfo(){ $url = "https://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/index&action=index&token={$this->webToken}&lang=zh_CN"; $res = $this->get($url, $this->cookie); preg_match_all('/
(.*)<\/div>/U', $res['body'], $matchs); $bossInfo = array(); if(count($matchs)==2){ foreach($matchs[1] as $k=>$v){ switch($k){ case 0: preg_match('/src=\"(.*)\"/', $v, $match_img); $bossInfo['logo'] = 'https://mp.weixin.qq.com'.$match_img['1']; break; case 1: $bossInfo['mp_name'] = trim(strip_tags($v)); break; case 2: $bossInfo['email'] = trim(strip_tags($v)); //登录邮箱 $bossInfo['mp_username'] = trim(strip_tags($v)); break; case 3: $bossInfo['mp_fakeid'] = trim(strip_tags($v)); $bossInfo['openid'] = trim(strip_tags($v)); break; case 4: $bossInfo['mp_wxid'] = trim(strip_tags($v)); break; case 8: $bossInfo['address'] = trim(strip_tags($v)); break; } } } return $bossInfo; } public function downloadImage($imgUrl){ $res = $this->get($imgUrl, $this->cookie); return $res['body']; } /** * 登录后从结果中解析出webToken * @param [String] $logonRet * @return mix */ private function getWebToken($logonRet) { $logonRet = json_decode($logonRet, true); $msg = $logonRet["ErrMsg"]; // /cgi-bin/indexpage?t=wxm-index&lang=zh_CN&token=1455899896 $msgArr = explode("&token=", $msg); if(count($msgArr) != 2) { return false; } else { $this->webToken = $msgArr[1]; file_put_contents($this->webTokenPath, $this->webToken); return true; } } /** * 主动发消息 * @param string $id 用户的fakeid * @param string $content 发送的内容 * @return mix */ public function send($id, $content) { $post = array(); $post['tofakeid'] = $id; $post['type'] = 1; $post['content'] = $content; $post['ajax'] = 1; $url = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response&token={$this->webToken}"; $re = $this->submit($url, $post, $this->cookie); return json_decode($re['body']); } /** * 批量发送 * @param [array] $ids 用户的fakeid集合 * @param [type] $content [description] * @return mix */ public function batSend($ids, $content) { $result = array(); foreach($ids as $id) { $result[$id] = $this->send($id, $content); } return $result; } /** * 发送图片 * @param int $fakeId [description] * @param int $fileId 图片ID * @return mix */ public function sendImage($fakeId, $fileId) { $post = array(); $post['tofakeid'] = $fakeId; $post['type'] = 2; $post['fid'] = $post['fileId'] = $fileId; // 图片ID $post['error'] = false; $post['ajax'] = 1; $post['token'] = $this->webToken; $url = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response&lang=zh_CN"; $re = $this->submit($url, $post, $this->cookie); return json_decode($re['body']); } /* 得到最近发来的信息 [0] => Array ( [id] => 189 [type] => 1 [fileId] => 0 [hasReply] => 0 [fakeId] => 1477341521 [nickName] => lealife [remarkName] => [dateTime] => 1374253963 ) [ok] */ public function getLatestMsgs($page = 0) { // frommsgid是最新一条的msgid $frommsgid = 100000; $offset = 50 * $page; $url = "https://mp.weixin.qq.com/cgi-bin/message?t=message/list&count=999999&day=7&offset={$offset}&token={$this->webToken}&lang=zh_CN"; $re = $this->get($url, $this->cookie); // 解析得到数据 list : ({"msg_item":[{"id":}, {}]}) $match = array(); preg_match('/["\' ]msg_item["\' ]:\[{(.+?)}\]/', $re['body'], $match); if(count($match) != 2) { return ""; } $match[1] = "[{". $match[1]. "}]"; return json_decode($match[1], 1); } // 解析用户信息 // 当有用户发送信息后, 如何得到用户的fakeId? // 1. 从web上得到最近发送的信息 // 2. 将用户发送的信息与web上发送的信息进行对比, 如果内容和时间都正确, 那肯定是该用户 // 实践发现, 时间可能会不对, 相隔1-2s或10多秒也有可能, 此时如果内容相同就断定是该用户 // 如果用户在时间相隔很短的情况况下输入同样的内容很可能会出错, 此时可以这样解决: 提示用户输入一些随机数. /** * 通过时间 和 内容 双重判断用户 * @param [type] $createTime * @param [type] $content * @return mix */ public function getLatestMsgByCreateTimeAndContent($createTime, $content) { $lMsgs = $this->getLatestMsgs(0); // 最先的数据在前面 $contentMatchedMsg = array(); foreach($lMsgs as $msg) { // 仅仅时间符合 if($msg['dateTime'] == $createTime) { // 内容+时间都符合 if($msg['content'] == $content) { return $msg; } // 仅仅是内容符合 } else if($msg['content'] == $content) { $contentMatchedMsg[] = $msg; } } // 最后, 没有匹配到的数据, 内容符合, 而时间不符 // 返回最新的一条 if($contentMatchedMsg) { return $contentMatchedMsg[0]; } return false; } /** * 获取用户分组信息 * @return mixed|string */ public function getGroups(){ $url = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&lang=zh_CN&token={$this->webToken}&pagesize=10&pageidx=0&type=0&groupid=0"; $re = $this->get($url, $this->cookie); $result = json_decode($re['body'], 1); $match = array(); preg_match('/["\' ]groups["\' ]:\[{(.+?)}\]/', $re['body'], $match); if(count($match) != 2) { return ""; } $match[1] = "[{". $match[1]. "}]"; return json_decode($match[1], 1); } /** * 获取fakeid * @param $pageNum 每页显示数量 * @return array Array ( [0] => Array ( [id] => 2858907422 //fakeid [nick_name] => 黄海 //昵称 [remark_name] => //备注 [group_id] => 0 //分组ID ) ) */ public function getFakeid($pageNum){ $url = "https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize={$pageNum}&pageidx=0&type=0&token={$this->webToken}&lang=zh_CN"; $re = $this->get($url, $this->cookie); preg_match('/["\' ]contacts["\' ]:\[{(.+?)}\]/', $re['body'], $match); if(count($match) != 2) { return ""; } $match[1] = "[{". $match[1]. "}]"; return json_decode($match[1], 1); } /** * 返回array(cookie=>, body=>) * @param string $url url地址 * @param array $data 提交的数据 * @param boolean $cookie * @param boolean $isPost * @return array */ private function exec($url, $data, $cookie = false, $isPost = true) { $dataStr = ""; if($data && is_array($data)) { foreach($data as $key => $value) { $dataStr .= "$key=$value&"; } } $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 // curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer $referer = "https://mp.weixin.qq.com/cgi-bin/singlemsgpage"; $oldReferer = "https://mp.weixin.qq.com/"; curl_setopt($curl, CURLOPT_HTTPHEADER, array("Referer:$referer")); if($isPost) { curl_setopt($curl, CURLOPT_POST, 0); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $dataStr); // Post提交的数据包 } curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制 防止死循环 curl_setopt($curl, CURLOPT_HEADER, 1); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 // curl_setopt($curl, CURLOPT_COOKIEFILE, 'cookie.txt'); // curl_setopt($curl, CURLOPT_COOKIEJAR, 'cookie.txt'); // curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // curl_setopt($curl, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt'); if($cookie) { curl_setopt($curl, CURLOPT_COOKIE, $cookie); } $tmpInfo = curl_exec($curl); // 执行操作 if (curl_errno($curl)) { echo 'Errno'. curl_error($curl);//捕抓异常 return; } curl_close($curl); // 关闭CURL会话 // 解析HTTP数据流 list($header, $body) = explode("\r\n\r\n", $tmpInfo); if(!$cookie) { // 解析COOKIE $cookie = ""; preg_match_all("/set\-cookie: (.*)/i", $header, $matches); if(count($matches) == 2) { foreach($matches[1] as $each) { $cookie .= trim($each). ";"; } } } return array("cookie" => $cookie, "body" => trim($body)); } //post方式调用curl function submit($url, $data, $cookie = false) { return $this->exec($url, $data, $cookie); } //get方式调用curl function get($url, $cookie) { return $this->exec($url, '', $cookie, false); } }