微信那点事儿-公众平台开发系列之自定义菜单(php版)

首先需要注意两个概念:服务号和订阅号

那么微信公众平台订阅号和服务号有什么区别呢?看看官方的解释:http://www.5icool.org/a/201308/a2086.html

因此,在使用自定义菜单之前,必须先申请获得服务号的权限,这个审核经过实践需要一周的时间,而且最近好像这方面的审核管理的比较松,只要合理的申请都能通过。

进入正题,我们先来看看创建自定义菜单的步骤和原理:

1.注册公众号、开通开发者模式时,平台将提供两个参数APPID、APPSECRET(订阅号不提供这两项参数)

2.自定义菜单前,必须先向平台申请一个使用凭证(AccessToken),方法如下:

用GET方式读取URL https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

其中:APPID,APPSECRET 用实际参数值代入

返回结果是一个JSON格式的文本,其中有AccessToken. (JSON是一种数据交换格式,不了解的同学要从头学一下才能明白)

      AccessToken不是永久有效的,返回结果中有一个失效时间,即过了XX秒后(一般是两个小时),AccessToken就会失效。

3.获得有效的AccessToken后,就可以进行自定义菜单的创建、删除操作了

3.1 创建菜单

     用POST方式向这个URL提交菜单定义数据, URL:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

其中:ACCESS_TOKEN 用实际参数值代入

    菜单定义数据是一个JSON格式的文本 (开发文档讲得不是那么清晰,让我理解了好一会),做为POST方式的提交数据

返回结果是一个JSON格式的文本,其中有操作成功码和出错信息

3.2 删除菜单

      用GET方式读取URL https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN

其中:ACCESS_TOKEN 用实际参数值代入

返回结果是一个JSON格式的文本,其中有AccessToken. (JSON是一种数据交换格式,不了解的同学要从头学一下才能明白)

      AccessToken不是永久有效的,返回结果中还有一个失效时间,即过了XX秒后(一般是两个小时),AccessToken就会失效。

上述过程需要开发者非常了解HTTP协议细节和JSON数据格式,这里,我将编码、测试没问题的核心代码贴在这里,供自己以后翻看,也希望对大家有用:

<?php
	header('Content-Type: text/html; charset=UTF-8');
	include_once("config.inc"); //包含系统配置文件 
	require_once 'dbop.inc';   //包含数据库操作
	$mydb=new dbUtil;  //数据库操作类
