appid = $appid; $this->secret = $secret; $this->valid(); $this->getaccess_token(); } public function valid(){ //验证token $echoStr = input('echostr'); if($this->checkSignature()){ echo $echoStr; //exit; } } private function checkSignature(){ //验证token $signature = input("signature"); $timestamp = input("timestamp"); $nonce = input("nonce"); $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $tmpStr == $signature ){ return true; }else{ return false; } } public function getaccess_token(){ //获取access_token 用redis来做中间token存储 $redis = new \Redis(); $redis->connect('127.0.0.1',6379); $token = $redis->get($this->appid); if($token){ $this->access_token = $token; }else{ $token_access_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->appid . "&secret=" . $this->secret; $res = file_get_contents($token_access_url); //获取文件内容或获取网络请求的内容 $result = json_decode($res, true); //接受一个 JSON 格式的字符串并且把它转换为 PHP 变量 if(isset($result['access_token'])){ //把access_token存入redis用 access_token expires_in 过期时间 来做过期时间 $result['expires_in'] = 3600; $redis->setex($this->appid,$result['expires_in'],$result['access_token']); $this->access_token = $result['access_token']; }else{ $this->access_token = ''; } } } //获取粉丝openid 一次最多拉取 1万条 public function getopenid(){ $url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token=".$this->access_token; $result = $this->https_request($url); $info = json_decode($result,true); if(isset($info['data'])){ $users = $info['data']['openid']; }else{ $users = null; } return $users; } //获取所有全部粉丝openid 一次最多拉取 1万条 需要多次拉取 next_openid=列表最后一个openid public function getopenidall($nextid=null){ $next_openid = empty($nextid)?null:"&next_openid=".$nextid; $url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token=".$this->access_token.$next_openid; $result = $this->https_request($url); $info = json_decode($result,true); if(isset($info['data'])){ $users = $info['data']['openid']; $endid = $info['next_openid']; }else{ $users = null; $endid = null; } $openidArr = array( 'users'=>$users, 'endid'=>$endid ); return $openidArr; } //创建底部菜单 注意菜单名称如果是数组转json 需要 urlencode() 汉字 打包后 在解码 public function wechatnav($arr){ $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->access_token; $jsondata = urldecode(json_encode($arr)); $ch = curl_init(); //创建一个请求 curl_setopt($ch,CURLOPT_URL,$url); //设置请求的url curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); // 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。 curl_setopt($ch,CURLOPT_POST,1); //启用时会发送一个常规的POST请求,类型为:application/x-www-form-urlencoded,就像表单提交的一样 curl_setopt($ch,CURLOPT_POSTFIELDS,$jsondata); //全部数据使用HTTP协议中的"POST"操作来发送。要发送文件,在文件名前面加上@前缀并使用完整路径。这个参数可以通过urlencoded后的字符串类似'para1=val1¶2=val2&...'或使用一个以字段名为键值,字段数据为值的数组。如果value是一个数组,Content-Type头将会被设置成multipart/form-data。 $output = curl_exec($ch); //执行请求 curl_close($ch); //关闭资源 return $output; } //查看底部菜单 public function getwechatnav(){ $url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=".$this->access_token; $data = $this->getHttp($url); return $data; } public function deletenav(){ //删除底部菜单 return file_get_contents("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=".$this->access_token); } //被动回复图文消息 注意:Xml里面不能有编辑器换行或者空格 严格要求官方数据格式 //只能关注回复才能使用高级素材模式 否则会自动转成客服消息图文模式 public function transmitNews($object,$newsArray){ if(!is_array($newsArray)){ return ""; } $itemTpl = " <![CDATA[%s]]> "; $item_str = ""; foreach ($newsArray as $item){ $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']); } $xmlTpl = " %s %s $item_str "; $result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(), count($newsArray)); echo $result; } //被动回复文本消息 注意:Xml里面不能有编辑器换行或者空格 严格要求官方数据格式 public function transmitText($object,$content){ if (!isset($content) || empty($content)){ return ""; } $xmlTpl = " %s "; $result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(),'text',$content); echo $result; } //关注回复发送图片 public function transmitImage($object,$mediaId){ if (!isset($mediaId) || empty($mediaId)){ return ""; } $xmlTpl = " %s "; $result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(),'image',$mediaId); echo $result; } //推送模板消息 public function pushTemplate($openids=array(),$data=array()){ $touser = $openids; $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $this->access_token; foreach ($touser as $value) { $datapush = $this->getDataTemplateArray($value,$data); $json_data = json_encode($datapush);//转化成json数组让微信可以接收 $res = $this->https_request($url, urldecode($json_data));//请求开始 $res = json_decode($res, true); if ($res['errcode'] == 0 && $res['errcode'] == "ok"){ return 1; }else{ return $res['errcode']; } } } //获取发送模板消息数据数组 public function getDataTemplateArray($openid,$data){ $data = array( 'touser' => $openid, //单个openid 'template_id' => $data['template'], 'url' => $data['link'], 'data' => array( 'first' => array( 'value' => $data['title'], 'color' => "#000" ), 'keyword1' => array( 'value' => $data['keyword1'], 'color' => $data['color2'] ), 'keyword2' => array( 'value' => $data['keyword2'], 'color' => "#000" ), 'remark' => array( 'value' => $data['remark'], 'color' => $data['color3'] ), ) ); return $data; } public function getDataArrayKefu($value,$link){ //获取发送数据数组 发送文本客服消息 $data = array( 'touser' => $value, //要发送给用户的openid 'msgtype'=>'text', 'text' => array( 'content' =>$link ) ); return $data; } public function getDataArrayKefuImg($value,$title,$description,$url,$imgurl){ //获取发送数据数组 发送图文客服消息 $data = '{ "touser":"'.$value.'", "msgtype":"news", "news":{ "articles": [ { "title":"'.$title.'", "description":"'.$description.'", "url":"'.$url.'", "picurl":"'.$imgurl.'" } ] } }'; return $data; } //发送文本客服消息 text 需要urlencode编码一下 public function kefu($openids=array(),$text){ $touser = $openids; $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=". $this->access_token; foreach ($touser as $value) { $data = $this->getDataArrayKefu($value,$text); $json_data = json_encode($data);//转化成json数组让微信可以接收 $res = $this->https_request($url, urldecode($json_data));//请求开始 $res = json_decode($res, true); if ($res['errcode'] == 0 && $res['errcode'] == "ok"){ return '发送成功'; }else{ var_dump($res); } } } // 发送图文客服消息 openid 标题 描述 外链地址 图片地址 public function kefuImg($openids=array(),$title,$description,$linkurl,$imgurl){ $touser = $openids; $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=". $this->access_token; foreach ($touser as $value) { $data = $this->getDataArrayKefuImg($value,$title,$description,$linkurl,$imgurl); $res = $this->https_request($url, $data);//请求开始 $res = json_decode($res, true); if ($res['errcode'] == 0 && $res['errcode'] == "ok"){ return '发送成功'; }else{ var_dump($res); } } } //curl请求函数,微信都是通过该函数请求 public function https_request($url, $data = null){ $curl = curl_init(); //创建请求 curl_setopt($curl, CURLOPT_URL, $url); //设置请求的URL curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);//禁用后cURL将终止从服务端进行验证。使用CURLOPT_CAINFO选项设置证书使用CURLOPT_CAPATH选项设置证书目录 如果CURLOPT_SSL_VERIFYPEER(默认值为2)被启用,CURLOPT_SSL_VERIFYHOST需要被设置成TRUE否则设置为FALSE。 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);//1 检查服务器SSL证书中是否存在一个公用名(common name)。译者注:公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。2 检查公用名是否存在,并且是否与提供的主机名匹配 if (!empty($data)) { curl_setopt($curl, CURLOPT_POST, 1); //设置为POST curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//传递一个数组到CURLOPT_POSTFIELDS,cURL会把数据编码成 multipart/form-data,而然传递一个URL-encoded字符串时,数据会被编码成 application/x-www-form-urlencoded } curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);//在启用CURLOPT_RETURNTRANSFER的时候,返回原生的(Raw)输出。 $output = curl_exec($curl);//设置OK curl_close($curl); return $output; } // get请求 public function getHttp($url,$post_data=array()) { $ch = curl_init($url); $timeout = 6000; curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HEADER,0 ); curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); $ret = curl_exec($ch); curl_close($ch); return $ret; } // 以下是高级群发 素材管理 // 上传图片 返回media_id public function uploadImage($file,$type='image'){ $data = array('media' => new \CURLFile(realpath($file))); $url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$this->access_token.'&type='.$type; $res = $this->https_request($url,$data);//请求开始 $res = json_decode($res, true); if (isset($res['errcode'])){ return 0; }else{ return $res['media_id']; } } // 上传图文消息内的图片获取URL $file 必须服务器绝对路径 public function getimg($file){ $data = array('media' => new \CURLFile(realpath($file))); $url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.$this->access_token; $res = $this->https_request($url,$data);//请求开始 $res = json_decode($res, true); if (isset($res['errcode'])){ return 0; }else{ return $res['url']; } } // 上传图文素材 返回素材的media_id // 注意素材里的 文本需要 urlencode 编码 打包json后在 urldecode 数据才正确 // 编辑器里的文本需要 urlencode + htmlspecialchars(str_replace("\"", "'", $data['content'])) 然后 urldecode + htmlspecialchars_decode // $data = 2维数组(必须) public function upMaterial($data){ // $url = 'https://api.weixin.qq.com/cgi-bin/material/add_news?access_token='.$this->access_token; $url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token='.$this->access_token; $news = array(); $news['articles'] = $data; $news = json_encode($news); $news = urldecode($news); $news = htmlspecialchars_decode($news); $res = $this->https_request($url,$news);//请求开始 $res = json_decode($res, true); if (isset($res['errcode'])){ return null; }else{ return $res['media_id']; } } // 修改已经上传的图文素材 当个栏目修改 // 注意素材里的 文本需要 urlencode 编码 打包json后在 urldecode 数据才正确 // 编辑器里的文本需要 urlencode + htmlspecialchars(str_replace("\"", "'", $data['content'])) 然后 urldecode + htmlspecialchars_decode // 正确时errcode的值应为0 $data = 一维数组 $media_id = 素材ID $index = 栏目所在素材位置 public function renewNews($data,$media_id,$index){ // $url = 'https://api.weixin.qq.com/cgi-bin/material/update_news?access_token='.$this->access_token; $url = 'https://api.weixin.qq.com/cgi-bin/draft/update?access_token='.$this->access_token; $news = array( "media_id"=>$media_id, "index"=>$index, "articles"=>$data ); $news = json_encode($news); $news = urldecode($news); $news = htmlspecialchars_decode($news); $res = $this->https_request($url,urldecode($news));//请求开始 $res = json_decode($res, true); if ($res['errcode']==0){ return 1; }else{ return $res; } } // 删除图文模板 public function delmd($media_id){ // $url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token='.$this->access_token; $url = 'https://api.weixin.qq.com/cgi-bin/draft/delete?access_token='.$this->access_token; $data = array('media_id'=>$media_id); $data = json_encode($data); $res = $this->https_request($url,$data);//请求开始 $res = json_decode($res, true); if ($res['errcode']==0){ return 1; }else{ return $res; } } // 测试高级群发 public function ceshiPush($openid,$media_id){ $this->valid(); $this->getaccess_token(); $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token='.$this->access_token; $data = '{ "touser":"'.$openid.'", "mpnews":{ "media_id":"'.$media_id.'" }, "msgtype":"mpnews" }'; $res = $this->https_request($url,$data);//请求开始 $res = json_decode($res, true); if ($res['errcode']==0){ return '发送成功'; }else{ return $res['errmsg']; } } // 开始高级群发 $openids = 一维数组 $media_id = 素材ID public function advancedPush($openids,$media_id){ $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token='.$this->access_token; $openid = json_encode($openids); $news = '{ "touser":'.$openid.', "mpnews":{ "media_id":"'.$media_id.'" }, "msgtype":"mpnews", "send_ignore_reprint":1, "is_to_all":"true" }'; $res = $this->https_request($url,$news);//请求开始 $res = json_decode($res, true); if ($res['errcode']==0){ return 1; }else{ return $res['errmsg']; } } } ?>