Alan Hou的个人博客

微信公众平台开发实战与应用案例读书笔记


微信公众平台开发实战与应用案例读书笔记
开发者模式接入
接收消息格式和参数描述
公众号接收消息代码实现
公众号回复消息代码实现

开发者模式接入

初始认证代码的基本原理就是通过GET方法获取时间戳、随机数,与后台中的TOKEN组合为一个数组进行字典序排序并使用SHA1进行加密。使用加密后的字串与GET方法获取的signature进行比对,若相同输出GET方法获取到的echostr返回字串。

<?php //填入微信后台中使用的TOKEN define("TOKEN",""); $wechatObj = new wechatCallbackapiTest(); $wechatObj->valid();

	class wechatCallbackapiTest{
		public function valid(){
			$echoStr = $_GET['echostr'];
			
			if($this->checkSignature()){
				echo $echoStr;
				exit;
			}
		}


		private function checkSignature(){
			//检查是否设置了TOKEN
			if(!defined("TOKEN")){
				throw new Exception('TOKEN is not defined!');
			}
			//获取认证签名、时间戳、随机数和TOKEN
			$signature = $_GET['signature'];
			$timestamp = $_GET['timestamp'];
			$nonce = $_GET['nonce'];
			$token = TOKEN;
			//创建时间戳、随机数和TOKEN为数组
			$tmpArr = array($token, $timestamp, $nonce);
			//进行字典序排序、拼接和加密
			sort($tmpArr, SORT_STRING);
			$tmpStr = implode($tmpArr);
			$tmpStr = sha1($tmpStr);
			//对比与签名是否相符
			if($tmpStr == $signature){
				return true;
			}else{
				return false;
			}
		}
	}	
?>

 

微信开发调试软件链接: http://pan.baidu.com/s/1sj3hFMP 密码: s62p

接收消息格式和参数描述

文本消息格式

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>

文本消息参数描述

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id,64位整型

图片消息格式

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[this is a url]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>

图片消息参数描述

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType image
PicUrl 图片链接
MediaId 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId 消息id,64位整型

语音消息格式

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>

语音消息参数描述

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 语音为voice
MediaId 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
Format 语音格式,如amr,speex等
MsgID 消息id,64位整型

视频消息格式

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA . ]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>

视频消息参数描述

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 视频为video
MediaId 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId 消息id,64位整型

地理位置消息格式

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml> 

地理位置消息参数描述

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType location
Location_X 地理位置维度
Location_Y 地理位置经度
Scale 地图缩放大小
Label 地理位置信息
MsgId 消息id,64位整型

链接消息格式

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公众平台官网链接]]></Title>
<Description><![CDATA[公众平台官网链接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml> 

链接消息参数描述

参数 描述
ToUserName 接收方微信号
FromUserName 发送方微信号,若为普通用户,则是一个OpenID
CreateTime 消息创建时间
MsgType 消息类型,link
Title 消息标题
Description 消息描述
Url 消息链接
MsgId 消息id,64位整型

公众号接收消息代码实现

代码下载链接: http://pan.baidu.com/s/1t4PcU 密码: edta

<?php //填入微信后台中使用的TOKEN define("TOKEN", ""); $wechatObj = new wechatCallbackapiTest(); if(!isset($_GET['echostr'])){ $wechatObj->responseMsg();
	}else{
		$wechatObj->valid();
	}	
	//回调类
	class wechatCallbackapiTest{
		public $fromUsername='';
		public $toUsername='';
		public function valid(){
			$echostr = $_GET['echostr'];
			if($this->checkSignature()){
				echo $echostr;
				exit;
			}
		}
		//官方验证方法
		private function checkSignature(){
			$signature = $_GET["signature"];
		    $timestamp = $_GET["timestamp"];
		    $nonce = $_GET["nonce"];	
        		
			$token = TOKEN;
			$tmpArr = array($token, $timestamp, $nonce);
			sort($tmpArr, SORT_STRING);
			$tmpStr = implode( $tmpArr );
			$tmpStr = sha1( $tmpStr );
			
			if( $tmpStr == $signature ){
				return true;
			}else{
				return false;
			}
		}
		//消息回复方法
		public function responseMsg(){
			$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
			$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA );
			$fromUsername = $postObj->FromUserName;
			$toUsername = $postObj->ToUserName;
			$type = $postObj->MsgType;
			$event=$postObj->Event;
			$Event_Key=$postObj->EventKey;
			$mid=$postObj->MediaId;
			$link=$postObj->Url;

			$latitude  = $postObj->Location_X;
			$longitude = $postObj->Location_Y;
            $keyword = trim($postObj->Content);
            $time = time();

            $textTpl = "<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[text]]></MsgType>
						<Content><![CDATA[%s]]></Content>
						</xml>";
            if($keyword!=''){$contentStr=$keyword;}
            //判断消息类型
			elseif($type == "image"){$contentStr = "您发送的是图片消息,消息的MediaId是".$mid;}
			elseif($type == "voice"){$contentStr = "您发送的是语音消息,消息的MediaId是".$mid;"内容是".$rec;}
			elseif($type == "video"){$contentStr = "您发送的是视频消息,消息的MediaId是".$mid;}
			elseif($type == "location"){$contentStr = "您发送的是地理位置消息,您的地理位置是:经度".$longitude."纬度".$latitude;}
			elseif($type == "link"){$contentStr = "您发送的链接信息,消息链接为".$link;}
			elseif($type == "event" && $event == "subscribe"){$contentStr = "欢迎您关注Alan的微信公众账号,让我们一起开启奇妙有趣的微信公众号开发之旅";}
			elseif($type == "event" && $event == "unsubscribe"){$contentStr = "期待您再次关注Alan的微信公众账号。";}
			else{echo "";}
			$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);
            echo $resultStr;
		}
	}

