php微信公众平台交互与接口详解


Posted in PHP onNovember 28, 2016

本文分为三大部分为大家进行介绍,具体内容如下

1、微信用户、微信服务器和后台服务器的交互

例:微信用户向公众号发送一条文本消息,这条消息会首先传给微信服务器,微信服务器处理这条信息并将其以xml数据格式传递给后台服务器,后台服务器接受到数据后会对数据进行处理,再响应数据以xml数据格式传递给微信服务器,微信服务器再响应到用户微信界面。
微信用户与微信后台服务器之间的交互过程就是数据传递过程,只不过需要需要通过微信服务器这个中转站。

那么微信服务器这个中转站到底有什么用?
对xml数据进行加工包装后展现在手机屏幕上。我们接受的图文消息,如下:

单图文:

php微信公众平台交互与接口详解

多图文

php微信公众平台交互与接口详解

你会发现微信上几乎所有的图文都是这种格式,板式、大小都是一样,这就是经过微信服务器包装后的结果。

2、交互的数据类型

微信用户可以发送的数据类型
1、文本型(text)

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

2、语音(voice)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<Format><![CDATA[amr]]></Format>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
<Recognition><![CDATA[]]></Recognition>//recognition表示语音识别的结果
</xml>

3、图片( img)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz/L4qjYtOibummHn90t1mnaibYiaR8ljyicF3MW7XX3BLp1qZgUb7CtZ0D]]></PicUrl>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
</xml>

每一条消息传给微信服务器后都会被标记一个MsgId,上传的图片、视频、语音等也会被标记一个mediaId。

4、视频(video)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[vedio]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
<ThumbMediaId><![CDATA[mxUJ5gcCeesJwx2T9qsk62YzI
clCP_HnRdfTQcojlPeT2G9Q3d22UkSLyBFLZ01J]]></ThumbMediald>;//视频静止时显示那张图片地址
</xml>

5、地理位置消息(location)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<Location_X>22.539968</Location_X>
<Location_Y>113.954980</Location_Y>
<Scale>16</Scale>
<Label><![CDATA[中国广东省深圳市南山区深南大道9001号 
邮政编码: 518053]]></Label>
</xml>

