微信公共平台私有sdk實現獲取fakeid的構想與實現


    看到那么多人瀏覽,沒有回復,肯定是自己寫的太爛了,現在在做畢業論文,做完了,一定重新寫一下,微信公共平台大家還是很感興趣的,嘿嘿。期待留言指教!!!

      大家好,我很少原創,只因太菜,最近在研究微信api,說到這先講一個笑話:

話說西蜀劉備去世之后,托孤阿斗於諸葛孔明,孔明為報知遇之恩,興師北伐中原。臨行之前對阿斗說:“陛下聰慧機智,才藝超群,但缺威信”。阿斗回到:“這好辦,讓我注冊一個微信,昵稱:諸葛亮”。

       還是扯正經的,微信api這個相信關注這篇博客的同志們都已經很熟悉了,這里只是和大家一起探討一些官方api以外的想法。騰訊宣布開放的公共平台api,其實還是不夠開放,至少目前是這樣,像一些比較強大和需要的api就沒有對外開放,比如:訂閱(這個騰訊自家的dnspod就有內部接口,看着很好用)、獲取關注用戶fakeid ,主動發送消息。這里嘗試通過模擬調用網頁版的官方公共平台管理系統去封裝實現盡可能多的功能。

       先放出我的參考網上其他牛人資料封裝的類庫 https://github.com/ligboy/Wechat-php

           先說一下思路,首先在訂閱事件的回復中加入一個身份識別瑪,比如openid的16位的md5散列,附在歡迎回復內容的最后,其實不會顯得不美觀和突兀。

 1      
 2 
 3                     case "subscribe":
 4                         $subscribeusersModel = D("Subscribeusers");  //thinkphp中數據庫模型
 5                         $condition['openid'] = $this->wechatObj->getRevFrom();  //得到關注用戶的openid
 6                         $data = $subscribeusersModel->where($condition)->select();
 7                         if (!$data)
 8                         {
 9                             $subscribeusersModel->add($condition); 
10                         }
11                         elseif($data[0]['unsubscribed']=="1")
12                         {
13                             $subscribeusersModel->where($condition)->save(array('unsubscribed'=>0,'subscribetime'=>time()));
14                         }
15                         else
16                         {
17                             
18                         }
19                         //傳說中的識別碼
20                         $indentifyText = substr(md5($this->wechatObj->getRevFrom()), 0, 16);
21                         $this->wechatObj->text("歡迎您關注福大人,我們會用心為您服務。\n    福大人工作室"."\n".$indentifyText)->reply();
22                         break;

 

 

           然后通過一個定期定期執行的任務去檢索數據庫中字段fakeid為空的訂閱用戶的列表,同時通過整合的網頁微信公共平台接口去獲取當前未分組用戶列表和他們在最近一小時的聊天紀錄內容,然后通過foreach檢索某個openid的是否匹配某個用戶的消息,如果匹配,則更新該openid用戶的fakeid為當前fakeid,並把當前用戶移動到一個確定分組內。

 

實現代碼:

 

getfakeid
 1     /**
 2      * 得到制定分組的用戶列表
 3      * @param number $groupid
 4      * @return Ambigous <boolean, string, mixed>
 5      */
 6     public function getfriendlist($groupid=0)
 7     {
 8         $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/contactmanagepage?token=$this->webtoken&t=wxm-friend&pagesize=100&groupid=$groupid";
 9         $referer = $this->protocol."://mp.weixin.qq.com/";
10         $response = $this->get($url, $referer);
11         $tmp = "";
12         if (preg_match('%<script id="json-friendList" type="json/text">([\s\S]*?)</script>%', $response, $match)) {
13             $tmp = json_decode($match[1], true);
14         }
15         return empty($tmp)?false:$tmp;
16         
17     }
18     
19 
20     /**
21      * 獲取用戶的fakeid
22      * @param callback $callback 處理匹配結果的回調函數
23      */
24     public function getfakeid($callback)
25     {
26         $subscribeusersModel = D("Subscribeusers");
27         $data = $subscribeusersModel->where(' `fakeid` IS NULL and `unsubscribed`=0')->select();
28         if (!is_array($data))
29         {
30             die("none data");
31         }
32         $unfriendList = $this->getfriendlist(0);
33         if (!$unfriendList){
34             die("none friendlist");
35         }
36         $requestArray = array();
37         foreach ($unfriendList as $key => $value)
38         {
39 //             $requestArray[$key]['postfields']['createtime'] = time()-60000;
40             $requestArray[$key]['postfields']['fromfakeid'] = $value['fakeId'];
41             $requestArray[$key]['postfields']['opcode'] = 1;
42             $requestArray[$key]['postfields']['token'] = $this->webtoken;
43             $requestArray[$key]['postfields']['ajax'] = 1;
44             $requestArray[$key]['referer'] = $this->protocol."://mp.weixin.qq.com/";
45             $requestArray[$key]['cookiefilepath'] = $this->cookiefilepath;
46             $requestArray[$key]['method'] = "post";            
47             $requestArray[$key]['url'] = $this->protocol."://mp.weixin.qq.com/cgi-bin/singlemsgpage?t=ajax-single-getnewmsg";
48         }
49 //         $callback = '';
50         $rollingCurlObj = new Rollingcurl();
51         $rollingCurlObj->setOtherCallbackArg(array('data'=>$data, 'wechatObj'=>$this));
52         $response = $rollingCurlObj->setCallback($callback)->request($requestArray);
53         dump($response);
54     }
55     
56     /**
57      * 將用戶放入制定的分組
58      * @param array $fakeidsList
59      * @param string $groupid
60      * @return boolean 放入是否成功
61      */
62     public function putIntoGroup($fakeidsList, $groupid)
63     {
64         $fakeidsListString = "";
65         if(is_array($fakeidsList))
66         {
67             foreach ($fakeidsList as $value)
68             {
69                 $fakeidsListString .= $value."|";
70             }
71         }
72         else
73         {
74             $fakeidsListString = $fakeidsList;
75         }
76         $postfields['contacttype'] = $groupid;
77         $postfields['tofakeidlist'] = $fakeidsListString;
78         $postfields['token'] = $this->webtoken;
79         $postfields['ajax'] = 1;
80         $referer = $this->protocol."://mp.weixin.qq.com/";
81         $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/modifycontacts?action=modifycontacts&t=ajax-putinto-group";
82         $response = $this->post($url, $postfields, $referer);
83         $tmp = json_decode($response, true);
84         $result = $tmp['ret']=="0"&&!empty($tmp)?true:false;
85         return $result;
86     }

 

 

