php微信开发实现自定义菜单功能
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php微信开发实现自定义菜单功能相关的知识,希望对你有一定的参考价值。
首先说一下遇到的坑吧!
01我用的测试公众号,说好的有接口权限,结果呢,微信留了个坑,返回错误代码 48001
一查错误码 微信文档这样写:api功能未授权,请确认公众号已获得该接口,可以在公众平台官网-开发者中心页中查看接口权限
懵逼了吧!
半信半疑中,我果断换了认证过的服务号,一测试OK了
02代码的开头有空格也会报错,跟tp的机制有关,我的代码在tp下面。
03 调用接口的链接为https,结果我的服务器可能验证证书出错,最后找了半天才找到一种解决办法,就是在使用curl的部分使用如下代码:
可以通过添加一下代码解决 curl_setopt_array( $ch, array( CURLOPT_URL => $url, CURLOPT_REFERER => $url, CURLOPT_AUTOREFERER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_CONNECTTIMEOUT => 1, CURLOPT_TIMEOUT => 30, CURLOPT_USERAGENT => ‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/34.0.1847.116 Safari/537.36‘,) );
接下来就直接上代码吧!我的代码是在tp5下的代码,单独编写不方便运行,就用的tp5
我的访问路径为:http://wexin.bsgrj.com/wexin/public/index.php/index/index/definedItem
直接在浏览器运行就可以。
1 <?php 2 3 namespace app\index\controller; 4 5 use think\Controller; 6 7 //define your token 8 define("TOKEN", "weixin"); 9 10 Class Index extends Controller 11 { 12 public function index()//接收微信客户端发送的信息并回应! 13 { 14 //get post data, May be due to the different environments 15 $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; 16 //extract post data 17 if (!empty($postStr)){ 18 /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection, 19 the best way is to check the validity of xml by yourself */ 20 libxml_disable_entity_loader(true); 21 $postObj = simplexml_load_string($postStr, ‘SimpleXMLElement‘, LIBXML_NOCDATA); 22 $fromUsername = $postObj->FromUserName; 23 $toUsername = $postObj->ToUserName; 24 $keyword = trim($postObj->Content); 25 $time = time(); 26 $msgType = $postObj->MsgType;//消息类型 27 $event = $postObj->Event;//时间类型,subscribe(订阅)、unsubscribe(取消订阅) 28 $textTpl = "<xml> 29 <ToUserName><![CDATA[%s]]></ToUserName> 30 <FromUserName><![CDATA[%s]]></FromUserName> 31 <CreateTime>%s</CreateTime> 32 <MsgType><![CDATA[%s]]></MsgType> 33 <Content><![CDATA[%s]]></Content> 34 <FuncFlag>0</FuncFlag> 35 </xml>"; 36 switch($msgType){ 37 case "event": 38 if($event=="subscribe"){ 39 $contentStr = "Hi,欢迎关注168php微信开发"."\n"."回复数字‘1‘,了解相关基础教程."."\n"."回复数字‘2‘,添加技术交流群."; 40 } 41 break; 42 case "text": 43 switch($keyword){ 44 case "1": 45 $contentStr = "相关教程:"."\n"."<a href=‘http://www.imooc.com/‘>慕课网</a>."; 46 break; 47 case "2": 48 $contentStr = "技术交流群:"."\n"." QQ群:184037581."; 49 break; 50 case "3": 51 $this->singleGraphic($postObj); 52 exit; 53 default: 54 $contentStr = "对不起,你的内容我会稍后回复"; 55 } 56 break; 57 } 58 $msgType = "text"; 59 $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 60 echo $resultStr; 61 }else { 62 echo ""; 63 exit; 64 } 65 } 66 private function singleGraphic($postObj) /**多图文回复*/ 67 { 68 $toUser = $postObj->FromUserName; 69 $fromUser = $postObj->ToUserName; 70 $arr = array( 71 array( 72 ‘title‘=>‘imooc‘, 73 ‘description‘=>"imooc is very cool", 74 ‘picUrl‘=>‘http://www.imooc.com/static/img/common/logo.png‘, 75 ‘url‘=>‘http://www.imooc.com‘, 76 ), 77 array( 78 ‘title‘=>‘hao123‘, 79 ‘description‘=>"hao123 is very cool", 80 ‘picUrl‘=>‘https://www.baidu.com/img/bdlogo.png‘, 81 ‘url‘=>‘http://www.hao123.com‘, 82 ), 83 array( 84 ‘title‘=>‘qq‘, 85 ‘description‘=>"qq is very cool", 86 ‘picUrl‘=>‘http://www.imooc.com/static/img/common/logo.png‘, 87 ‘url‘=>‘http://www.qq.com‘, 88 ), 89 ); 90 $template = "<xml> 91 <ToUserName><![CDATA[%s]]></ToUserName> 92 <FromUserName><![CDATA[%s]]></FromUserName> 93 <CreateTime>%s</CreateTime> 94 <MsgType><![CDATA[%s]]></MsgType> 95 <ArticleCount>".count($arr)."</ArticleCount> 96 <Articles>"; 97 foreach($arr as $k=>$v){ 98 $template .="<item> 99 <Title><![CDATA[".$v[‘title‘]."]]></Title> 100 <Description><![CDATA[".$v[‘description‘]."]]></Description> 101 <PicUrl><![CDATA[".$v[‘picUrl‘]."]]></PicUrl> 102 <Url><![CDATA[".$v[‘url‘]."]]></Url> 103 </item>"; 104 } 105 $template .="</Articles> 106 </xml> "; 107 echo sprintf($template, $toUser, $fromUser, time(), ‘news‘); 108 } 109 private function checkSignature()//验证服务器 110 { 111 // you must define TOKEN by yourself 112 if (!defined("TOKEN")) { 113 throw new Exception(‘TOKEN is not defined!‘); 114 } 115 $signature = $_GET["signature"]; 116 $timestamp = $_GET["timestamp"]; 117 $nonce = $_GET["nonce"]; 118 $token = TOKEN; 119 $tmpArr = array($token, $timestamp, $nonce); 120 // use SORT_STRING rule 121 sort($tmpArr, SORT_STRING); 122 $tmpStr = implode( $tmpArr ); 123 $tmpStr = sha1( $tmpStr ); 124 if( $tmpStr == $signature ){ 125 return true; 126 }else{ 127 return false; 128 } 129 } 130 public function http_curl($url,$type=‘get‘,$res=‘json‘,$arr=‘‘)//接口调用函数 131 { 132 /* 133 *$cur 接口url string 134 *$type 请求类型 string 135 $res 返回数据类型 string 136 $arr post请求参数 string 137 */ 138 //1.初始化curl 139 $ch=curl_init(); 140 //2.设置curl的参数 141 // curl_setopt($ch, CURLOPT_URL, $url); 142 // curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 143 144 curl_setopt_array( 145 $ch, 146 array( 147 CURLOPT_URL => $url, 148 CURLOPT_REFERER => $url, 149 CURLOPT_AUTOREFERER => true, 150 CURLOPT_RETURNTRANSFER => true, 151 CURLOPT_SSL_VERIFYPEER => false, 152 CURLOPT_SSL_VERIFYHOST => false, 153 CURLOPT_CONNECTTIMEOUT => 1, 154 CURLOPT_TIMEOUT => 30, 155 ) 156 ); 157 158 if($type==‘post‘){ 159 curl_setopt($ch, CURLOPT_POST, 1); 160 curl_setopt($ch, CURLOPT_POSTFIELDS, $arr); 161 //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//测试 162 // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//测试 163 164 } 165 //3.采集 166 $output=curl_exec($ch); 167 //4.关闭 168 if($res==‘json‘){ 169 if(curl_error($ch)){ 170 return curl_error($ch); 171 curl_close($ch); 172 }else{ 173 return json_decode($output,true); 174 } 175 } 176 } 177 public function getWxAccessToken()//返回access_token *session解决办法 ,存mysql或memcache都可以 178 { 179 //将access_token 存在session/cookie中 180 if(isset($_SESSION[‘access_token‘])&&isset($_SESSION[‘expire_time‘])){ 181 if($_SESSION[‘access_token‘]&&$_SESSION[‘expire_time‘]>time()){ 182 //如果access_token在session中并没有过期 183 return $_SESSION[‘access_token‘]; 184 } 185 } 186 else{ 187 //如果access_token不存在或者已经过期,重新取access_token 188 $appid=‘wx4e91a0e959b399a5‘; 189 $appsecret=‘46cf302c8ff3585026682f6ae603da94‘; 190 $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; 191 $res=$this->http_curl($url,‘get‘,‘json‘); 192 $access_token=$res[‘access_token‘]; 193 $_SESSION[‘access_token‘]=$access_token; 194 $_SESSION[‘expire_time‘]=time()+7000; 195 return $access_token; 196 } 197 } 198 public function definedItem()//创建微信菜单 199 { 200 //目前微信接口的调用方式都是通过curl post/get 201 header(‘content-type:text/html;charset=utf-8‘); 202 echo $access_token=$this->getWxAccessToken(); 203 echo $url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token; 204 $postArr=array( 205 ‘button‘=>array( 206 array( 207 ‘name‘=>urlencode(‘科技力量‘), 208 ‘type‘=>‘view‘, 209 ‘url‘=>‘https://m.eqxiu.com/s/4Z7xqPHv‘, 210 ),//第一个一级菜单 211 array( 212 ‘name‘=>urlencode(‘公司官网‘), 213 ‘type‘=>‘view‘, 214 ‘url‘=>‘http://m.yztsaas.com‘, 215 ),//第二个一级菜单 216 array( 217 ‘name‘=>urlencode(‘下载APP‘), 218 ‘type‘=>‘view‘, 219 ‘url‘=>‘http://qrt.huilinchina.com/Home/Index/download‘, 220 ),//第三个一级菜单 221 222 )); 223 $postJson=urldecode(json_encode($postArr));//数组转换为json 224 //var_dump($postJson); 225 $res=$this->http_curl($url,‘post‘,‘json‘,$postJson); 226 var_dump($res); 227 } 228 229 230 }
接下来,开发微信卡包电子会员!加油!耽误10天左右了,入了好多坑,真心累!
以上是关于php微信开发实现自定义菜单功能的主要内容,如果未能解决你的问题,请参考以下文章
最全面 think php 实现微信公众号回复编号进行投票,自定义菜单功能