php微信开发自定义菜单


Posted in PHP onAugust 27, 2016

目前微信服务号自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。 

目前自定义菜单接口可实现两种类型按钮,如下:
 click:
用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
view:
用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值 (即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息。 

接口调用请求说明
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN 
请求示例(JSON数据请使用UTF-8编码)

{
 "button":[
  {"type":"click","name":"我的信息","sub_button":[
   {"type":"click","name":"拇指查询","key":"BUTTON_1"},
  {"type":"click","name":"拇指请假","key":"BUTTON_2"},
  {"type":"view","name":"工号绑定","url":"http://XXXXXXXXXXXXXXXXX"}]
 },
  {"type":"click","name":"业务流程","key":"BUTTON_3"},
  {"name":"员工建议","sub_button":[
   {"type":"view","name":"思想火花","url":"http://XXXXXXXXXXXXXXXXXX"},
   {"type":"view","name":"奖品兑换","url":"http://XXXXXXXXXXXXXXXXXX"},
   {"type":"click","name":"赞一下我们","key":"BUTTON_ZAN"}]
  }
 ]
}

参数说明

php微信开发自定义菜单

返回结果 
正确时的返回JSON数据包如下:
 {"errcode":0,"errmsg":"ok"} 
错误时的返回JSON数据包如下(示例为无效菜单名长度):
 {"errcode":40018,"errmsg":"invalid button name size"} 

以下是示例代码(PHP)。        

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="author" content="Chris Mao" />
 </head>
 <body>
 <?php
  $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POST, 0);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

  $output = curl_exec($ch);
  curl_close($ch);
  if (empty($output)) { var_dump($output); exit; }
  $result = json_decode($output);
  $token = $result->access_token;
   
  //创建菜单
  $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=$token";
  $jsonData = file_get_contents("menu.json");
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
  curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  $output = curl_exec($ch);
  curl_close($ch); 
  var_dump($output);
 ?>
 </body>
</html>

menu.json 

{
 "button":[
  {"type":"click","name":"我的信息","sub_button":[
   {"type":"click","name":"拇指查询","key":"BUTTON_1"},
  {"type":"click","name":"拇指请假","key":"BUTTON_2"},
  {"type":"view","name":"工号绑定","url":"http://XXXXXXXXXXXXXXXXX"}]
 },
  {"type":"click","name":"业务流程","key":"BUTTON_3"},
  {"name":"员工建议","sub_button":[
   {"type":"view","name":"思想火花","url":"http://XXXXXXXXXXXXXXXXXX"},
   {"type":"view","name":"奖品兑换","url":"http://XXXXXXXXXXXXXXXXXX"},
   {"type":"click","name":"赞一下我们","key":"BUTTON_ZAN"}]
  }
 ]
}

 响应自定义菜单事件

