博客列表 >605-微信公众平台开发:消息推送和附近店辅推送

605-微信公众平台开发:消息推送和附近店辅推送

小威的博客
小威的博客原创
2018年06月08日 19:58:521091浏览
  • 微信公众平台开发:消息推送

先分析一下回复消息的逻辑流程:用户发送消息给公众号,微信服务器接收的消息,立即对消息进行编码,并以一个xml格式发给开发者的服务器,开发者的服务器就响应一个编辑好的消息,也以xml格式发回给微信服务器,之后微信服务器解析xml发回给微信服务器。(现支持回复文本、图片、图文、语音、视频、音乐)。

消息推送也是在控制器中-index-方法中写的:

由于消息推送同关注和定位一样以xml数据包推送的,故此也要先对xml解析处理

// 微信推送事件
    public function index(){
        //获取xml数据包,并对数据包解析处理
        $xmldata = file_get_contents("php://input");、
        $postObj = simplexml_load_string($xmldata, 'SimpleXMLElement', LIBXML_NOCDATA);
        $data = (array)$postObj;
        
        if(isset($data['MsgType']) && $data['MsgType'] == 'text'){
            $this->robot($data);
            exit('success');
        }        
        exit(input('get.echostr'));
    }

当服务器判断用户的信息为text文本格式时,就调用机器人接口进行回复

// 机器人接口
    private function robot($data){
        //判断是否含有设定好的关键字
        if($data['Content'] == '图文消息'){
            $response = $this->model->img_article_msg($data);
            exit($response);
        }
        if($data['Content'] == '附近'){
            $response = $this->model->near_shops($data['ToUserName'],$data['FromUserName']);
            exit($response);
        }
        // 调用器机人智能聊天
        $response = $this->model->robot($data);
        exit($response);
    }

机器人接口也会对消息内容进行判断,如果消息中包含了设定好的关键字,就会回复相应图文信息,如果没有包含的关键,就开启智能聊天功能:调用模型中的机器人robot方法:

  • 消息推送:机器人自动回复  

  • 调用php中文网写好的机器人API,先配置APPID和KEY

return [
    //微信配置
    'token'                  => 'aMCikdpelconEk1omMjK4',
    'appid'                  => 'wxc68d8ac1d6fe2201',
    'appsecret'              => 'ca719e7b9270e24afa511ef0858f0516',
	
    // 机器人API
    'robot'                  => [
        'appid' => '10001',
        'key'   => '4fa92702a0633127d26ba957d97680ab',
    ],
];

由于对接微信平台也有个APPID  所以我们需要在机器人API配置中,包个robot配置,在模型中调用方法如下:

// 机器人聊天
    public function robot($data){
        //1. 调用机器人配置参数
        $config = config('app.robot');
        $params['appid'] = $config['appid'];
        $key = $config['key'];
        //2. 生成签名和消息内容处理
        $params['timestamp'] = time();//生成时间戳
        $params['msg'] = $data['Content'];//用户发送的消息
        ksort($params);//排序数组
        $str = http_build_query($params);//拼接数组
        $sign = sha1($str.$key);//加密生成签名
        //3. 请求机器人智能回复服务
        $url = 'http://www.php.cn/index.php/weixintest/robot?'.$str.'&sign='.$sign;
        $res = http_get($url);
        $res = json_decode($res,true);//解析机器人返回的消息
        $res['msg'] = str_replace('{br}', "\n", $res['msg']);//替换掉特殊字符串和强制换行
        //4. 打包成xml数据包 返回给微信服务器
        $response = '<xml> <ToUserName>'.$data['FromUserName'].'</ToUserName> <FromUserName>'.$data['ToUserName'].'</FromUserName> <CreateTime>'.time().'</CreateTime> <MsgType>text</MsgType> <Content>'.$res['msg'].'</Content> </xml>';
        return $response;
    }

当微信服务器接收机器人回复的消息,就原样返回给微信客户端,效果如下:1.png

  • 消息推送:图文信息

图文消息推送比较简单的,当用户发送的消息中包含了设定好的关键字,就会回复已编辑好的图文信息给用户浏览即可:

控制器判断和调用模型中的 img_article_msg 方法:关键词content可以自定义

