上一篇文章我们知道怎么获取二维码,这样别人就可以扫描二维码来关注我们,但是别人关注后,发送消息,我们怎么进行相关处理?

这里我们就来学习下怎么处理处理这些消息,以及推送消息。

学习之前首先你需要有一个域名和空间

url:填写你希望微信公众平台把用户的消息转发到哪里

token:随便输入,用于微信公众平台和你的站点进行第一次通信建立关联用

/*
用于第一次验证我们网站url合法性
*/
public function firstValid(){
//检验签名的合法性
if($this->_checkSignature()){
//签名合法,告知微信公众平台服务器
echo $_GET['echostr'];
}
}
/**
* 验证签名
* @return bool
*/
private function _checkSignature(){
//获得由微信公众平台请求的验证数据
$signature = $_GET['signature'];
$timestamp = $_GET['timestamp'];
$nonce = $_GET['nonce'];
//将时间戳,随机字符串,token按照字母顺序排序,病并连接
$tmp_arr = array($this->_token,$timestamp,$nonce);
sort($tmp_arr,SORT_STRING);//字典顺序
$tmp_str = implode($tmp_arr);//连接
$tmp_str = sha1($tmp_str);//sha1加密
if($signature==$tmp_str){
return true;
}else{
return false;
}

在你的站点写一个脚本,调用一下firstValid 就可以完成微信公众平台和你站点的关联。$this->_token,就是你上面写token。

然后再提交,就能成功了。

1、关注后,欢迎语的设置

有人关注后,微信公众平台会给我们发一个xml格式的数据,如下:

然后我们对这个信息进行获取,转化成我们想要的格式,进行相关判断,返回数据,同样也需要组装成xml格式

public function responseMsg(){
/*
获得请求时POST:XML字符串
不能用$_POST获取,因为没有key
*/
$xml_str = $GLOBALS['HTTP_RAW_POST_DATA'];
if(empty($xml_str)){
die('');
}
if(!empty($xml_str)){
// 解析该xml字符串,利用simpleXML
libxml_disable_entity_loader(true);
//禁止xml实体解析,防止xml注入
$request_xml = simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA);
//判断该消息的类型,通过元素MsgType
switch ($request_xml->MsgType){
case 'event':
//判断具体的时间类型(关注、取消、点击)
$event = $request_xml->Event;
if ($event=='subscribe') { // 关注事件
$this->_doSubscribe($request_xml);
}elseif ($event=='CLICK') {//菜单点击事件
$this->_doClick($request_xml);
}elseif ($event=='VIEW') {//连接跳转事件
$this->_doView($request_xml);
}else{ }
break;
case 'text'://文本消息
$this->_doText($request_xml);
break;
case 'image'://图片消息
$this->_doImage($request_xml);
break;
case 'voice'://语音消息
$this->_doVoice($request_xml);
break;
case 'video'://视频消息
$this->_doVideo($request_xml);
break;
case 'shortvideo'://短视频消息
$this->_doShortvideo($request_xml);
break;
case 'location'://位置消息
$this->_doLocation($request_xml);
break;
case 'link'://链接消息
$this->_doLink($request_xml);
break;
}
}
}

我们可以给用户回复文字,图片,视频,音乐,新闻等等,首先定义好相应的回复模块

private $_msg_template = array(
'text' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>',//文本回复XML模板
'image' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>',//图片回复XML模板
'music' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>',//音乐模板
'news' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles></xml>',// 新闻主体
'news_item' => '<item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item>',//某个新闻模板
);

%s就代表我们需要填的参数,后面用spritf统一传入

首先我们回复一句‘你好’;

/**
* 发送文本信息
* @param [type] $to 目标用户ID
* @param [type] $from 来源用户ID
* @param [type] $content 内容
* @return [type] [description]
*/
private function _msgText($to, $from, $content) {
$response = sprintf($this->_msg_template['text'], $to, $from, time(), $content);
die($response);
}
//关注后做的事件
private function _doSubscribe($request_xml){
//处理该关注事件,向用户发送关注信息
$content = '你好';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
}