$wechatObj = new wechatCallbackAPI();
 if (isset($_GET["echostr"])) { 
  $wechatObj->valid(); 
 } else { 
  $wechatObj->responseMsg();
 }


 class wechatCallbackAPI {

  private $token = "WEIXIN";

  private $appId = "APPID";

  private $appSecret = "APPSECRET";
  
  private function checkSignature() {
   $signature = $_GET["signature"];
   $timestamp = $_GET["timestamp"];
   $nonce = $_GET["nonce"]; 
     
   $tmpArr = array($this->token, $timestamp, $nonce);
   sort($tmpArr);
   $tmpStr = implode($tmpArr);
   $tmpStr = sha1($tmpStr);
   
   if($tmpStr == $signature) {
    return true;
   } else {
    return false;
   }
  }

  private function getAccessToken() {
   $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";

   $ch = curl_init($url);
   $curl_setopt($ch, CURLOPT_HEADER, 0);
   $curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $curl_setopt($ch, CURLOPT_POST, 0);
   $curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
   $curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

   $output = curl_exec($ch);
   curl_close($ch);
   if (empty($output)) { return ""; }

   $result = json_decode($result);
   return $result->access_token;
  }

  public function valid() {
   $echoStr = $_GET["echostr"];
   
   //valid signature, option
   if($this->checkSignature()){
    echo $echoStr;
    exit;
   }
  }
 
  public function responseMsg() {
   //get post data, May be due to the different environments
   $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
   if (empty($postStr)){
    echo "";
    exit;
   }

   //extract post data
   $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
   $fromUsername = $postObj->FromUserName;
   $toUsername = $postObj->ToUserName;
   $time = time();

   //文本消息模板
   $textTpl = "<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime>%s</CreateTime>
      <MsgType><![CDATA[%s]]></MsgType>
      <Content><![CDATA[%s]]></Content>
      <FuncFlag>0</FuncFlag>
      </xml>";
   
   switch (strtolower(trim($postObj->MsgType))) {
    case "text": //文本消息
     $keyword = trim($postObj->Content);
     if(!empty($keyword)) {
      $msgType = "text";
      $contentStr = "$fromUsername, 您发送了文本信息: $keyword ";
      if (strtolower($keyword) == "time") {
       $contentStr = date("Y-m-d H:i:s", $time);
      }
      $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     } else {
      $resultStr = "Input something...";
     }
     break;
    case "image": //图片消息
     $msgType = "text";
     $contentStr = "$fromUsername, 您发送了图片信息";
     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     break;
    case "voice": //声音消息
     $msgType = "text";
     $contentStr = "$fromUsername, 您发送了声音信息";
     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     break;
    case "video": //视频消息
     $msgType = "text";
     $contentStr = "$fromUsername, 您发送了视频信息";
     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     break;
    case "location": //位置消息
     $msgType = "text";
     $contentStr = "$fromUsername, 您发送了位置信息";
     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     break;
    case "link": //链接消息
     $msgType = "text";
     $contentStr = "$fromUsername, 您发送了链接信息";
     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
     break;
    case "event": //事件
     switch (strtolower(trim($postObj->Event))) {
      case "subscribe": //关注事件
       $msgType = "text";
       $contentStr = "欢迎您关注XXXXXXX";
       $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
       break;
      case "unsubscribe": //取消关注事件
       break;
      case "scan": //用户已关注时扫描二维码事件
       $msgType = "text";
       $contentStr = "$fromUsername, 您扫描了二维码";
       $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
       break;
      case "location": //上传地理位置事件
       $msgType = "text";
       $contentStr = "$fromUsername, 您上传地理位置";
       $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
       break;
      case "click": //自定义菜单事件
       $msgType = "text";
       $contentStr = "$fromUsername, 您点击了自定义菜单 $postObj->EventKey ";
       if ("BUTTON_ZAN" == $postObj->EventKey) {
        $contentStr = "感谢您的赞,我们会继续提供更优质的服务。";
       }
       $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
       ;
       break;
      default:
       $resultStr = "";
     }
     break;
    default:
     $resultStr = "";
   }
   echo $resultStr;
  }
 }
?>

自定义菜单查询 

使用接口创建自定义菜单后,开发者还可使用接口查询自定义菜单的结构。 

请求说明
 http请求方式:GET
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN

 返回说明
 对应创建接口,正确的Json返回结果:  

{"menu":{"button":[{"name":"我的信息","sub_button":[{"type":"click","name":"拇指查询","key":"BUTTON_1","sub_button":[]},{"type":"click","name":"拇指请假","key":"BUTTON_2","sub_button":[]},{"type":"view","name":"工号绑定","url":"http:\/\/XXXXXXXX","sub_button":[]}]},{"type":"click","name":"业务流程","key":"BUTTON_3","sub_button":[]},{"name":"员工建议","sub_button":[{"type":"view","name":"思想火花","url":"http:\/\/XXXXXXXX","sub_button":[]},{"type":"view","name":"奖品兑换","url":"http:\/\/XXXXXXXX","sub_button":[]},{"type":"click","name":"赞一下我们","key":"BUTTON_ZAN","sub_button":[]}]}]}}

自定义菜单删除 

