网上微信的二次开发教程很多,通用的封装类也很多,但是唯独不好找到易信的通用类,虽然说易信的用户少,但也算是通信阵营的一份子把,博主借鉴了易信公共平台整合库,但是在作者的基础上做了修改,作者原来的是照搬微信的核心通用封装类,不过里面API有些错误,易信是没法调通的,所以我在作者重构了对应的代码,目前在项目中是通过扩展类的形式,给ThinkPHP框架用的之前的。Github的那位作者,如果你能看到这篇文章,请给我留言啊,我还没有提交给这份代码呢。[email protected]
本文转自:迅捷互动网络工作室 » 易信通用封装核心类
<?php class YixinChat { /* 配置参数 */ /* 静态常量 */ const MSGTYPE_TEXT = 'text'; const MSGTYPE_IMAGE = 'image'; const MSGTYPE_LOCATION = 'location'; const MSGTYPE_LINK = 'link'; const MSGTYPE_EVENT = 'event'; const MSGTYPE_MUSIC = 'music'; const MSGTYPE_NEWS = 'news'; const MSGTYPE_VOICE = 'voice'; const MSGTYPE_VIDEO = 'video'; const MSGTYPE_GOODS = 'goods'; const MSGTYPE_CARD = 'card'; const API_URL_PREFIX = 'https://api.yixin.im/cgi-bin'; const AUTH_URL = '/token?grant_type=client_credential&'; const MENU_CREATE_URL = '/menu/create?'; const MENU_GET_URL = '/menu/get?'; const MENU_DELETE_URL = '/menu/delete?'; /* 私有参数 */ private $_msg; private $_funcflag = false; public $_receive; private $_logcallback = null; private $token; private $appid; private $appsecret; private $access_token; public $debug = false; //调试开关 /** * 初始化工作 * @param array $options array('token'=>'易信接口密钥'); */ public function __construct($options=array()) { if (!empty($options)) { $this->token = isset($options['token'])?$options['token']:''; $this->appid = isset($options['appid'])?$options['appid']:''; $this->appsecret = isset($options['appsecret'])?$options['appsecret']:''; $this->debug = isset($options['debug'])?$options['debug']:false; $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false; } } /** * 验证请求签名操作 * @return boolean */ private function checkSignature() { $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $token = $this->token; $tmpArray = array($token, $timestamp, $nonce); sort($tmpArray); if(sha1(implode($tmpArray)) == $signature) { return true; } else { return false; } } /** * 验证当前请求是否有效(可选) * @param bool $return 是否返回 * @return bool|string */ public function valid($return=false) { $echoStr = isset($_GET["echostr"])?$_GET["echostr"]: ''; if ($return) { if ($echoStr) { if ($this->checkSignature()) { return $echoStr; } else { return false; } } else { return $this->checkSignature(); } } else { if ($echoStr) { if ($this->checkSignature()) { die($echoStr); } else { die('No Access'); } } else { if ($this->checkSignature()) { return true; } else { die('No Access'); } } } } /** * 设置发送消息 * @param array|string $msg 消息数组 * @param bool $append 是否在原消息数组追加 * @return array */ public function Message($msg = array(),$append = false){ if(is_array($msg)) { if ($append){ $this->_msg = array_merge($this->_msg,$msg); } else{ $this->_msg = $msg; } return $this->_msg; } else { return $this->_msg; } } /** * 设置星标 * @param $flag * @return $this */ public function setFuncFlag($flag) { $this->_funcflag = $flag; return $this; } /** * 调试信息日志日记录 * @param $log * @return mixed|null */ private function log($log){ if ($this->debug && function_exists($this->_logcallback)) { if (is_array($log)) $log = print_r($log,true); return call_user_func($this->_logcallback,$log); } return null; } /** * @name 获取易信服务器发来的信息 * @return mixed */ public function getRev() { $postStr = file_get_contents("php://input"); $this->log($postStr); if (!empty($postStr)) { $this->_receive = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); } return $this; } /** * 获取消息发送者 * @return string or boolean */ public function getRevFrom() { if ($this->_receive) { return $this->_receive['FromUserName']; } else { return false; } } /** * 获取消息接受者 * @return string or boolean */ public function getRevTo() { if ($this->_receive) { return $this->_receive['ToUserName']; } else { return false; } } /** * 获取接收消息的类型 */ public function getRevType() { if (isset($this->_receive['MsgType'])) { return $this->_receive['MsgType']; } else { return false; } } /** * 获取消息ID */ public function getRevID() { if (isset($this->_receive['MsgId'])) return $this->_receive['MsgId']; else return false; } /** * 获取消息发送时间 */ public function getRevCtime() { if (isset($this->_receive['CreateTime'])) { return $this->_receive['CreateTime']; } else{ return false; } } /** * 获取接收消息内容正文 */ public function getRevContent(){ if (isset($this->_receive['Content'])) { return $this->_receive['Content']; } else if (isset($this->_receive['Url'])) //获取语音地址,需申请开通 { return array( 'Url'=>$this->_receive['Url'], 'name'=>$this->_receive['name'], 'mimeType'=>$this->_receive['mimeType'] ); } else if (isset($this->_receive['url'])) //获取视频地址,需申请开通 { return array( 'url'=>$this->_receive['url'], 'name'=>$this->_receive['name'], 'mimeType'=>$this->_receive['mimeType'] ); } else{ return false; } } /** * 获取接收消息图片 */ public function getRevPic(){ if (isset($this->_receive['PicUrl'])){ return $this->_receive['PicUrl']; } else{ return false; } } /** * 获取接收消息链接 */ /** public function getRevLink(){ if (isset($this->_receive['Url'])) { return array( 'url'=>$this->_receive['Url'], 'title'=>$this->_receive['Title'], 'description'=>$this->_receive['Description'] ); } else{ return false; } } /** * 获取接收语音推送 * @return array|bool */ public function getRevVoice() { if ($this->_receive['MsgType']=='audio') { return array( 'Url'=>$this->_receive['Url'], 'name'=>$this->_receive['name'], 'mimeType'=>$this->_receive['mimeType'] ); } else { return false; } } /** * 获取接收地理位置 * @return array('x'=>'','y'=>'','scale'=>'','label'=>'') */ public function getRevGeo(){ if (isset($this->_receive['Location_X'])){ return array( 'x'=>$this->_receive['Location_X'], 'y'=>$this->_receive['Location_Y'], 'scale'=>$this->_receive['Scale'], 'label'=>$this->_receive['Label'] ); } else{ return false; } } /** * 获取上报地理位置事件 */ public function getRevEventGeo(){ if (isset($this->_receive['Latitude'])){ return array( 'x'=>$this->_receive['Latitude'], 'y'=>$this->_receive['Longitude'], 'precision'=>$this->_receive['Precision'], ); } else return false; } /** * 获取接收事件推送 * @return array 成功返回事件数组,失败返回false */ public function getRevEvent(){ if (isset($this->_receive['Event'])){ $array['Event'] = $this->_receive['Event']; } if (isset($this->_receive['EventKey'])){ $array['EventKey'] = $this->_receive['EventKey']; } if (isset($array) && count($array) > 0) { return $array; } else { return false; } } /** * 获取扫描带参数二维码事件 * * 事件类型为以下两种时则调用此方法有效 * Event 事件类型,subscribe * Event 事件类型,scan * * @return: array | false * array ( * 'EventKey'=>'', 事件类型subscribe时候,qrscene_为前缀,后面为二维码的参数值;事件类型scan时候,是一个32位无符号整数 * 'Ticket'=>'' * ) */ public function getRevScanInfo(){ if(isset($this->_receive['Event'])) { return array( 'EventKey'=>$this->_receive['EventKey'], 'Ticket'=>$this->_receive['Ticket'], ); } } /** * 获取接收TICKET */ public function getRevTicket(){ if (isset($this->_receive['Ticket'])){ return $this->_receive['Ticket']; } else return false; } /** * 获取二维码的场景值 */ public function getRevSceneId (){ if (isset($this->_receive['EventKey'])){ return str_replace('qrscene_','',$this->_receive['EventKey']); } else{ return false; } } /** * XML特殊字符过滤 * @param $str * @return string */ private static function xmlSafeStr($str) { return '<![CDATA['.preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/",'',$str).']]>'; } /** * 数据XML编码 * @param mixed $data 数据 * @return string */ private static function data_to_xml($data) { $xml = ''; foreach ($data as $key => $val) { is_numeric($key) && $key = "item"; $xml .= "<$key>"; $xml .= ( is_array($val) || is_object($val)) ? self::data_to_xml($val) : self::xmlSafeStr($val); list($key, ) = explode(' ', $key); $xml .= "</$key>"; } return $xml; } /** * XML编码 * @param mixed $data 数据 * @param string $root 根节点名 * @param string $item 数字索引的子节点名 * @param string $attr 根节点属性 * @param string $id 数字索引子节点key转换的属性名 * @return string */ private function xml_encode($data, $root='xml', $item='item', $attr='', $id='id') { if(is_array($attr)) { $_attr = array(); foreach ($attr as $key => $value) { $_attr[] = "{$key}=\"{$value}\""; } $attr = implode(' ', $_attr); } $attr = trim($attr); $attr = empty($attr) ? '' : " {$attr}"; $xml = null; $xml .= "<{$root}{$attr}>"; $xml .= self::data_to_xml($data); $xml .= "</{$root}>"; return $xml; } /** * 过滤文字回复\r\n换行符 * @param string $text * @return string|mixed */ private function _auto_text_filter($text) { if (!$this->_text_filter) return $text; return str_replace("\r\n", "\n", $text); } /***********************************************************************************************************************************************************/ /** * 设置回复消息 * Examle: $obj->text('hello')->reply(); * @param string $text * @return $this */ public function text($text='') { $FuncFlag = $this->_funcflag ? 1 : 0; $msg = array( 'ToUserName' => $this->getRevFrom(), 'FromUserName'=>$this->getRevTo(), 'MsgType'=>self::MSGTYPE_TEXT, 'Content'=>$text, 'CreateTime'=>time() ); $this->Message($msg); return $this; } /** * 设置回复音乐 * @param string $title * @param string $desc * @param string $musicurl * @param string $hgmusicurl * @return $this */ public function music($title,$desc,$musicurl,$hgmusicurl='') { $FuncFlag = $this->_funcflag ? 1 : 0; $msg = array( 'ToUserName' => $this->getRevFrom(), 'FromUserName'=>$this->getRevTo(), 'CreateTime'=>time(), 'MsgType'=>self::MSGTYPE_MUSIC, 'Music'=>array( 'Title'=>$title, 'Description'=>$desc, 'MusicUrl'=>$musicurl, 'HQMusicUrl'=>$hgmusicurl ) ); $this->Message($msg); return $this; } /** * 设置回复图文 * @param array $newsData * @return $this * @example 数组结构: * array( * 0=>array( * 'Title'=>'msg title', * 'Description'=>'summary text', * 'PicUrl'=>'http://www.domain.com/1.jpg', * 'Url'=>'http://www.domain.com/1.html' * ), * 1=>.... * ) */ public function news($newsData=array()) { $FuncFlag = $this->_funcflag ? 1 : 0; $count = count($newsData); $msg = array( 'ToUserName' => $this->getRevFrom(), 'FromUserName'=>$this->getRevTo(), 'CreateTime'=>time(), 'MsgType'=>self::MSGTYPE_NEWS, 'ArticleCount'=>$count, 'Articles'=>$newsData ); $this->Message($msg); return $this; } /** * * 向易信服务器回复消息 * Example: $this->text('msg tips')->reply(); * @param array|string $msg 要发送的信息, 默认取$this->_msg * @param bool $return 是否返回信息而输出 默认:false * @return string */ public function reply($msg=array(),$return = false) { if (empty($msg)) { $msg = $this->_msg; } $xmldata= $this->xml_encode($msg); $this->log($xmldata); if ($return) { return $xmldata; } else { echo $xmldata; } } private static function getTextArea($text,$str_start,$str_end){ if(empty($text)||empty($str_start)) { return false; } $start_pos=@strpos($text,$str_start); if($start_pos===false){ return false; } $end_pos=strpos($text,$str_end, $start_pos); if($end_pos>$start_pos && $end_pos!==false) { $begin_pos=$start_pos+strlen($str_start); return substr($text, $begin_pos,$end_pos-$begin_pos); } else { return false; } } /** * GET 请求 * @param string $url */ private function http_get($url){ //$proxy_url = "http://10.1.255.24:8090"; $oCurl = curl_init(); if(stripos($url,"https://")!==FALSE){ //curl_setopt($oCurl, CURLOPT_PROXY, $proxy_url); curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } curl_setopt($oCurl, CURLOPT_URL, $url); curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 ); $sContent = curl_exec($oCurl); $aStatus = curl_getinfo($oCurl); curl_close($oCurl); if(intval($aStatus["http_code"])==200){ return $sContent; }else{ return false; } } /** * POST 请求 * @param string $url * @param array $param * @param boolean $post_file 是否文件上传 * @return string content */ private function http_post($url,$param,$post_file=false){ //$proxy_url = "http://10.1.255.24:8090"; $oCurl = curl_init(); if(stripos($url,"https://")!==FALSE){ //curl_setopt($oCurl, CURLOPT_PROXY, $proxy_url); curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } if (is_string($param) || $post_file) { $strPOST = $param; } else { $aPOST = array(); foreach($param as $key=>$val){ $aPOST[] = $key."=".urlencode($val); } $strPOST = join("&", $aPOST); } curl_setopt($oCurl, CURLOPT_URL, $url); curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt($oCurl, CURLOPT_POST,true); curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST); $sContent = curl_exec($oCurl); $aStatus = curl_getinfo($oCurl); curl_close($oCurl); if(intval($aStatus["http_code"])==200){ return $sContent; }else{ return false; } } /** * 通用auth验证方法,暂时仅用于菜单更新操作 * @param string $appid * @param string $appsecret */ public function checkAuth($appid='',$appsecret=''){ if (!$appid || !$appsecret) { $appid = $this->appid; $appsecret = $this->appsecret; } $result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$appid.'&secret='.$appsecret); if ($result) { $json = json_decode($result,true); if (!$json || isset($json['errcode'])) { $this->errCode = $json['errcode']; $this->errMsg = $json['errmsg']; return false; } $this->access_token = $json['access_token']; $expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600; S('authname',$this->access_token,$expire); return $this->access_token; } return false; } /** * 删除验证数据 * @param string $appid */ public function resetAuth($appid=''){ if (!$appid) $appid = $this->appid; $this->access_token = ''; $authname = 'wechat_access_token'.$appid; S($authname,null); return true; } /** * 微信api不支持中文转义的json结构 /JSON编码 * @param array $arr */ /** static function json_encode($arr) { $parts = array (); $is_list = false; //Find out if the given array is a numerical array $keys = array_keys ( $arr ); $max_length = count ( $arr ) - 1; if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1 $is_list = true; for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position if ($i != $keys [$i]) { //A key fails at position check. $is_list = false; //It is an associative array. break; } } } foreach ( $arr as $key => $value ) { if (is_array ( $value )) { //Custom handling for arrays if ($is_list) $parts [] = self::json_encode ( $value ); else $parts [] = '"' . $key . '":' . self::json_encode ( $value ); } else { $str = ''; if (! $is_list) $str = '"' . $key . '":'; //Custom handling for multiple data types if (is_numeric ( $value ) && $value<2000000000) $str .= $value; //Numbers elseif ($value === false) $str .= 'false'; //The booleans elseif ($value === true) $str .= 'true'; else $str .= '"' . addslashes ( $value ) . '"'; //All other things // :TODO: Is there any more datatype we should be in the lookout for? (Object?) $parts [] = $str; } } $json = implode ( ',', $parts ); if ($is_list) return '[' . $json . ']'; //Return numerical JSON return '{' . $json . '}'; //Return associative JSON } **/ /** * 创建菜单 * @param array $data 菜单数组数据 * example: * array ( * 'button' => array ( * 0 => array ( * 'name' => '扫码', * 'sub_button' => array ( * 0 => array ( * 'key' => 'rselfmenu_0_0', * 'name' => '扫码带提示', 'type' => 'scancode_waitmsg' * ), * 1 => array ( 'key' => 'rselfmenu_0_1', 'name' => '扫码推事件', * 'type' => 'scancode_push' * * ) * ), * ), * 1 => array ( * 'name' => '发图', * 'sub_button' => array ( * 0 => array ( * 'key' => 'rselfmenu_0_0', * 'name' => '扫码带提示', 'type' => 'scancode_waitmsg' * ), * 1 => array ( 'key' => 'rselfmenu_0_1', 'name' => '扫码推事件', * 'type' => 'scancode_push' * * ) * ), * ), * 2 => array ( * 'key' => 'rselfmenu_0_1', 'name' => '扫码推事件', * 'type' => 'scancode_push' * ), * ), * ); * type可以选择为以下2种 * 1、click:点击推事件 * 2、view:跳转URL */ public function createMenu($data){ header("Content-type:text/html;charset=utf-8"); if (!$this->access_token && !$this->checkAuth()) return false; $result = $this->http_post(self::API_URL_PREFIX.self::MENU_CREATE_URL.'access_token='.$this->access_token,json_encode($data)); if ($result) { $json = json_decode($result,true); if (!$json || !empty($json['errcode'])) { $this->errCode = $json['errcode']; $this->errMsg = $json['errmsg']; return false; } return true; } return false; } /** * 获取菜单 * @return array('menu'=>array(....s)) */ public function getMenu(){ header("Content-type:text/html;charset=utf-8"); if (!$this->access_token && !$this->checkAuth()) return false; $result = $this->http_get(self::API_URL_PREFIX.self::MENU_GET_URL.'access_token='.$this->access_token); if ($result) { $json = json_decode($result,true); if (!$json || isset($json['errcode'])) { $this->errCode = $json['errcode']; $this->errMsg = $json['errmsg']; return false; } return $json; } return false; } /** * 删除菜单 * @return boolean */ public function deleteMenu(){ header("Content-type:text/html;charset=utf-8"); if (!$this->access_token && !$this->checkAuth()) return false; $result = $this->http_get(self::API_URL_PREFIX.self::MENU_DELETE_URL.'access_token='.$this->access_token); if ($result) { $json = json_decode($result,true); if (!$json || !empty($json['errcode'])) { $this->errCode = $json['errcode']; $this->errMsg = $json['errmsg']; return false; } return true; } return false; } } /** * Rolling Curl Request Class * @author Ligboy ([email protected]) * @copyright * @example * * */ class CurlHttp { /* 单线程请求设置项 */ /* 并发请求设置项 */ private $limitCount = 10; //并发请求数量 public $returninfoswitch = false; //是否返回请求信息,开启后单项请求返回结果为:array('info'=>请求信息, 'result'=>返回内容, 'error'=>错误信息) //私有属性 private $singlequeue = null; private $rollqueue = null; private $_requstItems = null; private $_callback = null; private $_result; private $_referer = null; private $_cookies = array(); private $_resheader; private $_reqheader = array(); private $_resurl; private $_redirect_url; private $referer; private $_singleoptions = array( CURLOPT_RETURNTRANSFER => true, // return web page CURLOPT_HEADER => true, // don't return headers // CURLOPT_FOLLOWLOCATION => true, // follow redirects CURLOPT_NOSIGNAL =>true, CURLOPT_ENCODING => "", // handle all encodings CURLOPT_USERAGENT => "", // who am i CURLOPT_AUTOREFERER => true, // set referer on redirect CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect CURLOPT_TIMEOUT => 120, // timeout on response CURLOPT_MAXREDIRS => 10, // stop after 10 redirects CURLOPT_SSL_VERIFYHOST => 0, // don't verify ssl CURLOPT_SSL_VERIFYPEER => false, // ); private $_rolloptions = array( CURLOPT_RETURNTRANSFER => true, // return web page CURLOPT_HEADER => false, // don't return headers // CURLOPT_FOLLOWLOCATION => true, // follow redirects CURLOPT_NOSIGNAL =>true, CURLOPT_ENCODING => "", // handle all encodings CURLOPT_USERAGENT => "", // who am i CURLOPT_AUTOREFERER => true, // set referer on redirect CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect CURLOPT_TIMEOUT => 120, // timeout on response CURLOPT_MAXREDIRS => 10, // stop after 10 redirects CURLOPT_SSL_VERIFYHOST => 0, // don't verify ssl CURLOPT_SSL_VERIFYPEER => false, // ); function singleInit($options = array()) { if (!$this->singlequeue) { $this->singlequeue = curl_init(); } if ($options) { $this->_singleoptions = array_merge($this->_singleoptions, $options); } } function rollInit($options = array()) { if(!$this->rollqueue){ $this->rollqueue = curl_multi_init(); } if ($options) { $this->_rolloptions = array_merge($this->_rolloptions, $options); } } /** * @name 返回Header数组 * @param resource $ch * @param $result * @return string */ private function getResRawHeader($ch, $result) { $ch_info = curl_getinfo($ch); $header_size = $ch_info["header_size"]; $rawheader = substr($result, 0, $ch_info['header_size']); return $rawheader; } /** * @name 返回Header数组 * @param resource $ch * @param $result * @return string */ private function getResHeader($ch, $result) { $header = array(); $rawheader = $this->getResRawHeader($ch, $result); if(preg_match_all('/([^:\s]+): (.*)/i', $rawheader, $header_match)){ for($i=0;$i<count($header_match[0]);$i++){ $header[$header_match[1][$i]] = $header_match[2][$i]; } } return $header; } /** * @name 返回网页主体内容 * @param resource $ch * @param $result * @return string 网页主体内容 */ private function getResBody($ch, $result) { $ch_info = curl_getinfo($ch); $body = substr($result, -$ch_info['download_content_length']); return $body; } /** * @name 返回网页主体内容 * @param resource $ch * @param $result * @return array 网页主体内容 */ private function getResCookies($ch, $result) { $rawheader = $this->getResRawHeader($ch, $result); $cookies = array(); if(preg_match_all('/Set-Cookie:(?:\s*)([^=]*?)=([^\;]*?);/i', $rawheader, $cookie_match)){ for($i=0;$i<count($cookie_match[0]);$i++){ $cookies[$cookie_match[1][$i]] = $cookie_match[2][$i]; } } return $cookies; } private function setReqCookies($ch, $reqcookies = array()) { $reqCookiesString = ""; if(!empty($reqcookies)){ if(is_array($reqcookies)){ foreach ($reqcookies as $key => $val){ $reqCookiesString .= $key."=".$val."; "; } curl_setopt($ch, CURLOPT_COOKIE, $reqCookiesString); } }elseif(!empty($this->_cookies)) { foreach ($this->_cookies as $key => $val){ $reqCookiesString .= $key."=".$val."; "; } curl_setopt($ch, CURLOPT_COOKIE, $reqCookiesString); } } private function setResCookies($ch) { if(!empty($reqcookies)&&is_array($reqcookies)){ $this->_cookies = array_merge($this->_cookies, $reqcookies); } } /** * @param unknown $url * @param mixed $postfields * @param string $referer * @param array $reqcookies * @param array $reqheader * @return unknown */ function post($url, $postfields=null, $referer=null, $reqcookies=null, $reqheader=array()) { $this->singlequeue = curl_init($url); $options = array( CURLOPT_RETURNTRANSFER => true, // return web page CURLOPT_HEADER => true, // don't return headers // CURLOPT_FOLLOWLOCATION => true, // follow redirects CURLOPT_ENCODING => "", // handle all encodings CURLOPT_USERAGENT => "", // who am i CURLOPT_AUTOREFERER => true, // set referer on redirect CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect CURLOPT_TIMEOUT => 120, // timeout on response CURLOPT_MAXREDIRS => 10, // stop after 10 redirects CURLOPT_POST => true, // i am sending post data CURLOPT_SSL_VERIFYHOST => 0, // don't verify ssl CURLOPT_SSL_VERIFYPEER => false, // ); curl_setopt_array($this->singlequeue, $options); curl_setopt($this->singlequeue, CURLOPT_POSTFIELDS, $postfields); // this are my post vars if($referer){ curl_setopt($this->singlequeue, CURLOPT_REFERER, $referer); } elseif ($this->referer){ curl_setopt($this->singlequeue, CURLOPT_REFERER, $this->referer); } $this->setReqheader($this->singlequeue, $reqheader); $this->setReqCookies($this->singlequeue, $reqcookies); $result = curl_exec($this->singlequeue); $resCookies = $this->getResCookies($this->singlequeue, $result);; if (is_array($resCookies)&&!empty($resCookies)) { $this->_cookies = array_merge($this->_cookies ,$resCookies); } $resHeader = $this->getResHeader($this->singlequeue, $result); if (is_array($resHeader)&&!empty($resHeader)) { $this->_resheader = $resHeader; } $this->_result = $this->getResBody($this->singlequeue, $result); curl_close($this->singlequeue); $this->singlequeue = null; return $this->_result; } /** * @param unknown $url * @param unknown $referer * @param null $reqcookies * @param array $reqheader * @return unknown */ function get($url, $referer=null, $reqcookies=null, $reqheader=array()) { $this->singlequeue = curl_init($url); $options = array( CURLOPT_RETURNTRANSFER => true, // return web page CURLOPT_HEADER => true, // don't return headers // CURLOPT_FOLLOWLOCATION => true, // follow redirects CURLOPT_ENCODING => "", // handle all encodings CURLOPT_USERAGENT => "", // who am i CURLOPT_AUTOREFERER => true, // set referer on redirect CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect CURLOPT_TIMEOUT => 120, // timeout on response CURLOPT_MAXREDIRS => 10, // stop after 10 redirects CURLOPT_POST => false, // i am sending post data CURLOPT_SSL_VERIFYHOST => 0, // don't verify ssl CURLOPT_SSL_VERIFYPEER => false, // CURLOPT_REFERER =>$referer, ); curl_setopt_array($this->singlequeue, $options); if($referer){ curl_setopt($this->singlequeue, CURLOPT_REFERER, $referer); } elseif ($this->referer){ curl_setopt($this->singlequeue, CURLOPT_REFERER, $this->referer); } $this->setReqheader($this->singlequeue, $reqheader); $this->setReqCookies($this->singlequeue, $reqcookies); $result = curl_exec($this->singlequeue); $resCookies = $this->getResCookies($this->singlequeue, $result); if (is_array($resCookies)&&!empty($resCookies)) { $this->_cookies = array_merge($this->_cookies ,$resCookies); } $resHeader = $this->getResHeader($this->singlequeue, $result); if (is_array($resHeader)) { $this->_resheader = $resHeader; } $this->_result = $this->getResBody($this->singlequeue, $result); curl_close($this->singlequeue); $this->singlequeue = null; return $this->_result; } /** * 并发行的curl方法 * @param unknown $requestArray * @param string $callback * @return multitype:multitype: */ function rollRequest($requestArray, $callback="") { $this->_requstItems = $requestArray; $requestArrayKeys = array_keys($requestArray); $this->rollqueue = curl_multi_init(); $map = array(); for ($i=0;$i<$this->limitCount && !empty($requestArrayKeys);$i++) { $keyvalue = array_shift($requestArrayKeys); $this->addToRollQueue( $requestArray, $keyvalue, $map ); } $responses = array(); do { while (($code = curl_multi_exec($this->rollqueue, $active)) == CURLM_CALL_MULTI_PERFORM) ; if ($code != CURLM_OK) { break; } // 找到刚刚完成的任务句柄 while ($done = curl_multi_info_read($this->rollqueue)) { // 处理当前句柄的信息、错误、和返回内容 $info = curl_getinfo($done['handle']); $error = curl_error($done['handle']); if ($this->_callback) { //调用callback函数处理当前句柄的返回内容,callback函数参数有:(返回内容, 队列id) $result = call_user_func($this->_callback, curl_multi_getcontent($done['handle']), $map[(string) $done['handle']]); } else { //如果callback为空,直接返回内容 $result = curl_multi_getcontent($done['handle']); } if ($this->returninfoswitch) { $responses[$map[(string) $done['handle']]] = compact('info', 'error', 'result'); } else { $responses[$map[(string) $done['handle']]] = $result; } // 从队列里移除上面完成处理的句柄 curl_multi_remove_handle($this->rollqueue, $done['handle']); curl_close($done['handle']); if (!empty($requestArrayKeys)) { $addkey = array_shift($requestArrayKeys); $this->addToRollQueue ( $requestArray, $addkey, $map ); } } // Block for data in / output; error handling is done by curl_multi_exec if ($active > 0) { curl_multi_select($this->rollqueue, 0.5); } } while ($active); curl_multi_close($this->rollqueue); $this->rollqueue = null; return $responses; } /** * @param requestArray * @param map * @param keyvalue */ private function addToRollQueue($requestArray, $keyvalue, &$map) { $ch = curl_init(); curl_setopt_array($ch, $this->_rolloptions); //检查提交方式,并设置对应的设置,为空的话默认采用get方式 if ("post" === $requestArray[$keyvalue]['method']) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $requestArray[$keyvalue]['postfields']); } else { curl_setopt($ch, CURLOPT_HTTPGET, true); } if($requestArray[$keyvalue]['referer']){ curl_setopt($ch, CURLOPT_REFERER, $requestArray[$keyvalue]['referer']); } elseif ($this->referer){ curl_setopt($ch, CURLOPT_REFERER, $this->referer); } $this->setReqheader($ch, $requestArray[$keyvalue]['header']); //cookies设置 $this->setReqCookies($ch, $requestArray[$keyvalue]['cookies']); curl_setopt($ch, CURLOPT_URL, $requestArray[$keyvalue]['url']); curl_setopt($ch, CURLOPT_REFERER, $requestArray[$keyvalue]['referer']); curl_multi_add_handle($this->rollqueue, $ch); $map[(string) $ch] = $keyvalue; } /** * 返回当前并行数 * @return the $limitCount */ public function getRollLimitCount() { return $this->limitCount; } /** * 设置并发性请求数量 * @param number $limitCount * @return $this */ public function setRollLimitCount($limitCount) { $this->limitCount = $limitCount; return $this; } /** * 设置回调函数 * @param field_type $_callback * @return $this */ public function setCallback($_callback) { $this->_callback = $_callback; return $this; } public function getResult() { return $this->_result; } public function getRawHeader() { return $this->_resheader; } public function getCookies() { return $this->_cookies; } public function setCookies($_cookies) { $this->_cookies = $_cookies; return $this; } /** * @param $header * @return $this */ public function setHeader($header) { $this->_reqheader = array_merge($this->_reqheader, $header); return $this; } /** * @param resource $ch * @param array $reqheader * @return $this */ private function setReqheader($ch, $reqheader) { $reqheader = array_merge($this->_reqheader, $reqheader); if (is_array($reqheader)) { $rawReqHeader = array(); foreach ($reqheader as $key => $value){ $rawReqHeader[] = "$key: $value"; } curl_setopt($ch, CURLOPT_HTTPHEADER, $rawReqHeader); $this->_reqheader = array(); } return $this; } } /** * error code * 仅用作类内部使用,不用于官方API接口的errCode码 */ class ErrorCode { public static $OK = 0; public static $ValidateSignatureError = 40001; public static $ParseXmlError = 40002; public static $ComputeSignatureError = 40003; public static $IllegalAesKey = 40004; public static $ValidateAppidError = 40005; public static $EncryptAESError = 40006; public static $DecryptAESError = 40007; public static $IllegalBuffer = 40008; public static $EncodeBase64Error = 40009; public static $DecodeBase64Error = 40010; public static $GenReturnXmlError = 40011; public static $errCode=array( '0'=>'请求成功', '40001'=>'验证失败', '40002'=>'不合法的凭证类型', '40003'=>'不合法的OpenID', '40004'=>'不合法的媒体文件类型', '40005'=>'不合法的文件类型', '40006'=>'不合法的文件大小', '40007'=>'不合法的媒体文件id', '40008'=>'不合法的消息类型', '40009'=>'不合法的图片文件大小', '40010'=>'不合法的语音文件大小', '40011'=>'不合法的视频文件大小', '40012'=>'不合法的缩略图文件大小', '40013'=>'不合法的APPID', '40014'=>'不合法的access_token', '40015'=>'不合法的菜单类型', '40016'=>'不合法的按钮个数', '40018'=>'不合法的按钮名字长度', '40019'=>'不合法的按钮KEY长度', '40020'=>'不合法的按钮URL长度', '40021'=>'不合法的菜单版本号', '40022'=>'不合法的子菜单级数', '40023'=>'不合法的子菜单按钮个数', '40024'=>'不合法的子菜单按钮类型', '40025'=>'不合法的子菜单按钮名字长度', '40026'=>'不合法的子菜单按钮KEY长度', '40027'=>'不合法的子菜单按钮URL长度', '40028'=>'不合法的自定义菜单使用用户', '40029'=>'access_token超时', '40030'=>'refresh_token超时', '40035'=>'不合法的参数', '40038'=>'不合法的请求格式', '40039'=>'不合法的URL长度', '40050'=>'不合法的分组id', '40051'=>'分组名字不合法', '40052'=>'已有重复的分组名称', '40053'=>'不存在的分组名', '40054'=>'不允许对黑名单分组群发', '40998'=>'未授权的API', '40999'=>'非法IP访问', '41001'=>'缺少access_token参数', '41002'=>'缺少appid参数', '41003'=>'缺少refresh_token参数', '41004'=>'缺少secret参数', '41005'=>'缺少多媒体文件数据', '41006'=>'缺少media_id参数', '41007'=>'缺少子菜单数据', '41009'=>'缺少openid', '42001'=>'access_token超时', '42008'=>'用户ID不一致', '42009'=>'APPID不一致', '43001'=>'需要GET请求', '43002'=>'需要POST请求', '43003'=>'需要HTTPS请求', '43004'=>'需要接收者关注', '44001'=>'多媒体文件为空', '44002'=>'POST的数据包为空', '44003'=>'图文消息内容为空', '44004'=>'文本消息内容为空', '45001'=>'多媒体文件大小超过限制', '45002'=>'消息内容超过限制', '45003'=>'标题字段超过限制', '45004'=>'描述字段超过限制', '45005'=>'链接字段超过限制', '45006'=>'图片链接字段超过限制', '45007'=>'语音播放时间超过限制', '45008'=>'图文消息超过限制', '45009'=>'接口调用超过限制', '45010'=>'创建菜单个数超过限制', '45016'=>'系统分组,不允许修改', '45017'=>'分组名字过长', '45018'=>'分组数量超过上限', '45019'=>'分组名称为空', '45020'=>'不存在的分组', '45021'=>'群发消息量超过限制', '45999'=>'接口调用超过每秒限制', '46001'=>'不存在媒体数据', '46002'=>'不存在的菜单版本', '46003'=>'不存在的菜单数据', '46004'=>'不存在的用户', '47001'=>'解析JSON/XML内容错误', '48001'=>'api功能未授权', '49000'=>'创建投票活动失败(不合法的请求消息)', '49001'=>'不合法的投票标题', '49002'=>'不合法的投票说明', '49003'=>'不合法的投票结果类型', '49004'=>'不合法的投票选项个数', '49005'=>'不合法的投票选项', '49006'=>'不合法的投票选项类型', '49007'=>'不合法的投票选择范围', '49008'=>'不合法的投票截止时间', '49009'=>'不合法的投票限制类型', '49010'=>'不存在的投票活动', '49011'=>'投票结果正在处理', '49012'=>'投票已结束', '49013'=>'投票未结束', '50001'=>'该用户没有关注此公众号', '50002'=>'该用户不允许公众号获取他的好友关系', '50003'=>'识别条形码失败', '50005'=>'无法识别该条形码', '50006'=>'无法打开所提供的图片链接地址', '50007'=>'next_openid未关注此公众号', '50008'=>'生成二维码失败(错误的请求内容)', '50009'=>'生成二维码失败', '50010'=>'不合法的ticket', '51001'=>'不合法的mobile', '52001'=>'无权访问该动态或该动态不存在', '52029'=>'发送的内容涉及敏感词', '60001'=>'请求参数中缺少key', '60002'=>'公众号不存在', '60003'=>'公众号状态错误', '60004'=>'用户在黑名单中' ); public static function getErrText($err) { if (isset(self::$errCode[$err])) { return self::$errCode[$err]; }else { return false; }; } }