private function robot($data){
        if($data['Content'] == '图文消息'){
            $response = $this->model->img_article_msg($data);
            exit($response);
        }

我们先看看官方的示例和各项参数:

<xml>
<ToUserName>< ![CDATA[toUser]接收方帐号(收到的OpenID) ]></ToUserName>
<FromUserName>< ![CDATA[fromUser]开发者微信号     ]></FromUserName>
<CreateTime>12345678 消息创建时间 (整型)</CreateTime>
<MsgType>< ![CDATA[news] ]>消息类型:新闻/活动</MsgType>
<ArticleCount>2  图文消息个数,限制为8条以内</ArticleCount>
<Articles 多条图文消息信息,注意,如果图文数超过8,则将会无响应>
<item 默认第一个item为大图,>
<Title>< ![CDATA[title1]图文消息标题 ]></Title> 
<Description>< ![CDATA[description1] 图文消息描述]></Description> 类似于新闻简介
<PicUrl>< ![CDATA[picurl]  图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 ]></PicUrl>
<Url>< ![CDATA[url] 点击图文消息跳转链接    ]></Url>
</item>
<item>
<Title>< ![CDATA[title] ]></Title>
<Description>< ![CDATA[description] ]></Description>
<PicUrl>< ![CDATA[picurl] ]></PicUrl>
<Url>< ![CDATA[url] ]></Url>
</item>
</Articles>
</xml>

这里我们需要注意一下:每一个图文消息都由2个标签包住1.Articles,类似于div或ul标签 >2. item标签类似于li标签

而图文消息有三步形成:

1.编辑好图文消息内容:用数组方法包含节点方式读取图文消息

// 被动回复用户图文消息
    public function img_article_msg($data){
        // 真实环境下是由后台编辑内容,再从数据库读取图文消息,此处我们直接拉取PHP中文网的新闻链接
        $articles = array(
            array('title'=>'从php招聘要求看php程序员应该会什么?','description'=>'目前在国内有很多知名公司都采用PHP 作为主要的开发 Web 开发语言,php中文网小编就从专业的IT招聘网站拉钩网挑选几条php招聘要','picurl'=>'https://img.php.cn/upload/article/000/000/164/58a56f51f0d4c979.jpg','url'=>'http://www.php.cn/toutiao-352287.html'),
            array('title'=>'全球php开发框架排行榜','description'=>'在PHP开发中,选择合适的框架有助于加快软件开发,节约宝贵的项目时间,让开发者专注于功能的实现上。由于流行的框架经过了大量项','picurl'=>'https://img.php.cn/upload/article/000/000/002/82ff85191adbac932aec043cbf901727.jpg','url'=>'http://www.php.cn/toutiao-380795.html'),
        );

读取数据库的图文消息:

public function img_article_msg($data){
        // 数据库读取图文消息
        $res = \think\Db::name('news')->field('id,title,newsmi,img,url')->select();
        foreach ($res as $key => $value){
            $articles[] = array('title'=>$value['title'],'description'=>$value['newsmi'],'picurl'=>$value['img'],'url'=>$value['url']);
        }
}

2. 用一个构造方法 【build_img_text_msg 】对图文消息进行重组成 xml数据包

//构造图文消息
    private function build_img_text_msg($from,$to,$data){
        $str = '<xml><ToUserName>'.$from.'</ToUserName><FromUserName>'.$from.'</FromUserName><CreateTime>'.time().'</CreateTime><MsgType>news</MsgType><ArticleCount>2</ArticleCount><Articles>';
        foreach ($data as $item) {
            $str .= '<item><Title>'.$item['title'].'</Title> <Description>'.$item['description'].'</Description><PicUrl>'.$item['picurl】'].'</PicUrl><Url>'.$item['url'].'</Url></item>';
        }
        $str .= '</Articles></xml>';
        return $str;
    }

构造图文消息需要几个参数:1. $from 谁发的  2. $to 发给谁的   $data:发送的数据

  • 由于图文消息可以有几段,所以我们对图文消息进行拼接组装:

先将头部标签参数写出来:count($data) 表示计算取出多少条数据

$str = '<xml><ToUserName>'.$from.'</ToUserName><FromUserName>'.$to.'</FromUserName><CreateTime>'.time().'</CreateTime><MsgType>news</MsgType><ArticleCount>'.count($data).'</ArticleCount><Articles>';

再将标题内容进行循环出来:foreach ($data as $item) 

$str .= '<item><Title>'.$item['title'].'</Title> <Description>'.$item['description'].'</Description><PicUrl>'.$item['picurl'].'</PicUrl><Url>'.$item['url'].'</Url></item>';

最后把尾部标签拼接上,最后 return $str;

$str .= '</Articles></xml>';
return $str;

3. 回复图文消息 xml 数据包给微信服务器

$xml = $this->build_img_text_msg($data['FromUserName'],$data['ToUserName'],$articles);
return $xml;

这样一段图文消息就能成功推送出来了  效果如下:

2.png

  • 消息推送:推送附近店铺  根据记录用户的经纬度坐标进行推荐附近店铺,增强营销。。

推送附近店铺跟推送图文消息方法一样,只是推送的内容参数不一样,下面我们看看实现的步骤:

  • 1. 先对用户发送的信息进行判断,是否包含关键字,附近,有就在控制器中调用near_shops的方法:

private function robot($data){
   if($data['Content'] == '附近'){
     $response = $this->model->near_shops($data['ToUserName'],$data['FromUserName']);
     exit($response);
}
  • 2. 设定需推送的店铺经纬度坐标位置:

先创建店铺数据库表shop,创建六个字段:id  title 店铺名称 address 地址 img 店铺图片 lat 经度  lng纬度

可以利用百度地图的拾取坐标系统,或高德地图的高德云图功能来获取地图的经纬度坐标参数,创建店铺数据

QQ截图20180608153034.png

创建好店铺数据后,就可以在模型中写方法:

public function near_shops($from,$to,$distance = 10){
        //先用openid值查找到用户信息
        $user = Db::name('user')->where(array('openid'=>$to))->find();
        //取出经纬度值
        $lat = $user['lat'];
        $lng = $user['lng'];
        //查询计算排序用户群的经纬度
        $res = \think\Db::name('shop')->field('id,title,address,(6371*acos(cos(radians('.$lat.'))*cos(radians(lat))*cos(radians(lng)-radians('.$lng.'))+sin(radians('.$lat.'))*sin(radians(lat)))) AS distance')->having('distance < '.$distance)->order('distance')->select();
        $shop_list = [];
        //循环读取数组的值
        foreach ($res as $key => $value) {
            $shop_list[] = array('title'=>$value['title'],'description'=>$value['address'].'  距离:'.$value['distance'].'公里','picurl'=>$value['img'],'url'=>'/');
        }

这里需要注意几个参数 $lat 经度 $lng 纬度   $distance 距离  HAVING  对由sum或其它集合函数运算结果的输出进行限制。

        // 回复图文消息
        $xml = $this->build_img_text_msg($to,$from,$shop_list);
        return $xml;

看看效果:

QQ图片20180608195957.png



声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议