6、链接消息(link)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<Title><![CDATA[微信公众平台开发者的江湖]]></Title>
<Description><![CDATA[陈坤的微信公众号这段时间大火,大家...]]></Description>
<Url><![CDATA[http://www.cnblogs.com/txw1958/]]></Url>
<MsgId>5839907284805129867</MsgId>
</xml>

后台服务器响应的消息类型
1、文本型(text)
2、语音(voice)

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

3、图片( img)

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

4、视频(video)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[vedio]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<video>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
<ThumbMediaId><![CDATA[mxUJ5gcCeesJwx2T9qsk62YzI
clCP_HnRdfTQcojlPeT2G9Q3d22UkSLyBFLZ01J]]></ThumbMediald>;//视频静止时显示那张图片地址
</video>
</xml>

5、音乐(music)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<Music>
<Title><![CDATA[最炫民族风]]></Title>
<Description><![CDATA[凤凰传奇]]></Description>
<MusicUrl><![CDATA[http://zj189.cn/zj/download/music/zxmzf.mp3]]></MusicUrl>
<HQMusicUrl><![CDATA[http://zj189.cn/zj/dodownload/music/zxmzf.mp3]]></HQMusicUrl>
</Music>
</xml>

6、图文(news)

<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<MsgId>5836982871638042400</MsgId>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
<item>
<Title><![CDATA[ 【深圳】实况 温度:6℃ 湿度:62? 风速:东北风2级]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
<item>
<Title><![CDATA[ 【深圳】实况 温度:6℃ 湿度:62? 风速:东北风2级]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
</Articles>
</xml>

上面代码在数据填写方面只做参照。以上代码在需要的时候调用即可,这里只是为大家展现以下数据格式。
CDATA是一个标记,被其标记的文本数据中不会被xml解析器进行解析。一个 CDATA 部件以"

ToUserName  接收方帐号
FromUserName  发送方帐号
CreateTime 发送事件
MsgType  数据类型
Content   文本内容
ArticleCount  图文数量
MsgId  数据id
MediaId  媒介id
Title  标题
Description  描述
MusicUrl   音乐连接地址
HQMusicUrl  高品质音乐连接地址

2、具体的交互步骤即代码

在上一章图2中,我们为测试号定义了url和token。url就是与微信服务器进行通信的后台服务器地址,而token一个相当于一个令牌。微信服务器与后台服务器进行通信时会出示该令牌,如果后台服务器发现微信服务器与自己携带的令牌相同才会进行通信,不相同则拒绝通信 。这个过程叫做token验证(这个令牌不是token的值)。
上面比较形象的说话,下面我通过代码来解释
例如:url为http://weixinceshi111111.applinzi.com/index2.php
token:weixin
index2.php代码

<?php
//
// 响应用户消息
// 微信公众账号响应给用户的不同消息类型
//微信服务器要和后台服务器进行通信首先要进行token验证,微信会通过get方式发送signature(微信加密签名)、nonce(随机数)、timestamp(时间戳)、echostr(随机字符串)。后台服务器获取之后会将timestamp、nonce与自身定义的TOKEN按照一定的顺序拼接成字符串,通过shal加密后获得的结果与signature进行对比,如果相同则把echostr返回给微信服务器。 表示验证成功。
header("content-type:text;charset=utf8");
define("TOKEN", "weixin");
//token验证是通过get传输数据,微信用户发送的数据通过post方式发送。先进行get请求,再进行post请求。
$wechatObj = new wechatCallbackapiTest();
//判断是get请求还是post请求。$_GET['echostr']如果存在,表示是进行token验证的get请求。反之是传输数据的post请求。
if (!isset($_GET['echostr'])) {
 $wechatObj->responseMsg();//响应数据
}else{
 $wechatObj->valid();//响应
}

class wechatCallbackapiTest
{
 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);//对数组中的元素进行排序
 $tmpStr = implode($tmpArr);//将数组中的元素连接成一个字符串
 $tmpStr = sha1($tmpStr);//对字符串进行加密操作。

 if($tmpStr == $signature){
 return true;
 }else{
 return false;
 }
 }

 public function responseMsg()
 {
 $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];//获取发送过来的数据。
 if (!empty($postStr)){
 $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', );//把xml字符串载入到一个SimpleXMLelement对象中。simplexml_load_string()是一种xml解析器。
 $RX_TYPE = trim($postObj->MsgType);//trim去掉字符串两端kongge。

 //用户发送的消息类型判断
 switch ($RX_TYPE)
 {
 case "text":
  $result = $this->receiveText($postObj);
  break;
 case "image":
  $result = $this->receiveImage($postObj);
  break;
 case "voice":
  $result = $this->receiveVoice($postObj);
  break;
 case "video":
  $result = $this->receiveVideo($postObj);
  break;
 default:
  $result = "unknow msg type: ".$RX_TYPE;
  break;
 }
 echo $result;
 }else {
 echo "";
 exit;
 }
 }

 private function receiveText($object)
 {
 $keyword = trim($object->Content);

 if($keyword == "文本"){
 //回复文本消息
 $content = "这是个文本消息";
 $result = $this->transmitText($object, $content);
 }
 else if($keyword == "图文" || $keyword == "单图文"){
 //回复单图文消息
 $content = array();
 $content[] = array("Title"=>"单图文标题", 
  "Description"=>"单图文内容", 
  "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", 
  "Url" =>"http://m.cnblogs.com/?u=txw1958");
 $result = $this->transmitNews($object, $content);
 }
 else if($keyword == "多图文"){
 //回复多图文消息
 $content = array();
 $content[] = array("Title"=>"多图文1标题", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
 $content[] = array("Title"=>"多图文2标题", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
 $content[] = array("Title"=>"多图文3标题", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
 $result = $this->transmitNews($object, $content);

 }
 else if($keyword == "音乐"){
 //回复音乐消息
 $content = array("Title"=>"最炫民族风", 
 "Description"=>"歌手:凤凰传奇", 
 "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3",
 "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3");
 $result = $this->transmitMusic($object, $content);
 }

 return $result;
 }

 private function receiveImage($object)
 {
 //回复图片消息 
 $content = array("MediaId"=>$object->MediaId);
 $result = $this->transmitImage($object, $content);;
 return $result;
 }

 private function receiveVoice($object)
 {
 //回复语音消息 
 $content = array("MediaId"=>$object->MediaId);
 $result = $this->transmitVoice($object, $content);;
 return $result;
 }

 private function receiveVideo($object)
 {
 //回复视频消息 
 $content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->ThumbMediaId, "Title"=>"", "Description"=>"");
 $result = $this->transmitVideo($object, $content);;
 return $result;
 } 

 /*
 * 回复文本消息,将要回复的xml消息进行包装。
 */
 private function transmitText($object, $content)
 {
 $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
 $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);//sprintf()这个函数的作用还是比较有意思的,可以搜索看看。
 return $result;
 }

 /*
 * 回复图片消息
 */
 private function transmitImage($object, $imageArray)
 {
 $itemTpl = "<Image>
 <MediaId><![CDATA[%s]]></MediaId>
</Image>";

 $item_str = sprintf($itemTpl, $imageArray['MediaId']);

 $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
$item_str
</xml>";

 $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
 return $result;
 }

 /*
 * 回复语音消息
 */
 private function transmitVoice($object, $voiceArray)
 {
 $itemTpl = "<Voice>
 <MediaId><![CDATA[%s]]></MediaId>
</Voice>";

 $item_str = sprintf($itemTpl, $voiceArray['MediaId']);

 $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
$item_str
</xml>";

 $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
 return $result;
 }

 /*
 * 回复视频消息
 */
 private function transmitVideo($object, $videoArray)
 {
 $itemTpl = "<Video>
 <MediaId><![CDATA[%s]]></MediaId>
 <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
 <Title><![CDATA[%s]]></Title>
 <Description><![CDATA[%s]]></Description>
</Video>";

 $item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'], $videoArray['Title'], $videoArray['Description']);

 $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
$item_str
</xml>";

 $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
 return $result;
 }

 /*
 * 回复图文消息
 */
 private function transmitNews($object, $arr_item)
 {
 if(!is_array($arr_item))
 return;

 $itemTpl = " <item>
 <Title><![CDATA[%s]]></Title>
 <Description><![CDATA[%s]]></Description>
 <PicUrl><![CDATA[%s]]></PicUrl>
 <Url><![CDATA[%s]]></Url>
 </item>
";
 $item_str = "";
 foreach ($arr_item as $item)
 $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);

 $newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";

 $result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item));
 return $result;
 }

 /*
 * 回复音乐消息
 */
 private function transmitMusic($object, $musicArray)
 {
 $itemTpl = "<Music>
 <Title><![CDATA[%s]]></Title>
 <Description><![CDATA[%s]]></Description>
 <MusicUrl><![CDATA[%s]]></MusicUrl>
 <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>";

 $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);

 $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
$item_str
</xml>";

 $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
 return $result;
 }
}
?>

3.接口

3.1 接口是什么

接口就相当于一个工具,具备特定的功能。比如你在建造房子的时候需要在墙上钻孔,你就会使用钻机工具来钻孔。从调来工具到钻孔完成,你要完成插电、校准、钻孔等一系列步骤,最终实现你的目标。钻机就是我们的接口,插电、校准、钻孔就是我们调用工具完成目的步骤。

微信的创建菜单接口举例。

调用接口的步骤:
1、获得微信菜单接口的连接地址,通过curl函数与这个接口建立对话。
2、把创建菜单数据发送给这个接口。
接口调用完成,这个接口会自动把这些数据进行处理并在微信公众好页面生成菜单。

微信接口的调用方式请看下一章:微信公众平台开发(三):微信高级接口的调用。

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

PHP 相关文章推荐
PHP 手机归属地查询 api
Feb 08 PHP
利用php绘制饼状图的实现代码
Jun 07 PHP
IIS+fastcgi下PHP运行超时问题的解决办法详解
Jun 20 PHP
使用swoole扩展php websocket示例
Feb 13 PHP
PhpDocumentor 2安装以及生成API文档的方法
May 21 PHP
完美解决thinkphp验证码出错无法显示的方法
Dec 09 PHP
php多线程实现方法及用法实例详解
Oct 26 PHP
thinkphp关于简单的权限判定方法
Apr 03 PHP
php 7新特性之类型申明详解
Jun 06 PHP
PHP按符号截取字符串的指定部分的实现方法
Sep 10 PHP
centos7上编译安装php7以php-fpm方式连接apache
Nov 08 PHP
tp5.1 框架查询表达式用法详解
May 25 PHP
php微信公众号开发模式详解
Nov 28 #PHP
jQuery+php简单实现全选删除的方法
Nov 28 #PHP
PHP中的use关键字及文件的加载详解
Nov 28 #PHP
php连接微软MSSQL(sql server)完全攻略
Nov 27 #PHP
php源码之将图片转化为data/base64数据流实例详解
Nov 27 #PHP
PHP使用curl函数发送Post请求的注意事项
Nov 26 #PHP
laravel创建类似ThinPHP中functions.php的全局函数
Nov 26 #PHP
You might like
PHP 多维数组排序实现代码
2009/08/05 PHP
PHP 字符串分割和比较
2009/10/06 PHP
php 一元分词算法
2009/11/30 PHP
php中global和$GLOBALS[]的分析之一
2012/02/02 PHP
php生成缩略图填充白边(等比缩略图方案)
2013/12/25 PHP
php网页病毒清除类
2014/12/08 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
laravel 出现command not found问题的解决方案
2019/10/23 PHP
Javascript 中的 &amp;&amp; 和 || 使用小结
2010/04/25 Javascript
js onkeypress与onkeydown 事件区别详细说明
2012/12/13 Javascript
JS 各种网页尺寸判断实例方法
2013/04/18 Javascript
使用Jquery获取带特殊符号的ID 标签的方法
2014/04/30 Javascript
js控制文本框禁止输入特殊字符详解
2017/04/07 Javascript
JavaScript设计模式之策略模式详解
2017/06/09 Javascript
vue中echarts3.0自适应的方法
2018/02/26 Javascript
angular将html代码输出为内容的实例
2018/09/30 Javascript
详解key在Vue列表渲染时究竟起到了什么作用
2019/04/20 Javascript
vue-router路由模式详解(小结)
2019/08/26 Javascript
完美解决通过IP地址访问VUE项目的问题
2020/07/18 Javascript
[08:08]DOTA2-DPC中国联赛2月28日Recap集锦
2021/03/11 DOTA
用Python写的图片蜘蛛人代码
2012/08/27 Python
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
完美解决在oj中Python的循环输入问题
2018/06/25 Python
使用python获取(宜宾市地震信息)地震信息
2019/06/20 Python
python实现的自动发送消息功能详解
2019/08/15 Python
OpenCV哈里斯(Harris)角点检测的实现
2020/01/15 Python
美国家喻户晓的保健品品牌:Vitamin World(维他命世界)
2016/08/19 全球购物
急诊科护士自我鉴定
2013/10/14 职场文书
门诊挂号室室长岗位职责
2013/11/27 职场文书
幼儿园实习自我鉴定
2013/12/15 职场文书
酒店人事专员岗位职责
2013/12/19 职场文书
社团活动总结
2014/04/28 职场文书
网络管理员岗位职责
2015/02/12 职场文书
毕业生政审意见范文
2015/06/04 职场文书
经营场所证明范本
2015/06/19 职场文书
python+opencv实现目标跟踪过程
2022/06/21 Python