代码参考自慕课网视频https://www.imooc.com/learn/616
博客:https://blog.youkuaiyun.com/John_rush/article/details/80632349
先上完整代码,再分别讲解吧!代码GitHub地址:https://github.com/xiaoming000/wechat_meau.git
完整的代码有四个文件,其中包含了上篇学的微信公众平台开发-被动消息回复的代码,涉及到这个的就不多讲了;
$str = sha1( implode( $array ) );
if( $str == $signature && $echostr ){
//第一次接入weixin api接口的时候
echo $echostr;
exit;
}else{
// 定义菜单
$meau = new Meau();
$meau -> definedItem();
// 消息回复
$this -> responseMsg();
}
这段代码就是index.php的构造函数中的初始化配置和其他操作,所以我们在非初始化请求中调用了definedItem这样一个方法,这个方法就是下来定义自定义菜单的;自定义菜单的官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013
当然如果是学习者,开通的个人订阅号是没有自定义菜单的接口权限的,所以如果是学习则需要申请开发测试号;
权限接口参照文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433401084;可以看到个人订阅号权限非常少;
申请文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421137522
接下来我们看看自定义菜单的方法吧:
public function definedItem(){
// 实例化公共方法
$pub_func = new PublicFunction();
header('content-type:text/html;charset=utf-8');
$access_token = $pub_func -> getWxAccessToken();
$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='.$access_token;
$postArr = array(
'button' => array(
array(
'name' => urlencode('菜单一'),
'type' => 'click',
'key' => 'item1',
),//第一个一级菜单
array(
'name' => urlencode('菜单二'),
'sub_button' => array(
array(
'name' => urlencode('歌曲'),
'type' => 'click',
'key' => 'songs',
),//第一个二级菜单
array(
'name' => urlencode('电影'),
'type' => 'view',
'url' => 'http://www.baidu.com',
),//第二个二级菜单
),
),//第二个一级菜单
array(
'name' => urlencode('菜单三'),
'type' => 'view',
'url' => 'http://www.qq.com',
),//第三个一级菜单
),
);
// 编码转换
$postJson = urldecode(json_encode($postArr));
$res = $pub_func->http_curl($url,'post','json',$postJson);
// echo "<hr>";
// var_dump($res);
} // definedItem() end
从官方文档中我们可以看到自定义菜单有9种事件类型,我们这里定义了用的比较多点击和链接类型的时间;
$access_token = $pub_func -> getWxAccessToken();
这里是获取access_token,这个方法定义在public.php中。关于access_token到底是什么,简单来说就是我们调用微信平台接口时附带的一把钥匙。
这是你的公众平台的标志,我们在微信公众平台下的接口开发,其实就是按照微信公众平台的格式接口要求发送相应的数据;当用户进入我们的微信公众平台的时候,向微信平台发送消息后再向我们的微信工作服务器发送 _GET["signature"];_GET["timestamp"];_GET["nonce"];和一段xml格式的数据(如果是初始化配置还包括echostr参数),我们的微信工作服务器根据xml数据作相应的处理,比如前面学习的根据时间相应返回xml消息;但是有些逻辑较复杂的应用便需要调用接口向微信平台发送相关数据,自定义菜单开发就是这样;
但是我们调用微信平台的接口当然需要表名我们的身份,才能对用户做出公众号的相关应用处理,access_token便是我们附带在接口数据发送时的身份参数;access_token由微信公众平台的appid和appsecret生成(如果使用过接口的话会发现其实基本都参不多是这样的),有效期为2个小时,过期后便需要重复申请生成;
所以我们在调用自定义菜单接口之前必须要先获取access_token,获取access_toke的接口附带appid和appsecret;想微信平台发送数据显然必须进行网络通讯,PHP中我们运用curl这样一个方法去进行;curl使用相关参数如果不明白可以看菜鸟教程:http://www.runoob.com/php/php-ref-curl.html,当然方法参数很多,也可以先看我们下面代码运用到的再去查看;
下面是public.php中的我们自己编写的公共方法http_curl()和getWxAccessToken()
public function http_curl($url, $method='get',$res='json',$arr=''){
// 1.初始化curl
$ch = curl_init();
// 2.设置curl参数
// 需要获取的URL地址,也可以在curl_init()函数中设置。
curl_setopt($ch, CURLOPT_URL, $url);
// 返回原生的(Raw)输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($method == 'post') {
// 启用时会发送一个常规的POST请求
curl_setopt($ch, CURLOPT_POST, 1);
// 全部数据使用HTTP协议中的"POST"操作来发送
curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
}
// 3.采集
$output = curl_exec($ch);
// 4.关闭
curl_close($ch);
if ($res = 'json') {
if (curl_error($ch)) {
// 请求发生错误,返回错误信息
return curl_error($ch);
}else{
// 请求正确返回结果
return json_decode($output, true);
}
}
}// html_curl() end
/* 将access_token存储在session中 */
public function getWxAccessToken(){
if ($_SESSION['access_token'] && $_SESSION['expire_time'] > time()) {
return $_SESSION['access_token'];
}else{
// 如果access_token不存在或者已经过期
$appid = 'wx70b222a95832e8b1';
$appsecret = 'afef21cf29c9e17c60c58ea37a210aa2';
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
$res = $this -> http_curl($url, 'get', 'json');
$access_token = $res['access_token'];
// 将获取到的access_token放到session中
$_SESSION['access_token'] = $access_token;
$_SESSION['expire_time'] = time() + 7000;
return $access_token;
}
}// getWxAccessToken() end
上面的代码经过上面的解释和代码注释应该不难看懂,把access_token存储在session中是比较好的方法,过期时间为2个小时7200秒,我们只要把过期时间设在这个前面就好了;
access_token获取的官方文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183
access_token获取设置好之后我们来回过去看自定义菜单的代码吧!回过去看代码器是会发现其实很简单,就是调用接口发送一个post的书数组数据!这就是我为什么每次发文章(或者说笔记)把完整代码放前面的原因,因为其实很多人只是不知道格式要求而已,代码有注释并不难理解;稍微解释下的是urldecode和urlencode这是对中文进行编码转换,以防止编码问题出现;还有借口附带的数据需要转换成json格式;这样自定义菜单就设置完成了;官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013
我们发现菜单的参数有三个type\name\key,type是菜单类型,总共有9种,我们在这里使用了常见的click点击和view链接事件。其中view会直接根据链接进行跳转,点击事件当然就需要我们做相关的处理了,我们这里就简单的返回纯文本数据吧,和昨天的方式一样的;代码在response.php中
index.php中的responseMsg()根据事件触发消息返回
// 菜单click事件触发
if( strtolower($postObj->Event) == 'click'){
$meau = new Meau();
$meau -> meau_res($postObj);
}
我们把回复消息的编码放在的definedItem中,这样编辑菜单方面只需要改动这一个文件就行,程序编写完之后可用性和可维护性是很重要的;
/**
* 菜单事件处理
* $postObj 微信平台获取的对象化的xml数据
*/
public function meau_res($postObj){
$info = array(
'toUser' => $postObj->FromUserName,
'fromUser' => $postObj->ToUserName,
'time' => time(),
'msgType' => 'text',
);
$key = $postObj->EventKey;
if(strtolower($key == 'item1')){
$info['content'] = "这是item1菜单的事件推送";
}elseif(strtolower($key == 'songs')){
$info['content'] = "这是歌曲菜单的事件推送";
} else {
$info['content'] = '未匹配'.print_r($postObj->EventKey, true);
}
// 纯文本消息回复
$response = new Response();
$response -> res_text($info);
} // meau_res() end
自定义菜单就先讲到这,其他时间安装文档应该不难,有时间我也可以在尝试后发表文章!