这样,用户一关注就会收到‘你好’。

2、发送图片

微信中的图片、语音、视频、缩略图统称素材,发送和接受都是以media_id进行的。

简单说:用给公众号一张图片,这张图片会上传到微信公众平台服务器,然后生成一个唯一的media_id,然后返回一个xml信息给我们,其中就有media_id。而我们要发给用户图片,也需要先把图片上传给公众平台,然后获取到media_id,根据这个media_id结合图片回复模板返回给平台

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

* 上传临时素材(永久素材也可以):图片,语音,视频,缩略图
* 储存到微信公众平台服务器,3天
* 可通过上传后返回的media_id再次去取得该图片
自己定义上传函数

public function uplodeTmp($file,$type){
$url='https://api.weixin.qq.com/cgi-bin/media/upload?access_token='.$this->getAccessToken().'&type='.$type;
$data = array(
'media' => '@'.$file,
);
$result = $this->_request('post',$url,$data);
$result_obj = json_decode($result);
return $result_obj;
}

自己调用该函数上传站点图片,通过返回结果获得该图片media_id

发送给用户:

//发送图片
private function _msgImage($to,$from,$file,$is_id=false){
//判断是不是media_id
if($is_id){
$media_id=$file;
}else{
// 上传图片到微信公众服务器,获取mediaID
$result_obj = $this->uploadTmp($file, 'image');
$media_id = $result_obj->media_id;
}
//拼凑xml图片发给微信平台,然后平台返回图片给用户
$response = sprintf($this->_msg_template['image'],$to,$from,time(),$media_id);
die($response);
}

这样用户就可以获得你的图片。

返回缩略图,语音、视频、短视频也是用同样的方法

如果我们希望用户发出‘图片’两个字时,返回给他一张图片,该怎么做?

private function _doText($request_xml){
//接受文本信息
$content = $request_xml->Content;
if('图片' == $content){
$imgMediaId = 'UD-4n5YeK6NXhPCOYT_eV4YxYNZqCILemIZuZR3GYmj_AtrqhnHiIUUOQHSi71Ew';
$this->_msgImage($request_xml->FromUserName, $request_xml->ToUserName,$imgMediaId,true);
} }

当然我们这里把图片写死了,实际可根据具体业务逻辑进行改变,改变media_id就行了。

3、发送音乐

如果用户输入音乐,我们发一首歌给他,音乐跟其他的几个素材不太一样

 private function _doText($request_xml){
//接受文本信息
$content = $request_xml->Content; if('音乐' == $content){
$music_url='音乐网络地址链接';
$ha_music_url='音乐网络地址链接';
$thumb_media_id='一张图片的media_id';
$title = '音乐名称';
$desc = '音乐描述';
$this->_msgMusic($request_xml->FromUserName, $request_xml->ToUserName, $music_url, $hq_music_url, $thumb_media_id, $title, $desc);
}
}
//发送音乐
private function _msgMusic($to, $from, $music_url, $hq_music_url, $thumb_media_id, $title='', $desc='') {
$response = sprintf($this->_msg_template['music'], $to, $from, time(), $title, $desc, $music_url, $hq_music_url, $thumb_media_id);
die($response);
}

4、图灵机器人的接入

图灵官网注册申请appkey

 //图灵机器人接入         
 $content = $request_xml->Content;
$url = 'http://www.tuling123.com/openapi/api?key='.$this->_appkey.'&info='.$content.'&userid='.$request_xml->FromUserName;
// $data['key'] = $this->_appkey;//
// $data['info'] = $content;//用户输入的内容
// $data['userid'] = $request_xml->FromUserName;
$response_content = json_decode($this->_request('get',$url,array(),false));
//$response_content->code决定返回的是什么
//100000 文本 text
//200000 链接 text+url
//302000 新闻 text +list(新闻列表,里面有:article,source,icon,detailurl)分别是标题、来源、图片、详情地址
//308000 菜谱 text+name+info+detailurl+icon
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content->text);

可以自行根据图灵官网反回的code进行分类判断,字符组装,再回复给用户。

这样,你的公众号就变成了一个图灵机器人了。

5、发送图文(新闻)

我一般看到的微信公众号都是以图文信息进行推送消息,这个新闻类型怎么发送?

if('新闻' == $content){
$item_list = array(
array('title'=>'标题','desc'=>'描述','picurl'=>'图片地址','url'=>'该文章的地址'),
array('title'=>'标题','desc'=>'描述','picurl'=>'图片地址','url'=>'该文章的地址')
);
$this->_msgNews($request_xml->FromUserName,$request_xml->ToUserName,$item_list);
} //发送新闻
private function _msgNews($to,$from,$item_list=array()){
//拼凑文章部分
$item_str = '';
foreach ($item_list as $item) {
$item_str .= sprintf($this->_msg_template['news_item'],$item['title'],$item['desc'],$item['picurl'],$item['url']);
}
//拼凑主体部分
$response = sprintf($this->_msg_template['news'], $to, $from, time(), count($item_list), $item_str);
die($response);
}

6、菜单创建删除

一般公众号底部都有1-3个菜单选项,选项里可能还有子菜单,这个如何通过php代码进行创建?

菜单创建和删除都是针对所有的,不能单独操作某一个菜单

//菜单删除
public function menuDelete(){
$url ='https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $this->getAccessToken();
$result = $this->_request('get',$url);
$result_obj = json_decode($result);
if($result_obj->errcode == 0){
return true;
}else{
return false;
}
}

删除很简单,调用这个函数就删除所有菜单了,不过已关注的用户需要24小时后才会生效。

//创建菜单
public function menuSet($menu) {
$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $this->getAccessToken();
$data = $menu;
$result_obj = json_decode($this->_request('post',$url, $data));
if ($result_obj->errcode == 0) {
return true;
} else {
echo $result_obj->errmsg, '<br>';
return false;
}
}

创建菜单需要我们传一个json格式参数,同一样已关注的用户也会24小时后生效

1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
各参数的类型,以及作用,请到开发者文档查看:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013

json数据格式如下:创建了3个主菜单,以及对应的子菜单。

$menu = <<<JSON
{
"button": [
{
"name": "扫码",
"sub_button": [
{
"type": "scancode_waitmsg",
"name": "扫码带提示",
"key": "scancode_waitmsg",
"sub_button": [ ]
},
{
"type": "scancode_push",
"name": "扫码推事件",
"key": "scancode_push",
"sub_button": [ ]
}
]
},
{
"name": "发图",
"sub_button": [
{
"type": "pic_sysphoto",
"name": "系统拍照发图",
"key": "pic_sysphoto",
"sub_button": [ ]
},
{
"type": "pic_photo_or_album",
"name": "拍照或者相册发图",
"key": "pic_photo_or_album",
"sub_button": [ ]
},
{
"type": "pic_weixin",
"name": "微信相册发图",
"key": "pic_weixin",
"sub_button": [ ]
}
]
},
{
"name": "快捷操作",
"sub_button" : [
{
"name": "地理位置",
"type": "location_select",
"key": "location_select"
},
{
"name": "普通点击",
"type": "click",
"key": "click"
},
{
"name": "查看URL",
"type": "view",
"url" : "http://www.soso.com/"
},
]
},
]
}
JSON; 源码下载:https://github.com/Ivanlovening/wechat