最下面附上全部代碼:

 

Wechat.class.php
   1 <?php
   2 /**
   3  * 微信公共平台整合庫
   4  * @author Ligboy (ligboy@gmail.com)
   5  * @license 本庫的很多思路來自於網上的其他熱心人士的貢獻,大家任意使用,我本人放棄所有權利,如果您心情好,給我留個署名也行。
   6  *
   7  */
   8 class Wechat {
   9     /* 配置參數  */
  10     /**
  11      *
  12      * @var array
  13      * @example array('token'=>'微信接口密鑰','account'=>'微信公共平台賬號','password'=>'微信公共平台密碼','webtoken'=>"微信公共平台網頁url的token");
  14      */
  15     private $wechatOptions=array('token'=>'rqerwer','account'=>'ligboy@gmail.com','password'=>'wwwwww');    //
  16     private $cookiefilepath = ""; //以文件形式保存cookie的保存目錄,肯定是可寫的
  17     public $webtoken = '742432903';  
  18     private $webtokenStoragefile = "";  //微信公共平台的token存儲文件,就是公共平后台網頁的token
  19     public $debug =  true;  //調試開關
  20     public $protocol = "https";  //使用協議類型 http or  https
  21 
  22     /* 靜態常量 */
  23     const MSGTYPE_TEXT = 'text';
  24     const MSGTYPE_IMAGE = 'image';
  25     const MSGTYPE_LOCATION = 'location';
  26     const MSGTYPE_LINK = 'link';
  27     const MSGTYPE_EVENT = 'event';
  28     const MSGTYPE_MUSIC = 'music';
  29     const MSGTYPE_NEWS = 'news';
  30     const MSGTYPE_VOICE = 'voice';
  31 
  32     /* 私有參數 */
  33     private $_msg;
  34     private $_funcflag = false;
  35     private $_receive;
  36     private $_logcallback;
  37     private $_token;
  38     private $_cookies;
  39     private $_tmp1;
  40     private $_tmp2;
  41     
  42 
  43 
  44     /**
  45      * 初始化工作
  46      * @param array $option  array('token'=>'微信接口密鑰','account'=>'微信公共平台賬號','password'=>'微信公共平台密碼');
  47      */
  48     function __construct($option=array())
  49     {
  50         if (!empty($option))
  51         {
  52             $this->wechatOptions = array_merge($this->wechatOptions, $option);
  53         }
  54         $this->setCookiefilepath("./app/Runtime", "wechatcookies".md5($this->wechatOptions['account']).".txt");
  55         if ($this->webtokenStoragefile) {
  56             $this->webtoken = (string)file_get_contents($this->webtokenStoragefile);
  57         }
  58         
  59 
  60     }
  61 
  62     /**
  63      * 驗證請求簽名操作
  64      * @return boolean
  65      */
  66     private function checkSignature()
  67     {
  68         $signature = $_GET["signature"];
  69         $timestamp = $_GET["timestamp"];
  70         $nonce = $_GET["nonce"];
  71 
  72         $token = $this->wechatOptions['token'];
  73         $tmpArr = array($token, $timestamp, $nonce);
  74         sort($tmpArr);
  75         $tmpStr = implode( $tmpArr );
  76         $tmpStr = sha1( $tmpStr );
  77 
  78         if( $tmpStr == $signature )
  79         {
  80             return true;
  81         }
  82         else
  83         {
  84             return false;
  85         }
  86     }
  87 
  88     /**
  89      * 驗證當前請求是否有效
  90      * @param bool $return 是否返回
  91      */
  92     public function valid($return=false)
  93     {
  94         $echoStr = isset($_GET["echostr"]) ? $_GET["echostr"]: '';
  95         if ($return)
  96         {
  97             if ($echoStr)
  98             {
  99                 if ($this->checkSignature())
 100                 {
 101                     return $echoStr;
 102                 }
 103                 else
 104                 {
 105                     return false;
 106                 }
 107             } else
 108                 return $this->checkSignature();
 109         }
 110         else
 111         {
 112             if ($echoStr)
 113             {
 114                 if ($this->checkSignature())
 115                 {
 116                     die($echoStr);
 117                 }
 118                 else
 119                 {
 120                     die('no access');
 121                 }
 122             }
 123             else
 124             {
 125                 if ($this->checkSignature())
 126                 {
 127                     return true;
 128                 }
 129                 else
 130                 {
 131                     die('no access');
 132                 }
 133             }
 134         }
 135         return false;
 136     }
 137 
 138 
 139     /**
 140      * 設置發送消息
 141      * @param array $msg 消息數組
 142      * @param bool $append 是否在原消息數組追加
 143      */
 144     public function Message($msg = '',$append = false){
 145         if (is_null($msg)) {
 146             $this->_msg =array();
 147         }elseif (is_array($msg)) {
 148             if ($append)
 149                 $this->_msg = array_merge($this->_msg,$msg);
 150             else
 151                 $this->_msg = $msg;
 152             return $this->_msg;
 153         } else {
 154             return $this->_msg;
 155         }
 156     }
 157 
 158     public function setFuncFlag($flag) {
 159         $this->_funcflag = $flag;
 160         return $this;
 161     }
 162 
 163     private function log($log){
 164         if ($this->debug && function_exists($this->_logcallback)) {
 165             if (is_array($log)) $log = print_r($log,true);
 166             return call_user_func($this->_logcallback,$log);
 167         }
 168     }
 169 
 170     /**
 171      * 獲取微信服務器發來的信息
 172      * @return mixed
 173      */
 174     public function getRev()
 175     {
 176         $postStr = file_get_contents("php://input");
 177         $this->log($postStr);
 178         if (!empty($postStr)) {
 179             $this->_receive = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
 180 
 181             //debug 調試記錄回復信息
 182             if ($this->debug){file_put_contents($this->debugpath."./rev.txt","\n---".date('Y-m-d H:i:s')."\n".print_r($this->_receive, true),FILE_APPEND);}
 183                 
 184         }
 185         return $this;
 186     }
 187 
 188     /**
 189      * 獲取消息發送者
 190      * @return string or boolean
 191      */
 192     public function getRevFrom() {
 193         if ($this->_receive)
 194             return $this->_receive['FromUserName'];
 195         else
 196             return false;
 197     }
 198 
 199     /**
 200      * 獲取消息接受者
 201      * @return string or boolean
 202      */
 203     public function getRevTo() {
 204         if ($this->_receive)
 205             return $this->_receive['ToUserName'];
 206         else
 207             return false;
 208     }
 209 
 210     /**
 211      * 獲取接收消息的類型
 212      */
 213     public function getRevType() {
 214         if (isset($this->_receive['MsgType']))
 215             return $this->_receive['MsgType'];
 216         else
 217             return false;
 218     }
 219 
 220     /**
 221      * 獲取消息ID
 222      */
 223     public function getRevID() {
 224         if (isset($this->_receive['MsgId']))
 225             return $this->_receive['MsgId'];
 226         else
 227             return false;
 228     }
 229 
 230     /**
 231      * 獲取消息發送時間
 232      */
 233     public function getRevCtime() {
 234         if (isset($this->_receive['CreateTime']))
 235             return $this->_receive['CreateTime'];
 236         else
 237             return false;
 238     }
 239 
 240     /**
 241      * 獲取接收消息內容正文
 242      */
 243     public function getRevContent(){
 244         if (isset($this->_receive['Content']))
 245             return $this->_receive['Content'];
 246         else
 247             return false;
 248     }
 249 
 250     /**
 251      * 獲取接收消息圖片
 252      */
 253     public function getRevPic(){
 254         if (isset($this->_receive['PicUrl']))
 255             return $this->_receive['PicUrl'];
 256         else
 257             return false;
 258     }
 259 
 260     /**
 261      * 獲取接收消息鏈接
 262      */
 263     public function getRevLink(){
 264         if (isset($this->_receive['Url'])){
 265             return array(
 266                     'url'=>$this->_receive['Url'],
 267                     'title'=>$this->_receive['Title'],
 268                     'description'=>$this->_receive['Description']
 269             );
 270         } else
 271             return false;
 272     }
 273 
 274     /**
 275      * 獲取接收地理位置
 276      * @return array('x'=>'','y'=>'','scale'=>'','label'=>'')
 277      */
 278     public function getRevGeo(){
 279         if (isset($this->_receive['Location_X'])){
 280             return array(
 281                     'x'=>$this->_receive['Location_X'],
 282                     'y'=>$this->_receive['Location_Y'],
 283                     'scale'=>$this->_receive['Scale'],
 284                     'label'=>$this->_receive['Label']
 285             );
 286         } else
 287             return false;
 288     }
 289 
 290     /**
 291      * 獲取接收事件推送
 292      * @return array 成功返回事件數組,失敗返回false
 293      */
 294     public function getRevEvent(){
 295         if (isset($this->_receive['Event'])){
 296             return array(
 297                     'event'=>$this->_receive['Event'],
 298                     'key'=>$this->_receive['EventKey'],
 299             );
 300         } else
 301             return false;
 302     }
 303 
 304     /**
 305      * 獲取接收語言推送
 306      * @return 
 307      */
 308     public function getRevVoice(){
 309         if (isset($this->_receive['MediaId'])){
 310             return array(
 311                     'mediaid'=>$this->_receive['MediaId'],
 312                     'format'=>$this->_receive['Format'],
 313             );
 314         } else
 315             return false;
 316     }
 317 
 318     public static function xmlSafeStr($str)
 319     {
 320         return '<![CDATA['.preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/",'',$str).']]>';
 321     }
 322 
 323     /**
 324      * 數據XML編碼
 325      * @param mixed $data 數據
 326      * @return string
 327      */
 328     public static function data_to_xml($data) {
 329         $xml = '';
 330         foreach ($data as $key => $val) {
 331             is_numeric($key) && $key = "item id=\"$key\"";
 332             $xml    .=  "<$key>";
 333             $xml    .=  ( is_array($val) || is_object($val)) ? self::data_to_xml($val)  : self::xmlSafeStr($val);
 334             list($key, ) = explode(' ', $key);
 335             $xml    .=  "</$key>";
 336         }
 337         return $xml;
 338     }
 339 
 340     /**
 341      * XML編碼
 342      * @param mixed $data 數據
 343      * @param string $root 根節點名
 344      * @param string $item 數字索引的子節點名
 345      * @param string $attr 根節點屬性
 346      * @param string $id   數字索引子節點key轉換的屬性名
 347      * @param string $encoding 數據編碼
 348      * @return string
 349      */
 350     public function xml_encode($data, $root='xml', $item='item', $attr='', $id='id', $encoding='utf-8') {
 351         if(is_array($attr)){
 352             $_attr = array();
 353             foreach ($attr as $key => $value) {
 354                 $_attr[] = "{$key}=\"{$value}\"";
 355             }
 356             $attr = implode(' ', $_attr);
 357         }
 358         $attr   = trim($attr);
 359         $attr   = empty($attr) ? '' : " {$attr}";
 360         $xml   .= "<{$root}{$attr}>";
 361         $xml   .= self::data_to_xml($data, $item, $id);
 362         $xml   .= "</{$root}>";
 363         return $xml;
 364     }
 365 
 366     /**
 367      * 設置回復消息
 368      * Examle: $obj->text('hello')->reply();
 369      * @param string $text
 370      */
 371     public function text($text='')
 372     {
 373         $FuncFlag = $this->_funcflag ? 1 : 0;
 374         $msg = array(
 375                 'ToUserName' => $this->getRevFrom(),
 376                 'FromUserName'=>$this->getRevTo(),
 377                 'MsgType'=>self::MSGTYPE_TEXT,
 378                 'Content'=>$text,
 379                 'CreateTime'=>time(),
 380                 'FuncFlag'=>$FuncFlag
 381         );
 382         $this->Message($msg);
 383         return $this;
 384     }
 385 
 386     /**
 387      * 設置回復音樂
 388      * @param string $title
 389      * @param string $desc
 390      * @param string $musicurl
 391      * @param string $hgmusicurl
 392      */
 393     public function music($title,$desc,$musicurl,$hgmusicurl='') {
 394         $FuncFlag = $this->_funcflag ? 1 : 0;
 395         $msg = array(
 396                 'ToUserName' => $this->getRevFrom(),
 397                 'FromUserName'=>$this->getRevTo(),
 398                 'CreateTime'=>time(),
 399                 'MsgType'=>self::MSGTYPE_MUSIC,
 400                 'Music'=>array(
 401                         'Title'=>$title,
 402                         'Description'=>$desc,
 403                         'MusicUrl'=>$musicurl,
 404                         'HQMusicUrl'=>$hgmusicurl
 405                 ),
 406                 'FuncFlag'=>$FuncFlag
 407         );
 408         $this->Message($msg);
 409         return $this;
 410     }
 411 
 412     /**
 413      * 設置回復圖文
 414      * @param array $newsData
 415      * @example 數組結構:
 416      *  array(
 417      *      [0]=>array(
 418      *          'Title'=>'msg title',
 419      *          'Description'=>'summary text',
 420      *          'PicUrl'=>'http://www.domain.com/1.jpg',
 421      *          'Url'=>'http://www.domain.com/1.html'
 422      *      ),
 423      *      [1]=>....
 424      *  )
 425      */
 426     public function news($newsData=array())
 427     {
 428         $FuncFlag = $this->_funcflag ? 1 : 0;
 429         $count = count($newsData);
 430 
 431         $msg = array(
 432                 'ToUserName' => $this->getRevFrom(),
 433                 'FromUserName'=>$this->getRevTo(),
 434                 'MsgType'=>self::MSGTYPE_NEWS,
 435                 'CreateTime'=>time(),
 436                 'ArticleCount'=>$count,
 437                 'Articles'=>$newsData,
 438                 'FuncFlag'=>$FuncFlag
 439         );
 440         $this->Message($msg);
 441         return $this;
 442     }
 443 
 444     /**
 445      *
 446      * 向微信服務器回復消息
 447      * Example: $this->text('msg tips')->reply();
 448      * @param string $msg 要發送的信息, 默認取$this->_msg
 449      * @param bool $return 是否返回信息而輸出  默認:false
 450      */
 451     public function reply($msg=array(),$return = false)
 452     {
 453         if (empty($msg))
 454         {
 455             $msg = $this->_msg;
 456         }
 457         $xmldata=  $this->xml_encode($msg);
 458         $this->log($xmldata);
 459         if ($return)
 460         {
 461             return $xmldata;
 462         }
 463         else
 464         {
 465             echo $xmldata;
 466         }
 467         //debug 調試記錄回復信息
 468         if ($this->debug){file_put_contents($this->debugpath."./reply.txt","\n---".date('Y-m-d H:i:s')."\n".$xmldata,FILE_APPEND);}
 469     }
 470 
 471 
 472     /**
 473      * 登錄微信公共平台,獲取並保存cookie、webtoken到指定文件
 474      * @return mixed 成功則返回true,失敗則返回失敗
 475      */
 476     public function login(){
 477         $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN";
 478         $postfields["username"] = $this->wechatOptions['account'];
 479         $postfields["pwd"] = md5($this->wechatOptions['password']);
 480         $postfields["f"] = "json";
 481         $postfieldss = "username=".urlencode($this->wechatOptions['account'])."&pwd=".urlencode(md5($this->wechatOptions['password']))."&f=json";
 482         $response = $this->post($url, $postfields, $this->protocol."://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN");
 483         $result = json_decode($response, true);
 484         if ($result['ErrCode']=="65201"||$result['ErrCode']=="65202"||$result['ErrCode']=="0")
 485         {
 486             preg_match('/&token=([\d]+)/i', $result['ErrMsg'],$match);
 487             file_put_contents($this->webtokenStoragefile, $match[1]);
 488             $this->webtoken = $match[1];
 489             return true;
 490         }
 491         else
 492         {
 493             unlink($this->cookiefilepath);
 494             return false;
 495 //             return $result['ErrCode'];
 496         }
 497     }
 498 
 499     /**
 500      * 讀取緩存的cookies文件
 501      * @param  string $filename 文件名
 502      * @param  string $content  文件內容
 503      * @return [type]           [description]
 504      */
 505     public function readFileCookies(){
 506 
 507         if(file_exists($this->cookiefilepath)){
 508             $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/getregions?id=1054&t=ajax-getregions&lang=zh_CN&token=".$this->webtoken;
 509             $response = $this->get($url, $this->protocol."://mp.weixin.qq.com/");
 510             $result = json_decode($response,true);
 511             if($result['num'])
 512             {
 513                 return true;
 514             }
 515             else
 516             {
 517                 return true===$this->login();
 518             }
 519         }
 520         else
 521         {
 522             return true===$this->login();
 523         }
 524     }
 525 
 526     /**
 527      * 驗證cookie的有效性
 528      * @return boolean
 529      */
 530     public function checkValid()
 531     {
 532         $postfields = array();
 533         $url = $this->protocol.":https://mp.weixin.qq.com/cgi-bin/getregions?id=1054&t=ajax-getregions&lang=zh_CN&token=".$this->webtoken;
 534         //判斷cookie是否為空,為空的話自動執行登錄
 535         if (file_exists($this->cookiefilepath))
 536         {
 537             $response = $this->get($url, $this->protocol."://mp.weixin.qq.com/cgi-bin/userinfopage?t=wxm-setting&token=383506232&lang=zh_CN");
 538             $result = json_decode($response,1);
 539             if(isset($result['num'])){
 540                 return true;
 541             }else{
 542                 return false;
 543             }
 544         }
 545         else
 546         {
 547             return false;
 548         }
 549     }
 550 
 551     /**
 552      * 主動單條發消息
 553      * @param  string $id      用戶的fakeid
 554      * @param  string $content 發送的內容
 555      * @return boolean 返回發送結果:成功返回:1,登錄問題返回:-1,其他原因返回:0
 556      */
 557     public function send($fakeid,$content)
 558     {
 559         //判斷cookie是否為空,為空的話自動執行登錄
 560         if (file_exists($this->cookiefilepath)||true===$this->login())
 561         {
 562             $postfields = array();
 563             $postfields['tofakeid'] = $fakeid;
 564             $postfields['type'] = 1;
 565             $postfields['error']= "false";
 566             $postfields['token']= $this->webtoken;
 567             $postfields['content'] = $content;
 568             $postfields['ajax'] = 1;
 569             $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response";
 570             $response = $this->post($url, $postfields, $this->protocol."://mp.weixin.qq.com/");
 571             $tmp = json_decode($response,true);
 572             //判斷發送結果的邏輯部分
 573             if ('ok'==$tmp["msg"]) {
 574                 return 1;
 575             }
 576             elseif ($tmp['ret']=="-2000")
 577             {
 578                 return -1;
 579             }
 580             else
 581             {
 582                 return false;
 583             }
 584         }
 585         else  //登錄失敗返回false
 586         {
 587             return false;
 588         }
 589     }
 590 
 591     /**
 592      * 主動批量發送,目前暫支持文本方式
 593      * @param  array $fakeidGroup     接受微信fakeid集合數組
 594      * @param  [type] $content [description]
 595      * @return mixed  如果所有都發送失敗,返回false,否則,返回一個數組分別記錄成功的列表
 596      * 這里需要注意請求耗時問題,目前采用curl並發性請求,並發請求數10個
 597      */
 598     public function batSend($fakeidGroup,$content)
 599     {
 600         $result = array();
 601         $successCount = 0;
 602         $requestArray = array();
 603         foreach ($fakeidGroup as $key =>$value)
 604         {
 605             $postfields = array();
 606             $postfields['tofakeid'] = $value;
 607             $postfields['type'] = 1;
 608             $postfields['error']= "false";
 609             $postfields['token']= $this->webtoken;
 610             $postfields['content'] = $content;
 611             $postfields['ajax'] = 1;
 612             $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response";
 613             $requestArray[] = array('url'=>$url,'method'=>'post','postfields'=>$postfields,'referer'=>$this->protocol."://mp.weixin.qq.com/",'cookiefilepath'=>$this->cookiefilepath);
 614         }
 615         //DEBUG: 
 616 //         dump($requestArray);
 617         $callback = function ($result, $key){
 618             $tmp = json_decode($result,true);
 619             //判斷發送結果的邏輯部分
 620             if ('ok'==$tmp["msg"]) {
 621                 return 1;
 622             }
 623             elseif ($tmp['ret']=="-2000")
 624             {
 625                 return -1;
 626             }
 627             else
 628             {
 629                 return 0;
 630             }
 631         };
 632         $rollingCurlObj = new Rollingcurl();
 633         $response = $rollingCurlObj->setCallback($callback)->request($requestArray);
 634         return $response;
 635     }
 636 
 637     /**
 638      * 獲取用戶的信息
 639      * @param  string $fakeid 用戶的fakeid
 640      * @return mixed 如果成功獲取返回數據數組,登錄問題返回false,其他未知問題返回true,
 641      */
 642     public function getContactInfo($fakeid)
 643     {
 644         if (file_exists($this->cookiefilepath)||true===$this->login())
 645         {
 646             $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/getcontactinfo?t=ajax-getcontactinfo&lang=zh_CN&fakeid=".$fakeid;
 647             $response = $this->get($url, $this->protocol."://mp.weixin.qq.com/");
 648             $result = json_decode($response,1);
 649             if($result['FakeId']){
 650                 return $result;
 651             }
 652             elseif ($result['ret'])
 653             {
 654                 return false;
 655             }
 656             else
 657             {
 658                 return true;
 659             }
 660         }
 661         else
 662         {
 663             return false;
 664         }
 665     }
 666     
 667 
 668     public function getfriendlist($groupid=0)
 669     {
 670         $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/contactmanagepage?token=$this->webtoken&t=wxm-friend&pagesize=100&groupid=$groupid";
 671         $referer = $this->protocol."://mp.weixin.qq.com/";
 672         $response = $this->get($url, $referer);
 673         $tmp = "";
 674         if (preg_match('%<script id="json-friendList" type="json/text">([\s\S]*?)</script>%', $response, $match)) {
 675             $tmp = json_decode($match[1], true);
 676         }
 677         return empty($tmp)?false:$tmp;
 678         
 679     }
 680     
 681 
 682     public function getfakeid($callback)
 683     {
 684         $subscribeusersModel = D("Subscribeusers");
 685         $data = $subscribeusersModel->where(' `fakeid` IS NULL and `unsubscribed`=0')->select();
 686         if (!is_array($data))
 687         {
 688             die("none data");
 689         }
 690         $unfriendList = $this->getfriendlist(0);
 691         if (!$unfriendList){
 692             die("none friendlist");
 693         }
 694         $requestArray = array();
 695         foreach ($unfriendList as $key => $value)
 696         {
 697 //             $requestArray[$key]['postfields']['createtime'] = time()-60000;
 698             $requestArray[$key]['postfields']['fromfakeid'] = $value['fakeId'];
 699             $requestArray[$key]['postfields']['opcode'] = 1;
 700 //             $requestArray[$key]['postfields']['lastmsgid'] = 0;
 701 //             $requestArray[$key]['lastmsgfromfakeid']['2399396672'] = 2399396672;
 702             $requestArray[$key]['postfields']['token'] = $this->webtoken;
 703             $requestArray[$key]['postfields']['ajax'] = 1;
 704             $requestArray[$key]['referer'] = $this->protocol."://mp.weixin.qq.com/";
 705             $requestArray[$key]['cookiefilepath'] = $this->cookiefilepath;
 706             $requestArray[$key]['method'] = "post";            
 707             $requestArray[$key]['url'] = $this->protocol."://mp.weixin.qq.com/cgi-bin/singlemsgpage?t=ajax-single-getnewmsg";
 708         }
 709 //         $callback = '';
 710         $rollingCurlObj = new Rollingcurl();
 711         $rollingCurlObj->setOtherCallbackArg(array('data'=>$data, 'wechatObj'=>$this));
 712         $response = $rollingCurlObj->setCallback($callback)->request($requestArray);
 713         dump($response);
 714     }
 715     
 716     /**
 717      * 將用戶放入制定的分組
 718      * @param array $fakeidsList
 719      * @param string $groupid
 720      * @return boolean 放入是否成功
 721      */
 722     public function putIntoGroup($fakeidsList, $groupid)
 723     {
 724         $fakeidsListString = "";
 725         if(is_array($fakeidsList))
 726         {
 727             foreach ($fakeidsList as $value)
 728             {
 729                 $fakeidsListString .= $value."|";
 730             }
 731         }
 732         else
 733         {
 734             $fakeidsListString = $fakeidsList;
 735         }
 736         $postfields['contacttype'] = $groupid;
 737         $postfields['tofakeidlist'] = $fakeidsListString;
 738         $postfields['token'] = $this->webtoken;
 739         $postfields['ajax'] = 1;
 740         $referer = $this->protocol."://mp.weixin.qq.com/";
 741         $url = $this->protocol."://mp.weixin.qq.com/cgi-bin/modifycontacts?action=modifycontacts&t=ajax-putinto-group";
 742         $response = $this->post($url, $postfields, $referer);
 743         $tmp = json_decode($response, true);
 744         $result = $tmp['ret']=="0"&&!empty($tmp)?true:false;
 745         return $result;
 746     }
 747     
 748 
 749     /**
 750      * @return the $wechatOptions
 751      */
 752     public function getWechatOptions() {
 753         return $this->wechatOptions;
 754     }
 755 
 756     /**
 757      * @return the $cookiestoragemode
 758      */
 759     public final function getCookiestoragemode() {
 760         return $this->cookiestoragemode;
 761     }
 762 
 763     /**
 764      * @return the $cookiefilepath
 765      */
 766     public final function getCookiefilepath() {
 767         return $this->cookiefilepath;
 768     }
 769 
 770     /**
 771      * @return the $debug
 772      */
 773     public function getDebug() {
 774         return $this->debug;
 775     }
 776 
 777     /**
 778      * 設置webtoken的保存文件路徑和文件名
 779      * @return the $webtokenStoragefile
 780      */
 781     public function getWebtokenStoragefile() {
 782         return $this->webtokenStoragefile;
 783     }
 784 
 785     /**
 786      *  設置webtoken的保存文件路徑和文件名
 787      * @param string $webtokenStoragefile
 788      */
 789     public function setWebtokenStoragefile($webtokenStoragefile) {
 790         $this->webtokenStoragefile = $webtokenStoragefile;
 791         $this->webtoken = (string)file_get_contents($this->webtokenStoragefile);
 792     }
 793 
 794     /**
 795      * 設置微信配置信息
 796      * @param multitype:string  $wechatOptions
 797      */
 798     public function setWechatOptions($wechatOptions) {
 799         $this->wechatOptions = array_merge($this->wechatOptions, $wechatOptions);
 800     }
 801 
 802     /**
 803      * 設置cookie文件保存位置
 804      * @param string $cookiefilepath cookie保存路徑
 805      * @param string $cookiefilename 默認:wechatcookies".md5($this->wechatOptions['account']).".txt"
 806      */
 807     public function setCookiefilepath($cookiefilepath, $cookiefilename = "") {
 808         $this->cookiefilepath = $cookiefilepath.(substr($cookiefilepath, -1, 1)=="/"?"":"/").(is_null($cookiefilename))?"wechatcookies".md5($this->wechatOptions['account']).".txt":$cookiefilename;
 809     }
 810 
 811     /**
 812      * @param boolean $debug
 813      */
 814     public function setDebug($debug) {
 815         $this->debug = $debug;
 816     }
 817 
 818     private function post($url, $postfields, $referer)
 819     {
 820         $ch = curl_init($url);
 821         $options = array(
 822             CURLOPT_RETURNTRANSFER => true,         // return web page
 823             CURLOPT_HEADER         => false,        // don't return headers
 824             CURLOPT_FOLLOWLOCATION => true,         // follow redirects
 825             CURLOPT_ENCODING       => "",           // handle all encodings
 826             CURLOPT_USERAGENT      => "",     // who am i
 827             CURLOPT_AUTOREFERER    => true,         // set referer on redirect
 828             CURLOPT_CONNECTTIMEOUT => 120,          // timeout on connect
 829             CURLOPT_TIMEOUT        => 120,          // timeout on response
 830             CURLOPT_MAXREDIRS      => 10,           // stop after 10 redirects
 831             CURLOPT_POST            => true,            // i am sending post data
 832             CURLOPT_POSTFIELDS     => $postfields,    // this are my post vars
 833             CURLOPT_SSL_VERIFYHOST => 0,            // don't verify ssl
 834             CURLOPT_SSL_VERIFYPEER => false,        //
 835             CURLOPT_COOKIEFILE     =>$this->cookiefilepath,
 836             CURLOPT_COOKIEJAR      =>$this->cookiefilepath,
 837             CURLOPT_REFERER        =>$referer,
 838         );
 839         curl_setopt_array($ch, $options);
 840         $result = curl_exec($ch);
 841         curl_close($ch);
 842         return $result;
 843     }
 844 
 845     private function get($url, $referer)
 846     {
 847         $info = null;
 848         $ch = curl_init($url);
 849         $options = array(
 850                 CURLOPT_RETURNTRANSFER => true,         // return web page
 851                 CURLOPT_HEADER         => false,        // don't return headers
 852                 CURLOPT_FOLLOWLOCATION => true,         // follow redirects
 853                 CURLOPT_ENCODING       => "",           // handle all encodings
 854                 CURLOPT_USERAGENT      => "",     // who am i
 855                 CURLOPT_AUTOREFERER    => true,         // set referer on redirect
 856                 CURLOPT_CONNECTTIMEOUT => 120,          // timeout on connect
 857                 CURLOPT_TIMEOUT        => 120,          // timeout on response
 858                 CURLOPT_MAXREDIRS      => 10,           // stop after 10 redirects
 859                 CURLOPT_SSL_VERIFYHOST => 0,            // don't verify ssl
 860                 CURLOPT_SSL_VERIFYPEER => false,        //
 861                 CURLOPT_COOKIEFILE     =>$this->cookiefilepath,
 862                 CURLOPT_COOKIEJAR      =>$this->cookiefilepath,
 863                 CURLOPT_REFERER        =>$referer,
 864         );
 865         curl_setopt_array($ch, $options);
 866         $result = curl_exec($ch);
 867         curl_close($ch);
 868         return $result;
 869     }
 870 }
 871 
 872 
 873 /**
 874  * Rolling Curl Request Class
 875  * @author Ligboy (ligboy@gamil.com)
 876  * @copyright 
 877  * @example 
 878  * 
 879  *        
 880  */
 881 class Rollingcurl {
 882     private $limitCount = 10; //並發請求數量
 883     public $returninfoswitch = false;  //是否返回請求信息,開啟后單項請求返回結果為:array('info'=>請求信息, 'result'=>返回內容, 'error'=>錯誤信息)
 884     
 885     
 886     //私有屬性
 887     private $queue = null;
 888     private $_requstItems = null;
 889     private $_callback = null;
 890     private $_otherCallbackArg = null;
 891     private $_options = array(
 892                     CURLOPT_RETURNTRANSFER => true,         // return web page
 893                     CURLOPT_HEADER         => false,        // don't return headers
 894                     CURLOPT_FOLLOWLOCATION => true,         // follow redirects
 895                     CURLOPT_NOSIGNAL      =>true,
 896                     CURLOPT_TIMEOUT      =>true,
 897                     CURLOPT_ENCODING       => "",           // handle all encodings
 898                     CURLOPT_USERAGENT      => "",           // who am i
 899                     CURLOPT_AUTOREFERER    => true,         // set referer on redirect
 900                     CURLOPT_CONNECTTIMEOUT => 120,          // timeout on connect
 901                     CURLOPT_TIMEOUT        => 120,          // timeout on response
 902                     CURLOPT_MAXREDIRS      => 10,           // stop after 10 redirects
 903                     CURLOPT_SSL_VERIFYHOST => 0,            // don't verify ssl
 904                     CURLOPT_SSL_VERIFYPEER => false,        //
 905             );
 906     
 907     
 908     /**
 909      * 
 910      * @param array $options [可選的]公共的Curl請求參數
 911      */
 912     function __construct($options = array()) {
 913         $this->queue = curl_multi_init();
 914         if ($options) {
 915             array_merge($this->_options, $options);
 916         }
 917     }
 918     
 919 
 920     /**
 921      * 並發行的curl方法
 922      * @param unknown $requestArray
 923      * @param string $callback
 924      * @return multitype:multitype:
 925      */
 926     function request($requestArray, $callback="")
 927     {
 928         $this->_requstItems = $requestArray;
 929         $requestArrayKeys = array_keys($requestArray);
 930 /*         $requestArray = array(
 931                 array(
 932                         'url' => "",
 933                         'method' => "post",
 934                         'postfields' => array(),
 935                         'cookiefilepath' => "",
 936                         'cookiefilepath' => "",
 937                         'referer' => "",
 938                 ),
 939                 array(
 940                         'url' => "",
 941                         'postfields' => array(),
 942                         'cookiefilepath' => "",
 943                         'cookiefilepath' => "",
 944                         'referer' => "",
 945                 ),
 946         ); */
 947         $this->queue = curl_multi_init();
 948         $map = array();
 949         for ($i=0;$i<$this->limitCount && !empty($requestArrayKeys);$i++)
 950         {
 951             $keyvalue = array_shift($requestArrayKeys);
 952             $this->addToQueue ( $requestArray, $keyvalue, $map );
 953 
 954         }
 955     
 956         $responses = array();
 957         do {
 958             while (($code = curl_multi_exec($this->queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
 959     
 960             if ($code != CURLM_OK) { break; }
 961     
 962             // 找到剛剛完成的任務句柄
 963             while ($done = curl_multi_info_read($this->queue)) {
 964                 // 處理當前句柄的信息、錯誤、和返回內容
 965                 $info = curl_getinfo($done['handle']);
 966                 $error = curl_error($done['handle']);
 967                 if (is_callable($this->_callback))
 968                 {
 969                     $result = $this->callback ( $requestArray, $map, $done, $this->_otherCallbackArg );
 970 
 971                 }
 972                 else
 973                 {
 974                     //如果callback為空,直接返回內容
 975                     $result = curl_multi_getcontent($done['handle']);
 976                 }
 977                 if ($this->returninfoswitch) {
 978                     $responses[$map[(string) $done['handle']]] = compact('info', 'error', 'result');
 979                 }
 980                 else
 981                 {
 982                     $responses[$map[(string) $done['handle']]] = $result;
 983                 }
 984     
 985                 // 從隊列里移除上面完成處理的句柄
 986                 curl_multi_remove_handle($this->queue, $done['handle']);
 987                 curl_close($done['handle']);
 988                 if (!empty($requestArrayKeys))
 989                 {
 990                     $addkey = array_shift($requestArrayKeys);
 991                     $this->addToQueue ( $requestArray, $addkey, $map );
 992                 }
 993             }
 994     
 995             // Block for data in / output; error handling is done by curl_multi_exec
 996             if ($active > 0) {
 997                 curl_multi_select($this->queue, 0.5);
 998             }
 999     
1000         } while ($active);
1001     
1002         curl_multi_close($this->queue);
1003         return $responses;
1004     }
1005     /**
1006      * @param requestArray
1007      * @param map
1008      * @param done
1009      */private function callback($requestArray, $map, $done, $otherCallbackArg) {
1010         //調用callback函數處理當前句柄的返回內容,callback函數參數有:(返回內容, 隊列id)
1011         $result = call_user_func($this->_callback, curl_multi_getcontent($done['handle']), $map[(string) $done['handle']], $requestArray[$map[(string) $done['handle']]], $otherCallbackArg );
1012         return $result;
1013     }
1014 
1015     /**
1016      * @param requestArray
1017      * @param map
1018      * @param keyvalue
1019      */private function addToQueue($requestArray, $keyvalue, &$map) {
1020         $ch = curl_init();
1021         curl_setopt_array($ch, $this->_options);
1022         //檢查提交方式,並設置對應的設置,為空的話默認采用get方式
1023         if ("post" === $requestArray[$keyvalue]['method'])
1024         {
1025             curl_setopt($ch, CURLOPT_POST, true);
1026             curl_setopt($ch, CURLOPT_POSTFIELDS, $requestArray[$keyvalue]['postfields']);
1027         }
1028         else
1029         {
1030             curl_setopt($ch, CURLOPT_HTTPGET, true);
1031         }
1032 
1033         //設置cookie保存文件路徑
1034         if (!empty($requestArray[$keyvalue]['cookiefilepath']))
1035         {
1036             //如果這個文件存在,則采用采用此文件配置cookie
1037             if (file_exists($requestArray[$keyvalue]['cookiefilepath']))
1038             {
1039                 curl_setopt($ch, CURLOPT_COOKIEFILE, $requestArray[$keyvalue]['cookiefilepath']);
1040             }
1041             curl_setopt($ch, CURLOPT_COOKIEJAR, $requestArray[$keyvalue]['cookiefilepath']);
1042         }
1043         ////直接設定cookie。多個cookie用分號分隔,分號后帶一個空格(例如, "username=ligboy; password=123456; ")。
1044         if (!empty($requestArray[$keyvalue]['cookie']))
1045         {
1046             curl_setopt($ch, CURLOPT_COOKIE, $requestArray[$keyvalue]['cookie']);
1047         }
1048         curl_setopt($ch, CURLOPT_URL, $requestArray[$keyvalue]['url']);
1049         curl_setopt($ch, CURLOPT_REFERER, $requestArray[$keyvalue]['referer']);
1050         curl_multi_add_handle($this->queue, $ch);
1051         $map[(string) $ch] = $keyvalue;
1052     }
1053 
1054     /**
1055      * @return the $limitCount
1056      */
1057     public function getLimitCount() {
1058         return $this->limitCount;
1059     }
1060 
1061     /**
1062      * 設置並發性請求數量
1063      * @param number $limitCount
1064      */
1065     public function setLimitCount($limitCount) {
1066         $this->limitCount = $limitCount;
1067         return $this;
1068     }
1069 
1070     /**
1071      * 設置回調函數
1072      * @param field_type $_callback
1073      */
1074     public function setCallback($_callback) {
1075         $this->_callback = $_callback;
1076         return $this;
1077     }
1078     /**
1079      * @return the $_otherCallbackArg
1080      */
1081     public function getOtherCallbackArg() {
1082         return $this->_otherCallbackArg;
1083     }
1084 
1085     /**
1086      * @param field_type $_otherCallbackArg
1087      */
1088     public function setOtherCallbackArg($_otherCallbackArg) {
1089         $this->_otherCallbackArg = $_otherCallbackArg;
1090     }
1091 
1092 
1093     
1094 }

 

調用實例

調用實例
 1         date_default_timezone_set("Asia/Shanghai");
 2         import("@.Common.Wechat");
 3         $options = array(
 4                 'token'=>'*****',
 5                 'account'=>'ligboy@gmail.com',
 6                 'password'=>'******'
 7         );
 8         $this->wechatObj = new Wechat($options);
 9         $this->wechatObj->setCookiefilepath("./app/Runtime/");
10         $this->wechatObj->setWebtokenStoragefile("./app/Runtime/webtoken.txt");
11         print_r($this->wechatObj->login());
12         $callback = function ($result, $key, $request, $otherCallbackArg){
13             $reruen_tmp = false;
14             foreach ($otherCallbackArg['data'] as $data_key => $data_value)
15             {
16                 if(false !== strpos($result, substr(md5($data_value['openid']), 0, 16)))
17                 {
18                     $subscribeusersModel = D("Subscribeusers");
19                     $condition['openid'] = $data_value['openid'];
20                     $data = $subscribeusersModel->where($condition)->save(array('fakeid'=>$request['postfields']['fromfakeid']));
21                     $otherCallbackArg['wechatObj']->putIntoGroup($request['postfields']['fromfakeid'], 101);
22                     $reruen_tmp = $data_value['openid'];
23                     break;
24                 }
25             }
26             return $reruen_tmp;
27         };
28         print_r($this->wechatObj->getfakeid($callback));

 



 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM