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 生成饼图 三维饼图
Sep 28 PHP
php 读取文件头判断文件类型的实现代码
Aug 05 PHP
php与Mysql的一些简单的操作
Feb 26 PHP
PHP+JS实现大规模数据提交的方法
Jul 02 PHP
ThinkPHP使用Smarty第三方插件方法小结
Mar 19 PHP
php基于mcrypt_encrypt和mcrypt_decrypt实现字符串加密解密的方法
Jul 12 PHP
PHP 接入微信扫码支付总结(总结篇)
Nov 03 PHP
php 判断页面或图片是否经过gzip压缩的方法
Apr 05 PHP
PHP开发的微信现金红包功能示例
Jun 29 PHP
Laravel 创建指定表 migrate的例子
Oct 09 PHP
php操作redis数据库常见方法实例总结
Feb 20 PHP
如何用RabbitMQ和Swoole实现一个异步任务系统
May 29 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加密函数 Javascript/Js 解密函数
2013/09/23 PHP
PHP中4个加速、缓存扩展的区别和选用建议
2014/03/12 PHP
PHP的Yii框架中创建视图和渲染视图的方法详解
2016/03/29 PHP
微信支付开发告警通知实例
2016/07/12 PHP
PHP操作Postgresql封装类与应用完整实例
2018/04/24 PHP
Aster vs KG BO3 第三场2.19
2021/03/10 DOTA
QQ邮箱的一个文本编辑器代码
2007/03/14 Javascript
使用js获取QueryString的方法小结
2010/02/28 Javascript
JavaScript高级程序设计(第3版)学习笔记9 js函数(下)
2012/10/11 Javascript
jQuery获取节点和子节点文本的方法
2014/07/22 Javascript
影响jQuery使用的14个方面
2014/09/01 Javascript
JavaScript中数组的合并以及排序实现示例
2015/10/24 Javascript
javascript动态生成树形菜单的方法
2015/11/14 Javascript
JS简单模拟触发按钮点击功能的方法
2015/11/30 Javascript
将json转换成struts参数的方法
2016/11/08 Javascript
jQuery滚动监听实现商城楼梯式导航效果
2017/03/06 Javascript
彻底解决 webpack 打包文件体积过大问题
2017/07/07 Javascript
js实现本地图片文件拖拽效果
2017/07/18 Javascript
NodeJS使用Range请求实现下载功能的方法示例
2018/10/12 NodeJs
vue组件tabbar使用方法详解
2018/11/06 Javascript
Vuejs监听vuex中值的变化的方法示例
2018/12/02 Javascript
小程序关于请求同步的总结
2019/05/05 Javascript
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
python使用点操作符访问字典(dict)数据的方法
2015/03/16 Python
python中函数传参详解
2016/07/03 Python
详解Python中的Numpy、SciPy、MatPlotLib安装与配置
2017/11/17 Python
Python序列循环移位的3种方法推荐
2018/04/09 Python
python 通过可变参数计算n个数的乘积方法
2019/06/13 Python
CSS3属性background-size使用指南
2014/12/09 HTML / CSS
Speedo美国:澳大利亚顶尖泳衣制造商
2016/08/03 全球购物
Omio美国:全欧洲低价大巴、火车和航班搜索和比价
2017/11/08 全球购物
Wedgwood英国官方网站:英式精致骨瓷餐具、礼品与生活精品,源于1759年
2019/09/02 全球购物
大学专科生推荐信范文
2013/11/23 职场文书
小学二年级评语
2014/04/21 职场文书
环保建议书600字
2014/05/14 职场文书
投诉信回复范文
2015/07/03 职场文书