使用接口创建自定义菜单后,开发者还可使用接口删除当前使用的自定义菜单。 

请求说明
http请求方式:GET
https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN

返回说明
 对应创建接口,正确的Json返回结果:
{"errcode":0,"errmsg":"ok"}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php的大小写敏感问题整理
Dec 29 PHP
php 深入理解strtotime函数的使用详解
May 23 PHP
php strrpos()与strripos()函数
Aug 31 PHP
PHP的MVC模式实现原理分析(一相简单的MVC框架范例)
Apr 29 PHP
php下获取http状态的实现代码
May 09 PHP
PHP中使用php5-ffmpeg撷取视频图片实例
Jan 07 PHP
在Nginx上部署ThinkPHP项目教程
Feb 02 PHP
PHP 获取ip地址代码汇总
Jul 05 PHP
PHP7新特性foreach 修改示例介绍
Aug 26 PHP
PHP获取数组中单列值的方法
Jun 10 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP getName()函数讲解
Feb 03 PHP
PHP7新特性foreach 修改示例介绍
Aug 26 #PHP
简单的自定义php模板引擎
Aug 26 #PHP
PHP flush 函数使用注意事项
Aug 26 #PHP
PHP获取不了React Native Fecth参数的解决办法
Aug 26 #PHP
简单的pgsql pdo php操作类实现代码
Aug 25 #PHP
php mongodb操作类 带几个简单的例子
Aug 25 #PHP
php flush无效,IIS7下php实时输出的方法
Aug 25 #PHP
You might like
S900/ ETON E1-XM 收音机
2021/03/02 无线电
php中mysql模块部分功能的简单封装
2011/09/30 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
php获取url参数方法总结
2014/11/13 PHP
Yii2 批量插入、更新数据实例
2017/03/15 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
彪哥1.1(智能表格)提供下载
2006/09/07 Javascript
使用prototype.js进行异步操作
2007/02/07 Javascript
一个判断抢购时间是否到达的简单的js函数
2014/06/23 Javascript
js实现搜索框关键字智能匹配代码
2020/03/26 Javascript
JS从一组数据中找到指定的单条数据的方法
2016/06/02 Javascript
JavaScript实现广告弹窗效果
2016/08/09 Javascript
详解javascript获取url信息的常见方法
2016/12/19 Javascript
在 Node.js 中使用原生 ES 模块方法解析
2017/09/19 Javascript
Vue+Mock.js模拟登录和表格的增删改查功能
2018/07/26 Javascript
微信小程序云开发之使用云存储
2019/05/17 Javascript
微信小程序—setTimeOut定时器的问题及解决
2019/07/26 Javascript
JS实现页面鼠标点击出现图片特效
2020/08/19 Javascript
[49:21]完美世界DOTA2联赛循环赛 Ink Ice vs LBZS BO2第二场 11.05
2020/11/06 DOTA
python计算最小优先级队列代码分享
2013/12/18 Python
python Tkinter的图片刷新实例
2019/06/14 Python
Python中顺序表原理与实现方法详解
2019/12/03 Python
使用Python求解带约束的最优化问题详解
2020/02/11 Python
打包PyQt5应用时的注意事项
2020/02/14 Python
Python Selenium截图功能实现代码
2020/04/26 Python
让你相见恨晚的十个Python骚操作
2020/11/18 Python
汽车专业人才自我鉴定范文
2013/12/29 职场文书
实验心得体会
2014/09/05 职场文书
快递员岗位职责
2014/09/12 职场文书
党的群众路线教育实践活动组织生活会发言材料
2014/10/17 职场文书
财务部会计岗位职责
2015/02/03 职场文书
2015教师年度思想工作总结
2015/04/30 职场文书
2015年幼儿教育工作总结
2015/07/24 职场文书
干部考核工作总结2015
2015/07/24 职场文书
2016年安全生产先进个人事迹材料
2016/02/29 职场文书
Vue-Element-Admin集成自己的接口实现登录跳转
2021/06/23 Vue.js