PHP开发微信公众号(二)消息接受与推送的更多相关文章

  1. Java开发微信公众号模板消息【同步|异步】

    第一步:申请模板消息功能并添加模板 在微信公众平台找到你需要的模板,并添加上即可: 第二步:添加功能模块后开始开发 功能中使用的类及代码: 发送数据主实体类: Template.java packag ...

  2. Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

    在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...

  3. Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装

    在前面几篇文章我们讲了微信公众号环境的配置 和微信公众号服务的接入,接下来我们来说一下微信服务器请求消息,响应消息以及事件消息的相关内容,首先我们来分析一下消息类型和返回xml格式及实体类的封装. ( ...

  4. Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发

    接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...

  5. spring-boot-route(二十三)开发微信公众号

    在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公众号大体上可以分为服务号和订阅号,订阅号和服务号的区别如下: 服务号可以申请微信支付功能. 服务号只能由企业申请,订阅号可以有企业或个人申请. ...

  6. PHP开发微信公众号(一)二维码的获取

    要开发微信公众号,首先进行需要注册一个,然后认证.这就不用多说了. 当然如果没有,也可以去申请一个测试号来使用,地址:https://mp.weixin.qq.com/debug/cgi-bin/sa ...

  7. 2014-07-24 .NET实现微信公众号的消息回复与自定义菜单

    今天是在吾索实习的第12天.我们在这一天中,基本实现了微信公众号的消息回复与自定义菜单的创建. 首先,是实现消息回复,其关键点如下: 读取POST来的数据流:Stream 数据流变量 = HttpCo ...

  8. 使用vue开发微信公众号下SPA站点的填坑之旅

    原文发表于本人博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅.作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^ ...

  9. Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token

    获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token.比如自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等在请求的时候 ...

  10. Java开发微信公众号(一)---初识微信公众号以及环境搭建

    ps:1.开发语言使用Java springMvc+Mybaits+spring maven实现 2.使用微信接口测试账号进行本地测试 https://mp.weixin.qq.com/debug/c ...

随机推荐

  1. Opencv读取图片像素值

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  2. 数据库版本控制工具:NeXtep Designer

    下载地址:http://pan.baidu.com/s/1dFuxKFB NeXtep Open Designer 是一个强大的多人协同/多平台的开源数据库的开发工具,致力于于自动化和生产级的集成开发 ...

  3. [C++] Type Conversion(类型转换)

    Type Conversion(类型转换) Two kinds of type conversion explict type conversion(显式类型转换) impict type conve ...

  4. C++获取字符串长度数

    strlen,获取到的是字节数,中文占两个字节. 如何获取字符数,无论中文英文,标点符号,都按一个字符计算呢?这里提供其中的一个方法.那就是通过MultiByteToWideChar函数,将CStri ...

  5. configparser模块读写ini配置文件

    在自动化测试过程中,为了提高脚本的可读性和降低维护成本,将一些通用信息写入配置文件,将重复使用的方法写成公共模块进行封装,使用时候直接调用即可. 这篇博客,介绍下python中利用configpars ...

  6. 软件加license的一种实现方法

    以前从没干过破解的勾当,这次确实必须要去破解一个,于是下了个反编译工具. 最终拿到反编译出来的文件,欣赏了一把它的license检测代码.原谅我的无知,以下代码在我看来还是比较新鲜,犬神请不要鄙视: ...

  7. CodeForces 122G Lucky Array(一脸懵逼的树状数组)

    Petya loves lucky numbers. Everybody knows that lucky numbers are positive integers whose decimal re ...

  8. node后台启动

    node启动后会占用当前shell 后台启动方式: 1.用forever进行管理 npm install -g forever forever start index.js   2.使用nohub命令 ...

  9. Adding Cache-Control headers to Static Files in ASP.NET Core

    Thanks to the ASP.NET Core middleware pipeline, it is relatively simple to add additional HTTP heade ...

  10. Java Integer为代表的包装类

    Java种的Integer是int的包装类型 1. Integer 是int的包装类型,数据类型是类,初值为null 2. 初始化时 int i = 1; Integer i = new Intege ...