?>


公众号回复消息代码实现

链接: http://pan.baidu.com/s/1eQFb5QU 密码: c57t

<?php //填入微信后台中使用的TOKEN define("TOKEN", ""); $wechatObj = new wechatCallbackapiTest(); if(!isset($_GET['echostr'])){ $wechatObj->responseMsg();
	}else{
		$wechatObj->valid();
	}	
	//回调类
	class wechatCallbackapiTest{
		public $fromUsername='';
		public $toUsername='';
		public $time='';
		public function valid(){
			$echostr = $_GET['echostr'];
			if($this->checkSignature()){
				echo $echostr;
				exit;
			}
		}
		//官方验证方法
		private function checkSignature(){
			$signature = $_GET["signature"];
		    $timestamp = $_GET["timestamp"];
		    $nonce = $_GET["nonce"];	
        		
			$token = TOKEN;
			$tmpArr = array($token, $timestamp, $nonce);
			sort($tmpArr, SORT_STRING);
			$tmpStr = implode( $tmpArr );
			$tmpStr = sha1( $tmpStr );
			
			if( $tmpStr == $signature ){
				return true;
			}else{
				return false;
			}
		}
		//消息回复方法
		public function responseMsg(){
			$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
			$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA );
			$this->fromUsername = $postObj->FromUserName;
			$this->toUsername = $postObj->ToUserName;
			$type = $postObj->MsgType;
			$event=$postObj->Event;
			$Event_Key=$postObj->EventKey;
			$this->mid=$postObj->MediaId;
			$link=$postObj->Url;

			$latitude  = $postObj->Location_X;
			$longitude = $postObj->Location_Y;
            $this->keyword = trim($postObj->Content);
            $this->time = time();
            $this->find_type($type);
        }
        //判断用户发送的消息类型调用不同方法进行回复
        public function find_type($type){
        	switch($type){
        		case 'text':
            		$result=$this->fetch_text($this->keyword);
            		break;
            	case 'image':
	                $result=$this->fetch_image($this->mid);
	                break;
                case 'voice':
	                $result=$this->fetch_voice($this->mid);
	                break;
                case 'video':
	                $result=$this->fetch_video($this->mid);
	                break;
      
	            default:
	                $result=$this->fetch_default_text($this->keyword);
	                break;
        	}
        	echo $result;
        }

        //判断用户发送的文本内容
    	public function fetch_text($keyword){
	       switch ($keyword) {
	           	case '图片':
	             	$res=$this->fetch_image();
	              	break;
	            case '语音':
	             	$res=$this->fetch_voice();
	              	break;
	            case '视频':
	             	$res=$this->fetch_video();
	               	break;
	            case '音乐':
	            	$res=$this->fetch_music();
	              	break;
	            case '单图文':
	             	$res=$this->fetch_sigle_news();
	               	break;
	            case '多图文':
	             	$res=$this->fetch_muti_news();
	              	break;
	           
	           default:
	               $res=$this->fetch_default_text($keyword);
	               break;
	       	}
	      	return $res;
	    }

	    //回复文本消息
	    public function fetch_default_text($keyword){
	    	if($keyword=''){
	    		echo "";
	    	}else{
	    		$textTpl = "<xml>
							<ToUserName><![CDATA[%s]]></ToUserName>
							<FromUserName><![CDATA[%s]]></FromUserName>
							<CreateTime>%s</CreateTime>
							<MsgType><![CDATA[text]]></MsgType>
							<Content><![CDATA[%s]]></Content>
							</xml>";
				$contentStr="您发送的是文本消息,消息内容是:".$keyword;
				$resultStr = sprintf($textTpl, $this->fromUsername, $this->toUsername, $this->time, $contentStr);
            	return $resultStr;
	    	}
	    }

    	//回复图片消息
	    public function fetch_image($mid='O1roH6Z6lAglbpNycSRiSGAIX-0M5hPwrNMn24n6QHsTWBCI1s_smv3cHhrxN32X'){
	        $textTpl = "<xml>
					  	<ToUserName><![CDATA[%s]]></ToUserName>
					 	<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[image]]></MsgType>
						<Image>
						<MediaId><![CDATA[%s]]></MediaId>
						</Image>
						</xml>";

			$resultStr=sprintf($textTpl,$this->fromUsername,$this->toUsername,$this->time,$mid);
			return $resultStr;
	    }

	    //回复语音消息
	    public function fetch_voice($mid='q8GlXn_aIrRRQS2_3THhScuWhM-ZGR1e512eiyX7I_kAiJoRRtbTJvhQg9LWeuSR'){
	        $textTpl = '<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[voice]]></MsgType>
						<Voice>
						<MediaId><![CDATA[%s]]></MediaId>
						</Voice>
						</xml>';
			$resultStr=sprintf($textTpl,$this->fromUsername,$this->toUsername,$this->time,$mid);
			return $resultStr;
	    }

	    //回复视频消息
	    public function fetch_video($mid='OZ4dnt_nujz5_zRqlwYHUo_aF4zTqn8ub7X-dN5lXmOT0jmhPV2zjld5qc50ueOC'){
	        $textTpl = '<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA . ]></MsgType>
						<Video>
						<MediaId><![CDATA[%s]]></MediaId>
						<Title><![CDATA[%s]]></Title>
						<Description><![CDATA[%s]]></Description>
						</Video> 
						</xml>';
			$title="随手拍的小视频";
			$desc="随手拍书桌小视频,只有几秒钟,用来测试。视频文件不宜太大,微信上传视频有大小限制";
			$resultStr=sprintf($textTpl,$this->fromUsername,$this->toUsername,$this->time,$mid,$title,$desc);
			return $resultStr;
	    }

	    //回复音乐消息
	    public function fetch_music(){
	        $textTpl = '<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[music]]></MsgType>
						<Music>
						<Title><![CDATA[梦中的婚礼]]></Title>
						<Description><![CDATA[理查德.克里德曼,非常美妙的旋律,钢琴的至美境界]]></Description>
						<MusicUrl><![CDATA[%s]]></MusicUrl>
						<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
						<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
						</Music>
						</xml>';
			$music_url="http://alanhou.org/a.mp3";
			$hq_url="http://alanhou.org/a.mp3";
			$mid="mYBU_kavD71rqGKg34YV47YNNcHz88C47cL9vN5QkDXdI8L_zIyWsXNPmfwICLWE";
			$resultStr=sprintf($textTpl,$this->fromUsername,$this->toUsername,$this->time,$music_url,$hq_url,$mid);
			return $resultStr;
	    }


		//回复单图文消息;
	    public function fetch_sigle_news(){
	        $textTpl = '<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[news]]></MsgType>
						<ArticleCount>1</ArticleCount>
						<Articles>
						<item>
						<Title><![CDATA[%s]]></Title>
						<Description><![CDATA[%s]]></Description>
						<PicUrl><![CDATA[%s]]></PicUrl>
						<Url><![CDATA[%s]]></Url>
						</item>
						</Articles>
						</xml> ';
			$title="Test个人理财中心";
			$desc="提供保险,投资,理财咨询服务。你身边的投资理财专家。";
			$picurl="http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png";
			$url="http://alanhou.org/";
			$resultStr=sprintf($textTpl,$this->fromUsername,$this->toUsername,$this->time,$title,$desc,$picurl,$url);
			return $resultStr;
	    }

	    //回复多图文消息
	    public function fetch_muti_news(){
	        $textTpl = "<xml>
						<ToUserName><![CDATA[%s]]></ToUserName>
						<FromUserName><![CDATA[%s]]></FromUserName>
						<CreateTime>%s</CreateTime>
						<MsgType><![CDATA[news]]></MsgType>
						<ArticleCount>5</ArticleCount>
						<Articles>
						<item>
						        <Title><![CDATA[欢迎您!点击进入Alan Hou的首页]]></Title>
						        <Description><![CDATA[描述]]></Description>
						        <PicUrl><![CDATA[http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png]]></PicUrl>
						        <Url><![CDATA[http://alanhou.org]]></Url>
						    </item>

						    <item>
						        <Title><![CDATA[个人介绍]]></Title>
						        <Description><![CDATA[个人介绍]]></Description>
						        <PicUrl><![CDATA[http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png]]></PicUrl>
						        <Url><![CDATA[http://alanhou.org/]]></Url>
						    </item>

						    <item>
						        <Title><![CDATA[诚聘英才]]></Title>
						        <Description><![CDATA[招聘]]></Description>
						        <PicUrl><![CDATA[http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png]]></PicUrl>
						        <Url><![CDATA[http://alanhou.org/]]></Url>
						    </item>

						    <item>
						        <Title><![CDATA[微图文]]></Title>
						        <Description><![CDATA[图文]]></Description>
						        <PicUrl><![CDATA[http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png]]></PicUrl>
						        <Url><![CDATA[http://alanhou.org/]]></Url>
						    </item>

						    <item>
						        <Title><![CDATA[联系我]]></Title>
						        <Description><![CDATA[联系我]]></Description>
						        <PicUrl><![CDATA[http://alanhou.org/wp-content/uploads/2015/09/wechat-development-notes.png]]></PicUrl>
						        <Url><![CDATA[http://alanhou.org/]]></Url>
						    </item>
						</Articles>
						</xml>";
			 $resultStr = sprintf($textTpl, $this->fromUsername, $this->toUsername,time());
			 return $resultStr;
	    } 		    
	}
?>

开发模式进阶

Access Token的获取

在进行微信开发中Access Token是一相当重要的认证,需要通过AppID和AppSecret(均可在开发者中心中获取)来共同获取,有效期为7200秒即两个小时。

手动获取方法:

1.在浏览器中方法https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET(替换其中的APPID和APPSECRET),即可获取下面这样的返回数据

{"access_token":"ctjuJW0WmvwiNzYrYsbKAhRap4uqSwugWWjJunqmPhyavupm5iYAZVUAz7fmllRxLj7vYKDKQzyQIhUoEcQ7b57oyvYZKyaG7lDK_rMFk5g","expires_in":7200}

2.访问后台 开发者中心>在线接口调试工具,使用“获取access_token接口/token”,然后填写appid和secret,点击检查问题按钮即可以在下方获取同样的数据

使用代码获取Access Token

代码下载链接: http://pan.baidu.com/s/1pJ6BENx 密码: aykc

<?php //填写后台中的AppID和AppSecret获取Access Token
 $appid="";
 $secret="";
 $url="https://api.weixin.qq.com/cgi-bin/token? grant_type=client_credential&appid=$appid&secret=$secret";    
 GetToken($url);
 function GetToken($url){
 $ch=curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 $res=curl_exec($ch);
 $access_token=json_decode($res,true);
 echo $access_token['access_token'];
 }
?>

创建菜单

代码链接: http://pan.baidu.com/s/1o6iXf8e 密码: etj5

创建菜单接口:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=$token

查询菜单接口:https://api.weixin.qq.com/cgi-bin/menu/get?access_token=$token

删除菜单接口:https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=$token

代码实现菜单功能

链接: http://pan.baidu.com/s/1i3o6Xmd 密码: d4nd

 

退出移动版