class Weixin
{
    public $token;//token
    public $debug;//是否debug的状态标示,方便我们在调试的时候记录一些中间数据
    public $setFlag;
    public $msgtype;   //('text','image','location')
    public $msgevent;
    public $EventKey;
    public $msg;
    function __construct(){
    	$this->debug =  true;//是否debug的状态标示,方便我们在调试的时候记录一些中间数据
	    $this->setFlag = false;
	    $this->msgtype = 'text';   //('text','image','location')
	    $this->msg = array(); 
        $this->token = "******";   //token ,共六位
		$this->__getMsg();
        $this->__createMenu();
    }
    function  __destruct(){
    	
    }
	public function __getMsg(){
		$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)) {
            $this->msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $this->msgtype = strtolower($this->msg['MsgType']);
			if($this->msgtype=='event'){
				$this->msgevent=$this->msg['Event'];
				$this->EventKey=$this->msg['EventKey'];
			}
        }
    }
	//回复文本消息
	public function __makeText($text=''){
	 	$CreateTime = time();
        $FuncFlag = $this->setFlag ? 1 : 0;
        $textTpl = "<xml>
            <ToUserName><![CDATA[{$this->msg['FromUserName']}]]></ToUserName>
            <FromUserName><![CDATA[{$this->msg['ToUserName']}]]></FromUserName>
            <CreateTime>{$CreateTime}</CreateTime>
            <MsgType><![CDATA[text]]></MsgType>
            <Content><![CDATA[%s]]></Content>
            <FuncFlag>%s</FuncFlag>
            </xml>";
        return sprintf($textTpl,$text,$FuncFlag);
	}
    //根据数组参数回复图文消息
	public function __makeNews($item=array(),$flag){
		$CreateTime = time();//其他数据貌似不好使 如$item['dateAndTime']
        $FuncFlag = $this->setFlag ? 1 : 0;
        $newTplHeader = "<xml>
            <ToUserName><![CDATA[{$this->msg['FromUserName']}]]></ToUserName>
            <FromUserName><![CDATA[{$this->msg['ToUserName']}]]></FromUserName>
            <CreateTime>{$CreateTime}</CreateTime>
            <MsgType><![CDATA[news]]></MsgType>
            <ArticleCount>%s</ArticleCount><Articles>";
        $newTplItem = "<item>
            <Title><![CDATA[%s]]></Title>
            <Description><![CDATA[%s]]></Description>
            <PicUrl><![CDATA[%s]]></PicUrl>
            <Url><![CDATA[%s]]></Url>
            </item>";
        $newTplFoot = "</Articles>
		<FuncFlag>%s</FuncFlag></xml>";
        $Content = '';
		$Content.= sprintf($newTplItem,$item['title'],$item['content'],'http://www.goldcjc.com/upload_file/'.$item['picurl'],$item['url']);
		$itemsCount=1;
        $header = sprintf($newTplHeader,$itemsCount);
        $footer = sprintf($newTplFoot,$FuncFlag);
        return $header.$Content.$footer;
	}

	public function __reply($data){
		if ($this->debug) {
           $this->__write_log($data);
        }
        echo $data;
	}

	public function __valid(){
		if ($this->__checkSignature()) {
            if( $_SERVER['REQUEST_METHOD']=='GET' )
            {
                echo $_GET['echostr'];
                exit;
            }
        }else{
            exit;
        }
	}

	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;
        }
	}

	public function __write_log($log){
    	$oldmask = @umask(0); 
		$fp = @fopen("weixinlog.log","w"); 
		@flock($fp, 3); 
		if(!$fp) { 
			return false; 
		} 
		else { 
			@fwrite($fp,$log); 
			@fclose($fp); 
			@umask($oldmask); 
			return true; 
			}
	}
	
	public function __getNewsFromDb($condition='',$mydb){
		$result = $mydb->execute($condition); 
		if(mysql_num_rows($result)) {   
		  	if($post = mysql_fetch_array($result,MYSQL_ASSOC)) { 
					return $post;
		   } else {
		   		return '';
		   }  
		}else {
			return '';
		}  
	}
	public function __createMenu(){
		
		$APPID="******************";
		$APPSECRET="********************************";
		$TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$APPID."&secret=".$APPSECRET;
		$json=file_get_contents($TOKEN_URL);
		$result=json_decode($json,true);
		$ACC_TOKEN=$result['access_token'];//跟token不是一个概念,位数都不同
		$data='{
		"button":[
		{
		"name":"菜单一",
		"sub_button":[
		{
		"type":"click",
		"name":"项一",
		"key":"CJSJGB"
		},
		{
		"type":"click",
		"name":"项二",
		"key":"MRSJJD"
		},
		{
		"type":"click",
		"name":"项三",
		"key":"CJPL"
		}]
		},
		{
		"name":"菜单二",
		"sub_button":[
		{
		"type":"click",
		"name":"项一",
		"key":"KHYL"
		},
		{
		"type":"click",
		"name":"项二",
		"key":"KHHK"
		},
		{
		"type":"click",
		"name":"项三",
		"key":"ZTHD"
		}]
		},
		{
		"name":"菜单三",
		"sub_button":[
		{
		"type":"click",
		"name":"项一",
		"key":"KHCX"
		},
		{
		"type":"click",
		"name":"项二",
		"key":"HQBJ"
		},
		{
		"type":"click",
		"name":"项三",
		"key":"YNJD"
		}]
		}]
		}';
		$MENU_URL="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$ACC_TOKEN;
		 $ch = curl_init();
		 curl_setopt($ch, CURLOPT_URL, $MENU_URL);
		 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;
	}
}
?>
<?php
$weixin=new Weixin;
$reply="";
$selectFlag=0;
$type = $weixin->msgtype;//消息类型
$msgevent = $weixin->msgevent;//消息事件
$eventkey = $weixin->EventKey;//事件键值
$username = $weixin->msg['FromUserName'];//哪个用户给你发的消息,这个$username是微信加密之后的,但是每个用户都是一一对应的
if ($type==='text') {
	$reply = $weixin->__makeText("未搜索到相应资源\n谢谢您的宝贵提醒!\n我们会尽快弥补不足!"); 
}elseif ($type==='location') {
	$reply = $weixin->__makeText("未搜索到相应资源\n谢谢您的宝贵提醒!\n我们会尽快弥补不足!");    	
}elseif ($type==='image') {
	$reply = $weixin->__makeText("未搜索到相应资源\n谢谢您的宝贵提醒!\n我们会尽快弥补不足!");    	
}elseif ($type==='voice') {     
	$reply = $weixin->__makeText("未搜索到相应资源\n谢谢您的宝贵提醒!\n我们会尽快弥补不足!");     
}elseif ($type==='event') {
	if ($msgevent=='subscribe'){//订阅
		$reply = $weixin->__makeText("谢谢您的关注!"); 
	}elseif ($msgevent=='unsubscribe'){//取消订阅,用户收不到任何信息
	
    }elseif ($msgevent=='CLICK'){
		if($eventkey=="CJSJGB"){
            $query="SELECT * FROM calendar ORDER BY  'dateAndTime' DESC LIMIT 0 , 10"; 
			$selectFlag=0;
        }elseif($eventkey=="MRSJJD"){
			$query="SELECT * FROM datainterpretation ORDER BY  'dateAndTime' DESC LIMIT 0 , 1"; 
			$selectFlag=1;
		}elseif($eventkey=="CJPL"){
			$query="select * from comment order by 'dateAndTime' desc LIMIT 0 , 1"; 
			$selectFlag=2;
		}elseif($eventkey=="KHYL"){
			$query="select * from present order by 'dateAndTime' desc LIMIT 0 , 1"; 
			$selectFlag=3;
		}elseif($eventkey=="KHHK"){
			$query="select * from feedback order by 'dateAndTime' desc LIMIT 0 , 1";
			$selectFlag=4;
		}elseif($eventkey=="ZTHD"){
			$query="select * from activity order by 'dateAndTime' desc LIMIT 0 , 1"; 
			$selectFlag=5;
		}elseif($eventkey=="KHCX"){
			$query="select * from query LIMIT 0 , 1";
			$selectFlag=6;
		}elseif($eventkey=="HQBJ"){
			$query="select * from background LIMIT 0 , 1";
			$selectFlag=7;
		}elseif($eventkey=="YNJD"){
			$query="select * from problem LIMIT 0 , 1";
			$selectFlag=8;
		}
		$postStr=$weixin->__getNewsFromDb($query,$mydb);
		$reply = $weixin->__makeNews($postStr,$selectFlag);
	}
}
$weixin->__reply($reply);
?>


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值