3.1 Token验证

Token简单的说就是微信后台和公众账号服务器之间的秘钥,只有他们俩知道这个Token字符串。

Token验证过程

1. 微信后台向公众号服务器发送数据的时候,会额外携带4个参数:timestamp(时间戳)、nonce(随机数)、signature(对timestamp、nonce和Token进行SHA1加密后的字符串,加密过程不可逆,即不能通过其他三个计算出Token)、echostr(随机字符串,接入url时才有此参数)

2. 公众号服务器收到timestamp、nonce、signature之后,同样对timestamp、nonce和Token使用SHA1加密算法进行加密,得到自己的签名,如果接收到的签名和自己的签名是一样的,说明请求是来自微信后台而不是恶意的第三方

注:恶意的第三方有可能会截获timestamp、signature和nonce,然后直接利用这三个参数对公众账号服务器进行请求,这样公众账号服务器无法判断这是恶意请求,这种攻击叫replay攻击,防御方法很简单,加上对timestamp的校验,在收到请求后,将请求包中的timestamp与当前时间比较,如果误差大于一定值,就可以认为这个请求是恶意的。

3.2 请求消息

微信公众账号能够接收到的消息有文本(Text)、图片(image)、地理位置(location)、语音(voice)、视频(video)、事件(event)、链接消息(link)

1.请求文本消息

示例代码解读:

 



 3         //get post data, May be due to the different environments
 4         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
 5 
 6           //extract post data
 7         if (!empty($postStr)){
 8                 /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
 9                    the best way is to check the validity of xml by yourself */
10                 libxml_disable_entity_loader(true);
11                   $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
12                 $fromUsername = $postObj->FromUserName;
13                 $toUsername = $postObj->ToUserName;
14                 $keyword = trim($postObj->Content);
15                 $time = time();
16                 $textTpl = "<xml>
17                             <ToUserName><![CDATA[%s]]></ToUserName>
18                             <FromUserName><![CDATA[%s]]></FromUserName>
19                             <CreateTime>%s</CreateTime>
20                             <MsgType><![CDATA[%s]]></MsgType>
21                             <Content><![CDATA[%s]]></Content>
22                             <FuncFlag>0</FuncFlag>
23                             </xml>";             
24                 if(!empty( $keyword ))
25                 {
26                       $msgType = "text";
27                     $contentStr = "欢迎关注装修是家微信公众号!后续将为您提供更多精彩内容";
28                     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
29                     echo $resultStr;
30                 }else{
31                     echo "Input something...";
32                 }
33 
34         }else {
35             echo "";
36             exit;
37         }
38     }


 

第4行的作用是接收从微信公众账号服务端发送过来的代码

第11行的作用是通过simplexml_load_string将postStr字符串转换成对象格类型的数据,如下:

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <Content><![CDATA[%s]]></Content>
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

这样方便直接获取某个字段的数据。

第12行是获取用户的openid,可以表示发送方账号,但是不能通过这个openid在微信上找到对应的用户,而且对于不同的公众账号,同一个用户的openid是不一样的。

第13行是获取开发者的微信号公众账号

第14行是获取用户发送的消息内容

 2. 图片消息

微信后台对图片消息封装是这样的:

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <PicUrl><![CDATA[%s]]></PicUrl>
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

 3. 地理位置消息

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <Location_X><![CDATA[%s]]></Location_X>  地理位置纬度
  <Location_Y><![CDATA[%s]]></Location_Y>  地理位置经度
  <Scale>20</Scale>  地图缩放大小
  <Label><!DATA[%s]]></Label>  地理位置信息
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

 4. 语音消息 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <MediaId><![CDATA[%s]]></MediaId>  语音消息媒体id,可以调用多媒体文件下载接口拉取数据
  <Format><!DATA[%s]]></Format>  语音格式,如amr,speex等
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

 5. 视频消息

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <MediaId><![CDATA[%s]]></MediaId>  语音消息媒体id,可以调用多媒体文件下载接口拉取数据
  <ThumbMediaId><!DATA[%s]]></ThumbMediaId>  视频消息缩略图的媒体ID,可以调用多媒体文件下载接口拉取数据
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

 6. 链接消息

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <Title><![CDATA[%s]]></Title>  消息标题
  <Description><![CDATA[%s]]></Description>  消息描述
  <Url><![CDATA[%s]]></Url> 消息链接
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

 7. 事件消息

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <Event><![CDATA[%s]]></Event> 事件类型,有subscribe和unsubscribe
  <FuncFlag>0</FuncFlag>
</xml>
具体参照开发者文档

3.3 回复消息

1. 文本消息

 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>
  <Content><![CDATA[%s]]></Content>
</xml>

 

2. 图片消息

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType> //image
  <Image>
    <MediaId><![CDATA[%s]]></MediaId>
  </Image>
</xml>

 

3. 语音消息

 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>  //voice
  <Voice>
    <MediaId><![CDATA[%s]]></MediaId>
  </Voice>
</xml>

 

4. 音乐消息

 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>  //music
  <Music>
    <Title><![CDATA[%s]]></Title>  //音乐标题
    <Description><![CDATA[%s]]></Description>  //音乐描述
    <MusicUrl><![CDATA[%s]]></MusicUrl>  //音乐链接
    <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>  //高质量音乐链接,wifi环境下优先使用该链接播放
    <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
  </Music>
</xml>

 

5. 视频消息

 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>  //video
  <Video>
    <MediaId><![CDATA[%s]]></MediaId>  //语音消息媒体id,可以调用多媒体文件下载接口拉取数据
    <ThumbMediaId><!DATA[%s]]></ThumbMediaId>  //视频消息缩略图的媒体ID,可以调用多媒体文件下载接口拉取数据
  </Video>
</xml>

 

6. 图文消息

 

<xml>
  <ToUserName><![CDATA[%s]]></ToUserName>
  <FromUserName><![CDATA[%s]]></FromUserName>
  <CreateTime>%s</CreateTime>
  <MsgType><![CDATA[%s]]></MsgType>  //news
  <ArticleCount>2</ArticleCount> //图文消息个数,限制在10以内,默认第一个item为大图
  <Articles>  
  <item>
    <Title><![CDATA[%s]]></Title>  //图文消息标题
    <Description><![CDATA[%s]]></Description>  //图文消息描述
    <PicUrl><![CDATA[%s]]></PicUrl>  //图片链接
    <Url><![CDATA[%s]]></Url>  //消息链接
  </item>
  <item>
    <Title><![CDATA[%s]]></Title>  
    <Description><![CDATA[%s]]></Description> 
    <PicUrl><![CDATA[%s]]></PicUrl>
    <Url><![CDATA[%s]]></Url>
  </item>
  </Articles>
</xml>