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天左右了,入了好多坑,真心累!

时间: 2024-10-13 02:54:50

php微信开发实现自定义菜单功能的相关文章

Java企业微信开发_04_自定义菜单

一.本节要点 1.菜单相关实体类的封装 参考官方文档中的请求包的内容,对菜单相关实体类进行封装. 这里需要格外注意的是,企业微信中请求包的数据是Json字符串格式的,而不是xml格式.关于json序列化的问题请参考上一节   Java企业微信开发_03_通讯录同步 2.创建菜单的接口 public static String create_menu_url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS

微信开发之自定义菜单--weixin-java-tools

一.前言 平时在开发微信的过程中,肯定会设计到微信的相关菜单的使用,这次就和大家介绍下如何使用weixin-java-tools来管理菜单 二.自定义菜单分类 1.click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互: 2.view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获

微信开发 之 自定义菜单

http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 这是微信公众平台上的说明地址. 另外订阅号是没有这个权限的,认证过的公众号才可以有这个权限. 接口调用请求说明 http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN { "button":[ { "

微信公众平台开发(24) 自定义菜单功能开发

原文: http://www.cnblogs.com/imaker/p/5491433.html 一.简介 微信公众平台服务号以及之前成功申请内测资格的订阅号都具有自定义菜单的功能.开发者可利用该功能为公众账号的会话界面底部增加自定义菜单,用户点击菜单中的选项,可以调出相应的回复信息或网页链接.自定义菜单接口将为公众账号的信息展示空间提供更多可能性.本文将针对自定义菜单做简单的开发应用,以供读者参考. 二.官方说明 开发者获取使用凭证后,可以使用该凭证对公众账号的自定义菜单进行创建.查询和删除等

微信公众平台开发(八) 自定义菜单功能开发

原文地址:http://www.cnblogs.com/mchina/p/3276878.html 一.简介 微信公众平台服务号以及之前成功申请内测资格的订阅号都具有自定义菜单的功能.开发者可利用该功能为公众账号的会话界面底部增加自定义菜单,用户点击菜单中的选项,可以调出相应的回复信息或网页链接.自定义菜单接口将为公众账号的信息展示空间提供更多可能性.本文将针对自定义菜单做简单的开发应用,以供读者参考. 二.官方说明 开发者获取使用凭证后,可以使用该凭证对公众账号的自定义菜单进行创建.查询和删除

微信公众平台开发(104) 自定义菜单扫一扫、发图片、发地理位置

关键字:微信公众平台 自定义菜单 扫一扫 发图片 发地理位置作者:方倍工作室原文:http://www.cnblogs.com/txw1958/p/weixin-menu-new-type.html 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的重要功能.微信增加了点击菜单后调起扫一扫(支持二维码/一维码).发图片.发地理位置的能力,需开发实现.原有自定义菜单开发权限的公众号,均可获得以上能力. 在这篇微信公众平台开发教程中,我们将介绍如何在自定义菜单上开发扫一扫.发图片.发地理

[转载]微信公众平台二次开发之自定义菜单接口

原文地址:微信公众平台二次开发之自定义菜单接口作者:糊涂人 今天在SAE上运行代码时出现了一个小问题,所以发一篇博客与大家分享,这也是我第一次写关于技术上的博客,希望大家帮忙顶顶 步骤1. 你要有一个公众号,自己申请,过程略,很简单的. 步骤2. 登陆进去->高级功能,这时候要想开发必须要输入url和token,这里方法我引一下别人的文章http://www.cnblogs.com/txw1958/p/wechat-tutorial.html. 步骤3. 如果上面的工作完成了,这个时候你会在高级

微信公众平台自定义菜单开发——创建菜单

自己从不会到最后做出来,所以好东西必须分享,所以我就给大家写一下过程 1.首先必须是成为微信的开发者,这样才有AppId 和AppSecret 2步就是获取access_token 在你的浏览器上输入https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET (注意连接中得appid=APPID&secret=APPSECRET 分别是你自己在微信

微信小店开发(3) 自定义菜单加入维权

微信小店中,需要在菜单中加入“维权”按钮,让用户可以到达维权页面加入方法如下:给对应名称为“我要维权”的菜单设置链接(view事件),URL为 https://mp.weixin.qq.com/payfb/payfeedbackindex?appid=wx830f2de3fabcdefg#wechat_webview_type=1&wechat_redirect 把其中的appid,换成当前公众账号的即可. 微信小店开发(3) 自定义菜单加入维权,布布扣,bubuko.com