-
PHP 微信 自定义菜单
2019-01-16 09:52:231.拥有一个微信公众账号,并获取到appid和appsecret(在公众平台申请内测资格,审核通过后可获得) 2.通过获取凭证接口获取到access_token 注意: access_token是第三方访问api资源的票据; access_token对应于...原文地址
在使用通用接口前,你需要做以下两步工作:
1.拥有一个微信公众账号,并获取到appid和appsecret(在公众平台申请内测资格,审核通过后可获得)
2.通过获取凭证接口获取到access_token
注意:
access_token是第三方访问api资源的票据;
access_token对应于公众号是全局唯一的票据,重复获取将导致上次获取的access_token失效。访问下面这个地址(注意替换你的appid和secret):
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
然后在浏览器能看到一下返回信息:
{“access_token”:“这里就是你的access_token”,“expires_in”:7200}header("Content-type: text/html; charset=utf-8"); define("ACCESS_TOKEN", "这里填入你上面获取到的access_token"); //创建菜单 function createMenu($data){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".ACCESS_TOKEN); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $tmpInfo = curl_exec($ch); if (curl_errno($ch)) { return curl_error($ch); } curl_close($ch); return $tmpInfo; } //获取菜单 function getMenu(){ return file_get_contents("https://api.weixin.qq.com/cgi-bin/menu/get?access_token=".ACCESS_TOKEN); } //删除菜单 function deleteMenu(){ return file_get_contents("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=".ACCESS_TOKEN); } $data = '{ "button":[ { "type":"click", "name":"首页", "key":"home" }, { "type":"click", "name":"简介", "key":"introduct" }, { "name":"菜单", "sub_button":[ { "type":"click", "name":"hello word", "key":"V1001_HELLO_WORLD" }, { "type":"click", "name":"赞一下我们", "key":"V1001_GOOD" }] }] }'; echo createMenu($data); //echo getMenu(); //echo deleteMenu();
-
php微信自定义菜单开发
2014-03-18 14:13:36微信自定义菜单需要有一个微信服务号,在开发之前需要获取access_token,获取方法很简单,登陆微信公众账号,进入开发者模式,就可以看到{开发者凭据}:下面AppId和AppSecret,开发者文档说明 : 接口调用请求说明...微信自定义菜单需要有一个微信服务号,在开发之前需要获取access_token,获取方法很简单,登陆微信公众账号,进入开发者模式,就可以看到{开发者凭据}:下面AppId和AppSecret,开发者文档说明 :
接口调用请求说明
http请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明
参数 是否必须 说明 grant_type 是 获取access_token填写client_credential appid 是 第三方用户唯一凭证 secret 是 第三方用户唯一凭证密钥,即appsecret
复制那段https链接到浏览器地址,把相应的APPID和APPSECRET替代为你自己的Appid和AppSecret,确定有浏览器会显示一行字符串,复制这个字符串中access_token=后面的那段字符串,这个就是开发自定义菜单需要用到的。自定义菜单代码具体如下:
<?php
header("Content-type: text/html; charset=utf-8");
$access="6NlcAQRqJONBcHFteTgq7uQ0e0ajzdZkR7mekGXzHO3tTEATwOBc-JuzfmUGkL8s98RQ0VUI8fT_sWWbQfr1tQFQq4dMT-4tAOxEhoI7pXIhHwem_OE1E_K14bSAWdDIY0ZnOGxxBhHfr5dBqs7HhA";
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access;
//创建菜单
function createMenu($data){
$curl = curl_init();//初始化curl会话
curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // 对认证证书来源的检查
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); // 从证书中检查SSL加密算法是否存在
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); // 模拟用户使用的浏览器
// curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
// curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
$tmpInfo = curl_exec($curl);//执行curl会话
if (curl_errno($curl)) {
return curl_error($curl);
}
curl_close($curl);
return $tmpInfo;
}$data = ' {
"button":[
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
{
"type":"click",
"name":"歌手简介",
"key":"V1001_TODAY_SINGER"
},
{
"name":"菜单",
"sub_button":[
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
{
"type":"view",
"name":"视频",
"url":"http://v.qq.com/"
},
{
"type":"click",
"name":"赞一下我们",
"key":"V1001_GOOD"
}]
}]
}';
echo createMenu($data);//创建菜单
?>运行代码:如果显示
{"errcode":0,"errmsg":"ok"}
则运行成功,把代码传上服务器,完成。
-
PHP 微信自定义菜单接口详解
2013-12-25 11:33:59微信自定义菜单接口 简介 PHP 开发者获取使用凭证(如何获取凭证)后,可以使用该凭证对公众账号的自定义菜单进行创建、查询和删除等操作。 自定义菜单接口可实现以下类型按钮: click(点击事件):用户点击...微信自定义菜单接口
简介
PHP 开发者获取使用凭证(如何获取凭证)后,可以使用该凭证对公众账号的自定义菜单进行创建、查询和删除等操作。 自定义菜单接口可实现以下类型按钮:click(点击事件):用户点击click类型按钮后,微信服务器会通过消息接口(event类型)推送点击事件给开发者,并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值进行消息回复。view(访问网页):用户点击view类型按钮后,会直接跳转到开发者指定的url中。
创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后,再次关注,则可以看到创建后的效果。 (PS:T不错的PHP Q扣峮:276167802,验证:csl)
菜单创建
接口说明
通过POST一个特定结构体,实现在微信客户端创建自定义菜单。
请求说明
http请求方式:POST
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
请求示例:{ "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "type":"view", "name":"歌手简介", "url":"http://www.tsingyuan.cn/" }, { "name":"菜单", "sub_button":[ { "type":"click", "name":"hello word", "key":"V1001_HELLO_WORLD" }, { "type":"click", "name":"赞一下我们", "key":"V1001_GOOD" }] }] }
创建后效果:
参数说明
参数 是否必须 说明
button 是 按钮数组,按钮个数应为2~3个
sub_button 否 子按钮数组,按钮个数应为2~5个
type 是 按钮类型,目前有click类型
name 是 按钮描述,既按钮名字,不超过16个字节,子菜单不超过40个字节key 类型为click必须按钮KEY值,用于消息接口(event类型)推送,不超过128字节
返回说明
正确的Json返回结果:
{"errcode":0,"errmsg":"ok"}
错误的Json返回结果
{"errcode":40018,"errmsg":"invalid button name size"}
统一返回码说明
菜单查询
接口说明
查询当前使用的自定义菜单结构。
请求说明
http请求方式:GET
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
返回说明//对应创建接口,正确的Json返回结果: {"menu":{"button":[{"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC","sub_button":[]},{"type":"click","name":"歌手简介","key":"V1001_TODAY_SINGER","sub_button":[]},{"name":"菜单","sub_button":[{"type":"click","name":"hello word","key":"V1001_HELLO_WORLD","sub_button":[]},{"type":"click","name":"赞一下我们","key":"V1001_GOOD","sub_button":[]}]}]}}
统一返回码说明
菜单删除
接口说明
取消当前使用的自定义菜单。
请求说明
http请求方式:GET
https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
返回说明
对应创建接口,正确的Json返回结果:{"errcode":0,"errmsg":"ok"}
以上是本文关于PHP 微信自定义菜单接口的详解,希望本文对广大php开发者有所帮助,感谢阅读本文。
-
PHP实现创建微信自定义菜单的方法示例
2020-10-19 12:56:02主要介绍了PHP实现创建微信自定义菜单的方法,结合实例形式分析了php创建微信自定义菜单的原理、步骤与具体实现技巧,需要的朋友可以参考下 -
微信自定义菜单生成php
2014-03-27 13:28:41微信自定义菜单生成php源码,部分内容已修改,验证效果可行 -
微信自定义菜单的创建/查询/取消php示例代码
2021-01-20 01:12:51微信公众帐号 服务号可以使用 自定义菜单功能。... * 微信自定义菜单的创建|查询|取消 */ class weixinMenu { public static $appid = null; // 申请得到的appid public static $secret = null; // 申请得到的secret -
微信自定义菜单
2018-04-12 19:41:38微信自定义菜单是用户请求微信端,所有不需要把代码保存到自己的服务器上,但是注意的是必须有access_token,而且access_token两个小时之后就会失效,所有在没有到两个小时的时候就要请求微信端生成新的access_token...微信自定义菜单是用户请求微信端,所有不需要把代码保存到自己的服务器上,但是注意的是必须有access_token,而且access_token两个小时之后就会失效,所有在没有到两个小时的时候就要请求微信端生成新的access_token。下面代码是我写的自定义函数在后面的代码会使用 这个文件叫function.php,注意的是我的第一个函数是实例化了一张表,这张表有appid和那些用户的数据 ,is_user,这个字段是用户选择了那个公众号,那个公众号的zh
<?php //如果在自定义函数里面使用lanwechat 必须要加\ //获取正在使用的公众号 function getCurrentMp(){ $mp=M('mp')->where('is_use=1')->find(); return $mp; } //获取access_token function getAccess_token(){ $mp=M('mp')->where('is_use=1')->find(); if(empty($mp)) return false; $id=$mp['id']; if(empty($mp['access_token']) || $mp['expire_time']<time()){ $appid=$mp['appid']; $appsecret=$mp['appsecret']; $url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret; include_once APP_PATH.'LaneWeChat/lanewechat.php'; $arr= \LaneWeChat\Core\Curl::callWebServer($url,'','GET'); if(isset($arr['access_token'])){ $data['access_token']=$arr['access_token']; $data['expire_time']=$arr['expires_in']+time()-200; M('mp')->where("id=$id")->save($data); return $arr['access_token']; }else{ return false; } }else{ return $mp['access_token']; } }
下面这个代码是lanewechat里面的一个menu.lib.php的代码改造了一下,在getMenu和delMenu调用了函数getAccess_token
<?php namespace LaneWeChat\Core; /** * 自定义菜单 * Created by PhpStorm. * User: lane * Date: 14-8-17 * Time: 下午3:12 * E-mail: lixuan868686@163.com * WebSite: http://www.lanecn.com */ class Menu{ /** * 添加菜单,一级菜单最多3个,每个一级菜单最多可以有5个二级菜单 * @param $menuList * array( * array('index'=>'1', 'pindex'=>'0', 'name'=>'一级菜单', 'type'=>'click', 'content'=>'aaa'), * array('index'=>'11', 'pindex'=>'1', 'name'=>'二级菜单', 'type'=>'event', 'content'=>'scancode_push'), * array('index'=>'2', 'pindex'=>'0', 'name'=>'一级菜单', 'type'=>'view', 'content'=>'http://www.baidu.com'), * ); * 'content'是view类型的URL或者其他类型的key * 'type'是菜单类型,如下: * 1、click:点击推事件,用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; * 2、view:跳转URL,用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 * 3、scancode_push:扫码推事件,用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。 * 4、scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框,用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 * 5、pic_sysphoto:弹出系统拍照发图,用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。 * 6、pic_photo_or_album:弹出拍照或者相册发图,用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 * 7、pic_weixin:弹出微信相册发图器,用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。 * 8、location_select:弹出地理位置选择器,用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。 * * @return bool */ public static function setMenu($menuList){ //转换type,去掉无用的mp_id,content,sort foreach($menuList as $key=>$menu){ if(@$menu['type'] == 'view'){ $menuList[$key]['url'] = $menu['content']; }else if(@$menu['type'] == 'click'){ $menuList[$key]['key'] = $menu['content']; }else if(@$menu['type'] == 'event'){ $menuList[$key]['type'] = $menu['content']; $menuList[$key]['key'] = 'K_' . rand(1000,9999); } unset($menuList[$key]['mp_id']); unset($menuList[$key]['content']); unset($menuList[$key]['sort']); } //树形排布 $menuList2 = $menuList; foreach($menuList as $k=>$menu){ $hasChild = false; foreach($menuList2 as $k2=>$menu2){ if($menu['index'] == $menu2['pindex']){ unset($menuList2[$k2]['index']); unset($menuList2[$k2]['pindex']); $menuList[$k]['sub_button'][] = $menuList2[$k2]; unset($menuList[$k2]); $hasChild = true; } } //有子菜单 if($hasChild){ unset($menuList[$k]['type']); unset($menuList[$k]['url']); unset($menuList[$k]['key']); } unset($menuList[$k]['index']); unset($menuList[$k]['pindex']); } // return $menuList; // exit; //整理格式 $data = array(); $menuList = array_values($menuList); $data['button'] = $menuList; //转换成JSON $data = json_encode($data,JSON_UNESCAPED_UNICODE); // return $data; // exit; //获取ACCESS_TOKEN // $accessToken = AccessToken::getAccessToken(); $accessToken = getAccess_token(); $url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='.$accessToken; $result = Curl::callWebServer($url, $data, 'POST'); if($result['errcode'] == 0){ //创建菜单成功 return true; } return $result; } /** * 获取微信菜单 * @return bool|mixed * * 返回:{"menu":{"button":[{"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC","sub_button":[]},{"type":"click","name":"歌手简介","key":"V1001_TODAY_SINGER","sub_button":[]},{"name":"菜单","sub_button":[{"type":"view","name":"搜索","url":"http://www.soso.com/","sub_button":[]},{"type":"view","name":"视频","url":"http://v.qq.com/","sub_button":[]},{"type":"click","name":"赞一下我们","key":"V1001_GOOD","sub_button":[]}]}]}} */ public static function getMenu(){ //获取ACCESS_TOKEN $accessToken = getAccess_token(); $url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='.$accessToken; return Curl::callWebServer($url, '', 'GET'); } /** * 获取微信菜单 * @return bool|mixed * * 成功返回:{"errcode":0,"errmsg":"ok"} */ public static function delMenu(){ //获取ACCESS_TOKEN $accessToken = getAccess_token(); $url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token='.$accessToken; return Curl::callWebServer($url, '', 'GET'); } /** * 添加菜单,一级菜单最多3个,每个一级菜单最多可以有5个二级菜单 * @param $menuListJson * { "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜单", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://www.soso.com/" }, { "type":"view", "name":"视频", "url":"http://v.qq.com/" }, { "type":"click", "name":"赞一下我们", "key":"V1001_GOOD" }] }] } *各参数的说明同setMenu($menuList)方法 * @return bool */ public static function setMenuJson($menuListJson){ //json格式 $data=$menuListJson; //此处获得token所调用的函数内部有改写,此处是可在SAE平台上运行的,实际应用过程中可 //根据运行平台的不同改写getAccessToken()函数 $accessToken = AccessToken::getAccessToken(); //创建默认菜单的请求地址 $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$accessToken; $result = Curl::callWebServer($url, $data, 'POST'); if($result['errcode'] == 0){ return true; } return $result; } /** * 添加个性化菜单,一级菜单最多3个,每个一级菜单最多可以有5个二级菜单 * @param $menuListJson * { "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜单", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://www.soso.com/" }, { "type":"view", "name":"视频", "url":"http://v.qq.com/" }, { "type":"click", "name":"赞一下我们", "key":"V1001_GOOD" }] }], "matchrule":{ "group_id":"2", "sex":"1", "country":"中国", "province":"广东", "city":"广州", "client_platform_type":"2" "language":"zh_CN" } } *除了匹配规则之中的参数,其余各参数的说明同setMenu($menuList)方法 *关于匹配,只有符合匹配条件的用户才会有上述定制的个性化菜单 * @return bool */ public static function setPersonalMenuJson($menuListJson){ //json格式 $data=$menuListJson; //此处获得token所调用的函数内部有改写,此处是可在SAE平台上运行的,实际应用过程中可 //根据运行平台的不同改写getAccessToken()函数 $accessToken = AccessToken::getAccessToken(); //请求地址与创建普通菜单有区别 //创建个性化菜单之前必须先创建默认菜单 $url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=".$accessToken; $result = Curl::callWebServer($url, $data, 'POST'); if($result['errcode'] == 0){ return true; } return $result; } }
下面这是menuController的控制器内容
<?php namespace Home\Controller; use Think\Controller; use LaneWeChat\Core\Menu; class MenuController extends Controller { private $mp; public function _initialize(){ $mp=getCurrentMp(); if(empty($mp)){ $this->error('无使用公众号',U('mp/index')); }else{ $this->mp=$mp; } } public function hh(){ echo getAccess_token(); } public function index(){ $mp=$this->mp; // dump($mp); // exit; $mp_id = $mp['id']; $data=M('mp_menu')->where("mp_id={$mp['id']}")->order('id')->select(); // dump($data); // exit; $data2=$data; foreach ($data as $k => $v) { foreach ($data2 as $k2 => $v2) { if($v['index']==$v2['pindex']){ $data[$k]['sub'][]=$v2; unset($data[$k2]); } } } $this->assign('mpInfo',$mp); $this->assign('list',$data); $this->display(); } public function menuedit(){ $mp=$this->mp; $mp_id = $mp['id']; $data=I('post.data'); foreach ($data as &$value) { $value['mp_id']=$mp['id']; } $mp = M('mp_menu')->where("mp_id=$mp_id")->delete(); $mp = M('mp_menu')->addAll($data); // $arr = array(); // foreach ($data as $key => $value) { // $row = array(); // $row['index'] = $value['index']; // $row['pindex'] = $value['pindex']; // $row['name'] = $value['name']; // $row['content'] =$value['content']; // $row['type'] = $value['type']; // $row['sort'] = $value['sort']; // $row['mp_id'] = $mp_id; // $arr[] = $row; // } // $mp = M('mp_menu')->where("mp_id=$mp_id")->delete(); // $mp = M('mp_menu')->addAll($arr); //创建微信公众号菜单 include APP_PATH .'LaneWeChat/lanewechat.php'; $ret=Menu::setMenu($data); // if ($mp) { // $this->success('添加成功!','Menu/index'); // }else{ // $this->error('添加失败!','Menu/index'); // } if($ret===true){ $this->ajaxReturn(array('msg'=>'成功')); }else{ $this->ajaxReturn(array('msg'=>$ret)); } } public function downmenu(){ $mp = $this->mp; $mp_id = $mp['id']; include APP_PATH . 'LaneWeChat/lanewechat.php'; $menu = Menu::getMenu($data); // print_r($menu); // // exit; // print_r($menu['menu']['button']); // exit; $menu = $menu['menu']['button']; $arr = array(); $index = 1; foreach ($menu as $key => &$value) { $value['mp_id']= $mp_id; $value['index'] = $index; $value['pindex'] = 0; $value['sort'] = $index; if(!empty($value['sub_button'])){ $value['type'] = '';//设置一级菜单,默认值 $value['content'] = '';//设置一级菜单,默认值 $sub_menu = $value['sub_button']; //把二级菜单入到变量$sub_menu unset($value['sub_button']); $arr[] = $value; $subindex = 1; foreach ($sub_menu as $subkey=>&$subvalue) { $subvalue['mp_id'] = $mp_id; $subvalue['index'] = $index . $subindex; $subvalue['pindex'] = $index; $subvalue['sort'] = $subindex; if($subvalue['type']== 'click'){ $subvalue['content'] = $subvalue['key']; unset($subvalue['key']); }else if($subvalue['type']=='view'){ $subvalue['content'] = $subvalue['url']; unset($subvalue['url']); }else { $subvalue['content'] = $subvalue['type']; $subvalue['type'] = 'event'; unset($subvalue['key']); } unset($subvalue['sub_button']); $arr[] = $subvalue; $subindex++; } }else{ if($value['type']== 'click'){ $value['content'] = $value['key']; unset($value['key']); }else if($value['type']=='view'){ $value['content'] = $value['url']; unset($value['url']); }else { $value['content'] = $value['type']; $value['type'] = 'event'; unset($value['key']); } unset($value['sub_button']); $arr[] = $value; } $index++; } // print_r($arr); // exit; $model = M('mp_menu'); $model->where("mp_id={$mp['id']}")->delete(); foreach ($arr as $key => $value) { $model->add($value); } $this->redirect('menu/index'); } public function delmenu(){ $mp=$this->mp; $mp_id=$mp['id']; $model=M('mp_menu')->where("mp_id=$mp_id")->delete(); $this->redirect('menu/index'); } }
最后在补一下我前台页面的代码,我用的是模版继承
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>layout 后台大布局 - Layui</title> <link rel="stylesheet" href="__PUBLIC__/layui/css/layui.css"> </head> <body class="layui-layout-body"> <div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo">layui 后台布局</div> <!-- 头部区域(可配合layui已有的水平导航) --> <!-- <ul class="layui-nav layui-layout-left"> <li class="layui-nav-item"><a href="">控制台</a></li> <li class="layui-nav-item"><a href="">商品管理</a></li> <li class="layui-nav-item"><a href="">用户</a></li> <li class="layui-nav-item"> <a href="javascript:;">其它系统</a> <dl class="layui-nav-child"> <dd><a href="">邮件管理</a></dd> <dd><a href="">消息管理</a></dd> <dd><a href="">授权管理</a></dd> </dl> </li> </ul> --> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item"> <a href="javascript:;"> <img src="http://t.cn/RCzsdCq" class="layui-nav-img"> 贤心 </a> <dl class="layui-nav-child"> <dd><a href="">基本资料</a></dd> <dd><a href="">安全设置</a></dd> </dl> </li> <li class="layui-nav-item"><a href="">退了</a></li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul class="layui-nav layui-nav-tree" lay-filter="test"> <li class="layui-nav-item layui-nav-itemed"> <a class="" href="javascript:;">公众号</a> <dl class="layui-nav-child"> <dd><a href="{:U('mp/index')}">公众号管理</a></dd> <dd><a href="javascript:;">消息管理</a></dd> <dd><a href="{:U('menu/index')}">自定义菜单</a></dd> <dd><a href="">超链接</a></dd> </dl> </li> <!-- <li class="layui-nav-item"> <a href="javascript:;">解决方案</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">列表一</a></dd> <dd><a href="javascript:;">列表二</a></dd> <dd><a href="">超链接</a></dd> </dl> </li> <li class="layui-nav-item"><a href="">云市场</a></li> <li class="layui-nav-item"><a href="">发布商品</a></li> --> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> <div style="padding: 15px;"> <block name="css"> </block> <block name="body">内容主题区域</block> </div> </div> <div class="layui-footer"> <!-- 底部固定区域 --> © layui.com - 底部固定区域 </div> </div> <script type="text/javascript" src="__PUBLIC__/layui/jquery-1.7.min.js"></script> <script src="__PUBLIC__/layui/layui.js"></script> <script> //JavaScript代码区域 layui.use('element', function(){ var element = layui.element; }); <block name="js"></block> </script> </body> </html>
自定义菜单页面
<extend name="Common:base" /> <block name="css"> <link rel="stylesheet" type="text/css" href="__PUBLIC__/admin/css/console.css"> </block> <block name="body"> <style> .mobile-preview { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; -khtml-user-select: none; user-select: none;} .menu-editor { left: 317px; display: block; max-width: 500px; width: 500px; height: 480px; border-radius: 0; border-color: #e7e7eb; box-shadow: none} .menu-editor .arrow { top: auto !important; bottom: 15px} .menu-editor .popover-title { margin-top: 0} .menu-delete { font-weight: 400; font-size: 12px;} .menu-submit { margin-right: 10px} </style> <div class="content-hd"> <h2>自定义菜单</h2> </div> <div class="mp-menu"> <div class='mobile-preview pull-left'> <div class='mobile-header'>{$mpInfo.name}</div> <div class='mobile-body'></div> <ul class='mobile-footer'> <volist name="list" id="menu"> <li class="parent-menu"> <a><i class="icon-sub hide"></i> <span data-type="{$menu.type}" data-content="{$menu.content}">{$menu.name}</span></a> <div class="sub-menu text-center hide"> <ul> <notempty="menu['sub']"> <volist name="menu['sub']" id="submenu"> <li> <a class="bottom-border"><span data-type="{$submenu.type}" data-content="{$submenu.content}">{$submenu.name}</span></a> </li> </volist> </notempty> <li class="menu-add"><a><i class="icon-add"></i></a></li> </ul> <i class="arrow arrow_out"></i> <i class="arrow arrow_in"></i> </div> </li> </volist> <li class="parent-menu menu-add"> <a><i class="icon-add"></i></a> </li> </ul> </div> <div class="pull-left" style="position:absolute"> <div class="popover fade right up in menu-editor"> <div class="arrow"></div> <h3 class="popover-title"> 菜单名称 <a class="pull-right menu-delete">删除</a> </h3> <div class="popover-content menu-content"></div> </div> </div> <div class="hide menu-editor-parent-tpl"> <form class="layui-form"> <p>已添加子菜单,仅可设置菜单名称。</p> <div class="layui-form-item" style="margin-top:50px"> <label class="layui-form-label">菜单名称</label> <div class="layui-input-block"> <input name="menu-name" class="layui-input"> <span class="layui-form-mid layui-word-aux">字数不超过5个汉字或16个字母</span> </div> </div> </form> </div> <div class="hide menu-editor-content-tpl layui-form"> <form class="form-horizontal "> <div class="layui-form-item" style="margin-top:50px"> <label class="layui-form-label">菜单名称</label> <div class="layui-input-block"> <input name="menu-name" class="layui-input"> <span class="layui-form-mid layui-word-aux">字数不超过13个汉字或40个字母</span> </div> </div> <div class="layui-form-item" style="margin-top:30px"> <label class="layui-form-label">菜单内容</label> <div class="layui-input-block"> <!--<label class="col-xs-5 font-noraml">--> <!--<input class="cuci-radio" type="radio" name="menu-type" value="text"> 文字消息--> <!--</label>--> <label class="col-xs-5 font-noraml"> <input class="cuci-radio" type="radio" name="menu-type" value="click"> 关键字 </label> <label class="col-xs-5 font-noraml"> <input class="cuci-radio" type="radio" name="menu-type" value="view"> 跳转网页 </label> <label class="col-xs-5 font-noraml"> <input class="cuci-radio" type="radio" name="menu-type" value="event"> 事件功能 </label> <label class="col-xs-5 font-noraml"> <input class="cuci-radio" type="radio" name="menu-type" value="miniprogram"> 小程序 </label> <!--<label class="col-xs-5 font-noraml">--> <!--<input class="cuci-radio" type="radio" name="menu-type" value="customservice"> 多客服--> <!--</label>--> </div> </div> <div class="layui-form-item editor-content-input" style="margin-top:30px"></div> </form> </div> <div style="clear:both"></div> <div style="width:830px;padding-top:40px;text-align:center"> <button class="layui-btn menu-submit" lay-filter="formDemo" >保存发布</button> <a href="{:U('downmenu')}" class="layui-btn layui-btn-danger">同步菜单</a> <a href="{:U('delmenu')}" class="layui-btn layui-btn-normal">删除菜单</a> </div> </div> <script type="text/javascript" src="__PUBLIC__/layui/jquery-1.7.min.js"></script> <script> $(function () { /** * 菜单事件构造方法 * @returns {menu.index_L2.menu} */ var menu = function () { this.version = '1.0'; this.$btn; this.listen(); }; /** * 控件默认事件 * @returns {undefined} */ var layer; layui.use('layer', function(){ layer = layui.layer; }); menu.prototype.listen = function () { var self = this; $('.mobile-footer').on('click', 'li a', function () { self.$btn = $(this); self.$btn.parent('li').hasClass('menu-add') ? self.add() : self.checkShow(); }).find('li:first a:first').trigger('click'); $('.menu-delete').on('click', function () { var index = layer.confirm('确定删除吗?', function () { self.del(), layer.close(index); }); }); $('.menu-submit').on('click', function () { self.submit(); }); }; /** * 添加一个菜单 * @returns {undefined} */ menu.prototype.add = function () { var $add = this.$btn.parent('li'), $ul = $add.parent('ul'); if ($ul.hasClass('mobile-footer')) { /* 添加一级菜单 */ var $li = $('<li class="parent-menu"><a class="active"><i class="icon-sub hide"></i> <span>一级菜单</span></a></li>').insertBefore($add); this.$btn = $li.find('a'); $('<div class="sub-menu text-center hide"><ul><li class="menu-add"><a><i class="icon-add"></i></a></li></ul><i class="arrow arrow_out"></i><i class="arrow arrow_in"></i></div>').appendTo($li); } else { /* 添加二级菜单 */ this.$btn = $('<li><a class="bottom-border"><span>二级菜单</span></a></li>').prependTo($ul).find('a'); } this.checkShow(); }; /** * 数据校验显示 * @returns {unresolved} */ menu.prototype.checkShow = function () { var $li = this.$btn.parent('li'), $ul = $li.parent('ul'); /* 选中一级菜单时显示二级菜单 */ if ($li.hasClass('parent-menu')) { $('.parent-menu .sub-menu').not(this.$btn.parent('li').find('.sub-menu').removeClass('hide')).addClass('hide'); } /* 一级菜单添加按钮 */ var $add = $('li.parent-menu:last'); $add.siblings('li').size() >= 3 ? $add.addClass('hide') : $add.removeClass('hide'); /* 二级菜单添加按钮 */ $add.siblings('li').map(function () { var $add = $(this).find('ul li:last'); $add.siblings('li').size() >= 5 ? $add.addClass('hide') : $add.removeClass('hide'); }); /* 处理一级菜单 */ var parentWidth = 100 / $('li.parent-menu:visible').size() + '%'; $('li.parent-menu').map(function () { var $icon = $(this).find('.icon-sub'); $(this).width(parentWidth).find('ul li').size() > 1 ? $icon.removeClass('hide') : $icon.addClass('hide'); }); /* 更新选择中状态 */ $('.mobile-footer a.active').not(this.$btn.addClass('active')).removeClass('active'); this.renderEdit(); return $ul; }; /** * 删除当前菜单 * @returns {undefined} */ menu.prototype.del = function () { var $li = this.$btn.parent('li'), $ul = $li.parent('ul'); var $default = function () { if ($li.prev('li').size() > 0) { return $li.prev('li'); } if ($li.next('li').size() > 0 && !$li.next('li').hasClass('menu-add')) { return $li.next('li'); } if ($ul.parents('li.parent-menu').size() > 0) { return $ul.parents('li.parent-menu'); } return $('null'); }.call(this); $li.remove(); this.$btn = $default.find('a:first'); this.checkShow(); }; /** * 显示当前菜单的属性值 * @returns {undefined} */ menu.prototype.renderEdit = function () { var $span = this.$btn.find('span'), $li = this.$btn.parent('li'), $ul = $li.parent('ul'); var $html = ''; if ($li.find('ul li').size() > 1) { /*父菜单*/ $html = $($('.menu-editor-parent-tpl').html()); $html.find('input[name="menu-name"]').val($span.text()).on('change keyup', function () { $span.text(this.value || ' '); }); $('.menu-editor .menu-content').html($html); } else { $html = $($('.menu-editor-content-tpl').html()); $html.find('input[name="menu-name"]').val($span.text()).on('change keyup', function () { $span.text(this.value || ' '); }); $('.menu-editor .menu-content').html($html); var type = $span.attr('data-type') || 'text'; $html.find('input[name="menu-type"]').on('click', function () { $span.attr('data-type', this.value || 'text'); var content = $span.data('content') || ''; var type = this.value; var html = function () { switch (type) { case 'miniprogram': var tpl = '<div><div class="layui-form-item"><label class="layui-form-label">appid</label><div class="layui-input-block"><input type="text" name="appid" required="" lay-verify="required" placeholder="appid" autocomplete="off" class="layui-input" value="{appid}"></div></div><div class="layui-form-item"><label class="layui-form-label">url</label><div class="layui-input-block"><input type="text" name="url" required="" lay-verify="required" placeholder="url" autocomplete="off" class="layui-input" value="{url}"></div></div><div class="layui-form-item"><label class="layui-form-label">pagepath</label><div class="layui-input-block"><input type="text" name="pagepath" required="" lay-verify="required" placeholder="pagepath" autocomplete="off" class="layui-input" value="{pagepath}"></div></div></div>'; var _appid = '', _pagepath = '', _url = ''; if (content.indexOf(',') > 0) { _appid = content.split(',')[0] || ''; _url = content.split(',')[1] || ''; _pagepath = content.split(',')[2] || ''; } $span.data('appid', _appid), $span.data('url', _url), $span.data('pagepath', _pagepath); return tpl.replace('{appid}', _appid).replace('{url}', _url).replace('{pagepath}', _pagepath); case 'customservice': case 'text': return '<div>回复内容<textarea style="resize:none;height:225px" name="content" class="form-control input-sm">{content}</textarea></div>'.replace('{content}', content); case 'view': return '<div class="layui-form-item layui-form-text"><label class="layui-form-label">跳转地址</label><div class="layui-input-block"><textarea placeholder="请输入内容" class="layui-textarea" name="content">{content}</textarea></div></div>'.replace('{content}', content); case 'click': return '<div class="layui-form-item layui-form-text"><label class="layui-form-label">匹配内容</label><div class="layui-input-block"><textarea placeholder="请输入内容" class="layui-textarea" name="content">{content}</textarea></div></div>'.replace('{content}', content); case 'event': var options = { 'scancode_push': '扫码推事件', 'scancode_waitmsg': '扫码推事件且弹出“消息接收中”提示框', 'pic_sysphoto': '弹出系统拍照发图', 'pic_photo_or_album': '弹出拍照或者相册发图', 'pic_weixin': '弹出微信相册发图器', 'location_select': '弹出地理位置选择器'}; var select = [], tpl = '<div class="layui-form-item layui-form-text" style="margin-bottom: auto;"><label class="layui-form-label"></label><div><label><input class="cuci-radio" name="content" type="radio" {checked} value="{value}"> {title}</label></div></div>'; if (!(options[content] || false)) { content = 'scancode_push'; $span.data('content', content); } for (var i in options) { select.push(tpl.replace('{value}', i).replace('{title}', options[i]).replace('{checked}', (i === content) ? 'checked' : '')); } return select.join(''); } }.call(this); var $html = $(html), $input = $html.find('input,textarea'); $input.on('change keyup click', function () { // 将input值写入到span上 $span.data(this.name, $(this).val() || $(this).html()); // 如果是小程序,合并内容到span的content上 if (type === 'miniprogram') { $span.data('content', $span.data('appid') + ',' + $span.data('url') + ',' + $span.data('pagepath')); } }); $('.editor-content-input').html($html); }).filter('input[value="{type}"]'.replace('{type}', type)).trigger('click'); } }; /** * 提交数据 * @returns {undefined} */ menu.prototype.submit = function () { var data = []; function getdata($span) { var menudata = {}; menudata.name = $span.text(); menudata.type = $span.attr('data-type'); menudata.content = $span.data('content') || ''; return menudata; } $('li.parent-menu').map(function (index, item) { if (!$(item).hasClass('menu-add')) { var menudata = getdata($(item).find('a:first span')); menudata.index = index + 1; menudata.pindex = 0; // menudata.sub = []; menudata.sort = index; data.push(menudata); $(item).find('.sub-menu ul li:not(.menu-add) span').map(function (ii, span) { var submenudata = getdata($(span)); submenudata.index = (index + 1) + '' + (ii + 1); submenudata.pindex = menudata.index; submenudata.sort = ii; data.push(submenudata); }); } }); // console.log(data);return; var data = (data == '')?'':data; // var load = layer.load(1); $.post( '{:U("menuedit")}', {data:data}, function (res) { layer.alert(JSON.stringify(res.msg)); // if(res.status=='0'){ // layer.close(load); // layer.alert(res.msg); // } // if(res.status=='1'){ // layer.close(load); // layer.msg(res.msg,{time:1000},function () { // }); // } }, "json" ) }; new menu(); }); </script> </block>
-
微信自定义菜单生成器
2016-01-19 10:47:03微信自定义菜单生成器 http://menu.fangbei.org/index.php -
微信自定义菜单PHP
2014-07-23 11:20:20ini_set('error_reporting', E_ALL | E_STRICT); ini_set('display_errors', 'Off');...//定义AppId,需要在微信公众平台申请自定义菜单后会得到 define(AppSecret, "6f999a86ed075c5231b43940 -
微信自定义菜单的处理开发示例
2021-01-20 00:08:48自定义菜单的创建 <?php define(APPID, 您的appid); define(APPSECRET, 您的appsecret ); $token_access_url = ... -
PHP生成微信自定义菜单
2017-08-17 17:44:002019独角兽企业重金招聘Python工程师标准>>> $arr_new = [];... foreach($menudata as $k=>$v) ...微信自定义菜单! 转载于:https://my.oschina.net/u/914487/blog/1512292 -
php 生成微信自定义菜单
2014-09-15 11:11:37<?php $xjson ='{ "button": [ { "type": "click", "name": "今日歌曲", "key": "V1001_TODAY_MUSIC" }, { "type": "click", -
php-微信自定义菜单按钮格式
2018-01-31 15:06:29这里想吐槽下微信把这个弄的很麻烦,经常不知道在哪错了,也没有一个明确的错误提醒特别格式和细节! 一点都不能差{ "button": [ { "type": "click", "name": "畅迪用法", "key": "1" }, { -
微信 自定义菜单 菜单响应 代码
2016-03-17 07:38:20除view类型可以直接在url中赋值跳转链接外,其它都需要在...<?php $appid = "wx"; $appsecret = "0a0b97ad97ee2"; $times= date('y年m月d日 H:i:s',time()); echo $times.""; $url = "https://api.weixin.qq.com/cgi- -
微信自定义菜单的添加 同步 删除
2018-04-13 08:08:22根据appid appsercet 请求服务器 服务器返回用户一个accesstoken 根据微信提供的接口参数accesstoken 对公众号添加自定义菜单<?php namespace Admin\Controller; use Think\Controller; use LaneWeChat\Core... -
微信自定义菜单说php json_encode不转义中文汉字的方法
2015-10-08 15:58:00最近在开发微信自定义菜单。 接口比较简单,就是按微信要求的格式post一段json数据过去就成。 但我的菜单中里有中文,json_encode后出现了类似"\u5c0f\u8c61" 的unicode字符。 请求发出后被微信接口告知: ... -
从微信自定义菜单说php json_encode不转义中文汉字的方法
2015-05-13 10:38:48最近在开发微信自定义菜单。 接口比较简单,就是按微信要求的格式post一段json数据过去就成。 但我的菜单中里有中文,json_encode后出现了类似"\u5c0f\u8c61" 的unicode字符。 请求发出后被微信接口告知: {"errcode... -
微信自定义菜单文件直接提交生成
2019-04-07 10:00:36微信公众平台开发——>基本配置——>...将以下代码保存为diancan_menu.php,并且在浏览器中直接运行该文件(比如 http://www.hiretianxia.cn/diancan/diancan_menu.php),将直接向微信服务器提交... -
PHP开发微信自定义菜单40033不转义中文的方法
2017-07-11 16:56:10http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html按照文档走,使用php执行,结果: {“errcode”:40033,”errmsg”:”invalid charset. please check your request, if include \uxxxx will ... -
php微信开发自定义菜单
2020-10-21 15:42:59主要为大家详细介绍了php微信开发自定义菜单,具有一定的参考价值,感兴趣的小伙伴们可以参考一下