当前位置: 首页 > news >正文

php微信公众号开发

一、Introduction

微信公众号是一个平台。目前,提供了4类帐号,订阅号、服务号、小程序、企业微信。具体区别在官网有说明。

二、使用接口测试号开发

1.        申请接口测试号

平台提供了接口测试号。到公众平台开发者文档,可以申请测试号开发。申请后提供appID和appsecret等,以供开发使用。

2.        access_token

access_token是公众号的全局唯一接口调用凭证,调用接口时都需使用access_token,以提高安全性。access_token的请求方式,通过客户端,或通过企业服务器。获取方式三种,

第一种,通过浏览器访问url,https请求方式: GET

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

第二种,通过微信平台获取,在开发者文档获取access_token,点击使用网页调试工具调试该接口;

第三种,编写php程序来获取,使用cURL函数库,client  url library。使用curl,先在php.ini开启curl的扩展。

<?php

/**

 * 使用curl函数

 */

function_request($curl, $https=true, $method='get', $data=null)

{

         //初始化

         $ch = curl_init();

         //设置url

         curl_setopt($ch, CURLOPT_URL, $curl);

         //设置不需要头信息

         curl_setopt($ch, CURLOPT_HEADER,false);

         //至获取页面内容,但不输出

         curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);

         if($https)

         {

                   //设置不做服务器认证

                   curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);

                   //不做客户端认证

                   curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);

         }

         if($method == 'post')

         {

                   //设置请求方式为post

                   curl_setopt($ch,CURLOPT_POST, true);

                   //设置请求数据

                   curl_setopt($ch,CURLOPT_POSTFIELDS, $data);

         }

         //执行并接收输出

         $str = curl_exec($ch);

         //释放资源

         curl_close($ch);

         return $str;

}

echo _request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx49119aeb8923abfd&secret=96e13016d1cb24026545e5ed7c133fac");

/**

 * 获取access_token

 */

function_getAccesstoken()

{

         $file = './accessToken.txt';

         //判断文件是否存在

         if(file_exists($file))

         {

                   $content =file_get_contents($file);

                   //json解码文件的内容

                   $content =json_decode($content);

                   //判断是否过期

                   if(time() - filemtime($file)< $content->expires_in)

                   {

                            return$content->access_token;

                   }                

         }

         $content =_request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx49119aeb8923abfd&secret=96e13016d1cb24026545e5ed7c133fac");

         file_put_contents($file, $content);

         $content = json_decode($content);

         return $content->access_token;

}



echo_getAccesstoken();

3.        使用php封装一个获取access_token的工具类

<?php

/**

 * 定义微信工具类

 */

class WeChat

{

         //appid

         private $_appid;

         //appsecret

         private $_appsecret;

         //token

         private $_token;



         /**********************************************************/



         /**

          * 构造函数

          */

         public function __construct($appid,$appsecret, $token)

         {

                   $this->_appid = $appid;

                   $this->_appsecret =$appsecret;

                   $this->_token = $token;

         }



         /**

          * 使用curl函数抓取url内容

          */

         private function _request($curl,$https=true, $method='get', $data=null)

         {

                   //初始化

                   $ch = curl_init();

                   //设置url

                   curl_setopt($ch, CURLOPT_URL,$curl);

                   //设置不需要头信息

                   curl_setopt($ch,CURLOPT_HEADER, false);

                   //至获取页面内容,但不输出

                   curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

                   if($https)

                   {

                            //设置不做服务器认证

                            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);

                            //不做客户端认证

                            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);

                   }

                   if($method == 'post')

                   {

                            //设置请求方式为post

                            curl_setopt($ch,CURLOPT_POST, true);

                            //设置请求数据

                            curl_setopt($ch,CURLOPT_POSTFIELDS, $data);

                   }

                   //执行并接收输出

                   $str = curl_exec($ch);

                   //释放资源

                   curl_close($ch);

                   return $str;

         }



         /**

          * 获取access_token

          */

         private function _getAccesstoken()

         {

                   $file = './accessToken.txt';

                   //判断文件是否存在

                   if(file_exists($file))

                   {

                            $content =file_get_contents($file);

                            //json解码文件的内容

                            $content =json_decode($content);

                            //判断是否过期

                            if(time() -filemtime($file) < $content->expires_in)

                            {

                                      return $content->access_token;

                            }                

                   }

                   $content =_request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->_appid."&secret=".$this->_appsecret);

                   file_put_contents($file,$content);

                   $content = json_decode($content);

                   return$content->access_token;

         }



}

4.        生成带参数的二维码

QR Code,Quick  Response Code。用于用户渠道推广分析和用户帐号绑定等场景。分为临时二维码和永久二维码。获取的步骤,创建二维码ticket,凭借ticket到指定url获取二维码。

获取ticket

在工具类中添加获取ticket的方法

         /**

          * 获取ticket

          * expires_seconds,int,二维码的有效期,单位s;

          * type,str,二维码的类型,永久或临时;

          * scene,int,使用二维码场景编号;

          */

         public function_getTicket($expires_seconds = 604800, $type = "temp", $scene = 1)

         {

                   if($type == "temp")

                   {

                            $data ='{"expire_seconds": '.$expires_seconds.', "action_name":"QR_STR_SCENE", "action_info": {"scene":{"scene_str": "'.$scene.'"}}}';



                            return$this->_request("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$this->_getAccesstoken(),true, "post", $data);

                   }

                   else

                   {

                            $data ='{"action_name": "QR_LIMIT_STR_SCENE","action_info": {"scene": {"scene_str":"'.$scene.'"}}}';

                            return$this->_request("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$this->_getAccesstoken(),true, "post", $data);

                   }



         }

通过ticket获取二维码

在类中添加获取二维码的方法

         /**

          * 获取二维码的方法

          */

         public function_getQRCode($expires_seconds = '604800', $type = 'temp', $scene = 1)

         {

                   $content =$this->_getTicket($expires_seconds, $type, $scene);

                   $content =json_decode($content);

                   $ticket =$content->ticket;

                   $image =$this->_request("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".urlencode($ticket));

                   $file ="./".date("Y-m-d").'_'.$type.$scene.".jpg";

                   file_put_contents($file,$image);

                   return $image;

         }

测试获取二维码的方法

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","");

require'./Wechat.class.php';

header('Content-type:image/jpg');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

// echo $wechat->_getTicket($expires_seconds= 604800, $type = "yongjiu", $scene = 2);

echo$wechat->_getQRCode(604800, 'temp', 5);

5.        接口配置

接入校验,就是微信服务器地址是否正确。在接收消息时,要验证消息真实性。

平台官网提供了验证的样本代码,可以修改token为自己需要的。

<?php

/**

  * wechat php test

  * update time: 20141008

  */



//define your token

define("TOKEN","testwechat");//可以修改TOKEN

$wechatObj = newwechatCallbackapiTest();

$data = array();

$data[] =$_SERVER['REMOTE_ADDR'];

$data[] =$_SERVER['QUERY_STRING'];

$file ='./server.log';

//输出服务端信息,用于检测状态,如果无法写入文件,请修改父目录权限

file_put_contents($file,$data);

$wechatObj->valid();



classwechatCallbackapiTest

{

         public function valid()

    {

        $echoStr = $_GET["echostr"];



        //valid signature , option

        if($this->checkSignature()){

                 echo$echoStr;

                 exit;

        }

    }



    public function responseMsg()

    {

                   //get post data, May be dueto the different environments

                   $postStr =$GLOBALS["HTTP_RAW_POST_DATA"];



           //extractpost data

                   if (!empty($postStr)){

               

                   $postObj= simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);

                $fromUsername =$postObj->FromUserName;

                $toUsername =$postObj->ToUserName;

                $keyword =trim($postObj->Content);

                $time = time();

                $textTpl = "<xml>

                                                                 <ToUserName><![CDATA[%s]]></ToUserName>

                                                                 <FromUserName><![CDATA[%s]]></FromUserName>

                                                                 <CreateTime>%s</CreateTime>

                                                                 <MsgType><![CDATA[%s]]></MsgType>

                                                                 <Content><![CDATA[%s]]></Content>

                                                                 <FuncFlag>0</FuncFlag>

                                                                 </xml>";            

                                     if(!empty($keyword ))

                {

                            $msgType= "text";

                         $contentStr = "Welcome to wechat world!";

                         $resultStr = sprintf($textTpl, $fromUsername, $toUsername,$time, $msgType, $contentStr);

                         echo $resultStr;

                }else{

                         echo "Input something...";

                }



        }else {

                 echo"";

                 exit;

        }

    }

                  

         private function checkSignature()

         {

        $signature =$_GET["signature"];

        $timestamp =$_GET["timestamp"];

        $nonce = $_GET["nonce"];

                   $token = TOKEN;

                   $tmpArr = array($token,$timestamp, $nonce);

        sort($tmpArr, SORT_STRING);

                   $tmpStr = implode( $tmpArr );

                   $tmpStr = sha1( $tmpStr );

                  

                   if( $tmpStr == $signature ){

                            return true;

                   }else{

                            return false;

                   }

         }

}



?>

如果token能对的上,就配置成功。一次成功后,后续微信平台就知道了这个接口的使用者。除非更改了url或者token,可以再次验证。

为了便于通过类来管理,可以将样本提供的方法,复制到wechat的工具类中。那么,index.php不需要写这个类了。

然后在index.php中

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

//header('Content-type:image/jpg');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

// echo$wechat->_getTicket($expires_seconds = 604800, $type = "yongjiu",$scene = 2);

// echo$wechat->_getQRCode(604800, 'temp', 5);

$wechat->valid();

6.        接收普通消息

普通消息分为文本消息、图片消息、语音消息、视频消息、地理位置消息、链接信息等。也是使用平台提供的模版,就是上述验证的第二个方法responseMsg()

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

// header('Content-type:image/jpg');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

// echo$wechat->_getTicket($expires_seconds = 604800, $type = "yongjiu",$scene = 2);

// echo$wechat->_getQRCode(604800, 'temp', 5);

//$wechat->valid();//一次验证,可以延续使用,无需多次验证,除非验证url和token有更改

$wechat->responseMsg();

这样客户端向在公众号发送内容后,就会得到回复

在responseMsg()方法中,$contentStr = "Welcome to wechat world!";

可以对客户发送的内容进行判断,回复不同的内容。

平台提供了回复不同的内容的xml的格式,可以直接使用。

MsgType属性是关于回复的内容的类型的。根据回复的类型进行不同的处理。

在wechat工具类中

    /**

     * 回复客户端信息的方法

     */

   public function responseMsg()

    {

                   //get post data, May be dueto the different environments

                   $postStr =$GLOBALS["HTTP_RAW_POST_DATA"];



           //extractpost data

                   if (!empty($postStr)){

               

               $postObj= simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);

               $file= './post.log';

               file_put_contents($file,'['.date('Y-m-d H:i:s').']content:'.$postObj->MsgType.PHP_EOL, FILE_APPEND);

            switch ($postObj->MsgType) {

                        //文本类型

                        case'text':

                              $this->_doText($postObj);

                              break;

                        //图片

                        case'image':

                              $this->_doImage($postObj);

                              break;

                     //语音

                     case 'voice':

                              $this->_doVoice($postObj);

                              break;

                     //视频

                     case 'video':

                              $this->_doVideo($postObj);

                              break;

                     //定位信息

                     case 'location':

                              $this->_doLocation($postObj);

                              break;

                     //小视频

                     case 'shortvideo':

                              $this->_doShortVideo($postObj);

                              break;

                     //链接信息

                     case 'link':

                              $this->_doLink($postObj);

                              break;

                  default:exit;

            }

        }else {

                 echo"";

                 exit;

        }

    }

                  

    /**

     * 处理文本内容的回复

     */

         private function _doText($postObj)

         {

                   $fromUsername =$postObj->FromUserName;

        $toUsername = $postObj->ToUserName;

        $keyword = trim($postObj->Content);

        $time = time();

        $textTpl = "<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[%s]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               <FuncFlag>0</FuncFlag>

                                               </xml>";            

                   if(!empty( $keyword ))

        {

                 $contentStr= "Welcome to wessssssssssssschat world!";

                    if($keyword=="看看")

                    {

                             $contentStr= "没sssss有";

                    }

                    if($keyword== "走了")

                    {

                             $contentStr= "有ssss了";

                    }

                    $msgType= "text";

                

                 $resultStr= sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);

                 echo$resultStr;

        }

        exit;

         }



         /**

     * 处理图片内容的回复

     */

         private function _doImage($postObj)

         {                

                   $file = './post.log';

           $fromUsername= $postObj->FromUserName;

        $toUsername = $postObj->ToUserName;

        $keyword = trim($postObj->Content);

        $time = time();

                   //使用被动回复消息的模版

                   $textTpl = "<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[%s]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               </xml>";

                   $contentStr = '您发送的图片在-->'.$postObj->PicUrl.'<--';

                $msgType= "text";

                   $str = sprintf($textTpl,$fromUsername, $toUsername, $time, $msgType, $contentStr);

                   echo $str;

                   file_put_contents($file,'['.date('Y-m-d H:i:s').']content:'.$str.PHP_EOL, FILE_APPEND);

                   exit;

         }

7.        接收事件推送

事件推送的类型有关注/取消事件,扫描带参数二维码,上报地理位置,自定义菜单,点击菜单,点击菜单取消消息,点击菜单跳转链接等。

在回复方法中添加处理event类型的分支

switch($postObj->MsgType) {

     //事件类型

     case 'event':

         $this->_doEvent($postObj);

         break;

         ……

}
    /**

     * 处理事件类型

     */

         private function _doEvent($postObj)

         {

                   switch($postObj->Event)

                   {

                            //订阅

                            case 'subscribe':

                                     $this->_doSubscribe($postObj);

                                     break;

                            //取关

                            case 'unsubscribe':

                                     $this->_doUnsubscribe($postObj);

                                     break;

                            default:;



                   }

         }



         /**

          * 处理订阅事件

          */

         private function _doSubscribe($postObj)

         {

                   $fromUsername =$postObj->FromUserName;

        $toUsername = $postObj->ToUserName;

        $keyword = trim($postObj->Content);

        $time = time();

                   //使用被动回复消息的模版

                   $textTpl = "<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[%s]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               </xml>";

                   $contentStr = '欢迎订阅php1';

                $msgType= "text";

                   $str = sprintf($textTpl,$fromUsername, $toUsername, $time, $msgType, $contentStr);

                   echo $str;

                   exit;

         }



         /**

          * 处理取关事件

          */

         private function _doUnsubscribe($postObj)

         {

                   exit;

         }

8.        自定义菜单

为了丰富用户的操作,可以添加菜单,自定义操作。

1)        创建菜单

使用微信平台的测试工具,可以直接创建菜单。

打开网页测试工具。选择接口类型为自定义菜单,接口列表为menu/create,body可以复制提供的样板,根据实际做修改:

{

    "button": [

        {

            "type":"click",

            "name": "今日歌曲",

            "key":"V1001_TODAY_MUSIC"

        },

        {

            "name": "菜单",

            "sub_button": [

                {

                    "type":"view",

                    "name": "搜索",

                    "url":"http://www.soso.com/"

                },

                {

                    "type":"click",

                    "name": "赞一下我们",

                    "key":"V1001_GOOD"

                }

            ]

        }

    ]

}

检查问题就可以创建菜单,取关后重新关注,可以查看效果。

也可通过接口添加菜单

    /**

     * 创建菜单的方法

     */

    public function _createMenu($menu)

    {

             $url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->_getAccesstoken();

             $result= $this->_request($url, true, 'post', $menu);

             $result= json_decode($result);

             if($result->errcode== 0)

             {

                       $info= '菜单创建成功';

             }

             else

             {

                       $info= '服务器异常,请联系管理员';

             }

             return$info;

}

调用创建菜单的方法

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

//header('Content-type:image/jpg');

header('content-type:text/html;charset=utf-8');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

$menu = '{

                       "button": [

                           {

                               "type":"click",

                               "name": "今日歌曲",

                               "key":"V1001_TODAY_MUSIC"

                           },

                           {

                               "name": "游戏",

                               "sub_button": [

                                   {

                                       "type":"view",

                                       "name": "吃货大作战",

                                       "url":"http://my.59600.com/pc/webgame/?id=9696003&name=%E5%90%83%E8%B4%A7%E5%A4%A7%E4%BD%9C%E6%88%98"

                                   },

                                   {

                                       "type":"click",

                                       "name": "赞一下我们",

                                       "key":"V1001_GOOD"

                                   }

                               ]

                           }

                       ]

                   }';

echo$wechat->_createMenu($menu);

2)        删除菜单

可以在这个页面,接口列表,选择为menu/delete,检查问题就可以删除菜单。

也可以使用平台提供删除菜单的接口

    /**

     * 删除菜单的方法

     */

    public function _deleteMenu()

    {

             $url= "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=".$this->_getAccesstoken();

             $result= $this->_request($url);

             $result= json_decode($result);

             if($result->errcode== 0)

             {

                       $info= '菜单删除成功';

             }

             else

             {

                       $info= '服务器异常,请联系管理员';

             }

             $file= "./deletemenu.txt";

             file_put_contents($file,  '['.date('Y-m-dH:i:s').']content:'.$info.PHP_EOL, FILE_APPEND);

             return$info;

    }

3)        查询菜单

使用自定义菜单内的查询接口。返回的是json形式的字符串。

    /**

     * 查询菜单的方法

     */

    public function _queryMenu()

    {

             $url="https://api.weixin.qq.com/cgi-bin/menu/get?access_token=".$this->_getAccesstoken();

             $menu= $this->_request($url);

             $file= "./menu.txt";

             file_put_contents($file,  '['.date('Y-m-dH:i:s').']content:'.$menu.PHP_EOL, FILE_APPEND);

             return$menu;

}

4)        发送图文信息(被动)

当用户点击了某个菜单选项后,可以被动向用户发送图文信息。当用户点击了菜单后,会触发自定义菜单事件,平台会把点击事件推送给开发者,注意的是,点击菜单弹出子菜单,不会产生上报。推送的xml数据包中含有参数Event和EventKey,即创建按钮时设置的按钮的type和key。点击的哪个按钮,就推送这个按钮的type和key,然后被动发送图文信息等。

在处理事件的方法中添加处理点击事件的分支。

         //鼠标点击事件

         case 'CLICK':

                   $this->_doClick($postObj);

                   break;

创建点击的方法

         /**

          * 处理点击事件

          */

         private function _doClick($postObj)

         {

                   $eventKey =$postObj->EventKey;

                   if($eventKey == 'news')

                   {

                            $fromUsername =$postObj->FromUserName;

                $toUsername = $postObj->ToUserName;

                $keyword = trim($postObj->Content);

                $time = time();

                            //使用被动回复消息的模版

                            $textTpl ="<xml>

                                                        <ToUserName><![CDATA[%s]]></ToUserName>

                                                        <FromUserName><![CDATA[%s]]></FromUserName>

                                                        <CreateTime>%s</CreateTime>

                                                        <MsgType><![CDATA[%s]]></MsgType>

                                                        <ArticleCount>%s</ArticleCount>

                                                        <Articles>

                                                                 %s

                                                        </Articles>

                                                        </xml>";

                            $itemTpl ="<item>

                                                                 <Title><![CDATA[%s]]></Title>

                                                                 <Description><![CDATA[%s]]></Description>

                                                                 <PicUrl><![CDATA[%s]]></PicUrl>

                                                                 <Url><![CDATA[%s]]></Url>

                                                        </item>";

                            $items = array(

                                     array(

                                               'title'=>'阿森纳叛温格',

                                               'desc'=>'提起阿德巴约,阿森纳评温格虚伪,阿森纳无情。还表示自己最喜欢的教练是穆里尼奥,他永远爱穆帅。',

                                               'picurl'=>'http://n.sinaimg.cn/sports/transform/w650h364/20180119/G4LB-fyqtwzu6103615.jpg',

                                               'url'=>'http://sports.sina.com.cn/g/pl/2018-01-19/doc-ifyquptv7864181.shtml?cre=tianyi&mod=pcspth&loc=9&r=25&doct=0&rfunc=6&tj=none&tr=1',

                                               ),

                                     array(

                                               'title'=>'桑切斯去曼德的',

                                               'desc'=>'桑切斯加盟曼联的转会已经进入倒计时,阿森纳主帅温格也亲自承认:“桑切斯的交易很可能会发生。料地投奔昔日恩师、现任曼城主帅瓜迪奥拉。对此,《太阳报》首席评论员尼尔',

                                               'picurl'=>'http://n.sinaimg.cn/sports/transform/w650h457/20180119/Ofj1-fyqtwzu6235171.jpg',

                                               'url'=>'http://sports.sina.com.cn/g/pl/2018-01-19/doc-ifyqtwzu6240517.shtml?cre=tianyi&mod=pcspth&loc=5&r=0&doct=0&rfunc=6&tj=none&tr=1',

                                               ),

                            );

                            foreach ($items as$k => $v)

                            {

                                     $itemContent.= sprintf($itemTpl, $v['title'], $v['desc'], $v['picurl'], $v['url']);

                            }

                        $msgType ="news";

                            $str =sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, count($items),$itemContent);

                            echo $str;

                            exit;

                   }

         }

9.        定位信息的处理

在接收普通消息中,有地理位置消息。这个消息中有发送点的经纬度信息。在处理类型中添加处理地理位置的分支。并创建对应的方法。

         /**

          * 处理地理位置

          */

         private function _doLocation($postObj)

         {

                   $file = './post.log';

           $fromUsername = $postObj->FromUserName;

        $toUsername = $postObj->ToUserName;

        $keyword = trim($postObj->Content);

        $time = time();

                   //使用被动回复消息的模版

                   $textTpl = "<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[%s]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               </xml>";

                   $contentStr = '您所在的地理位置为:N '.$postObj->Location_X.',E '.$postObj->Location_Y;

                $msgType= "text";

                   $str = sprintf($textTpl,$fromUsername, $toUsername, $time, $msgType, $contentStr);

                   echo $str;

                   file_put_contents($file,'['.date('Y-m-d H:i:s').']content:'.$str.PHP_EOL, FILE_APPEND);

                   exit;

         }

10.    模版优化

由于程序中经常使用到模版,可以将模版提取为属性。

         //模版

         private $tpl = array(

                   //文本模版

                   'text' => '<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[text]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               <FuncFlag>0</FuncFlag>

                                               </xml>',

                   //被动回复消息的模版

                   'retext' => '<xml>

                                               <ToUserName><![CDATA[%s]]></ToUserName>

                                               <FromUserName><![CDATA[%s]]></FromUserName>

                                               <CreateTime>%s</CreateTime>

                                               <MsgType><![CDATA[text]]></MsgType>

                                               <Content><![CDATA[%s]]></Content>

                                               </xml>',

                   );

然后,在程序中使用到模版的地方改为使用属性。

$str = sprintf($this->tpl['retext'],$fromUsername, $toUsername, $time, $contentStr);

11.    获取用户列表

平台提供了接口获取用户列表。这个接口得到的是用户的openid,结合获取用户基本信息的接口,可以获取到用户的基本信息。

在微信工具类中创建_getUserlist()

         /**

          * 获取用户openid

          */

         public function _getUserOpenid()

         {

                   $url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token=".$this->_getAccesstoken();

                   $content =$this->_request($url);

                   $file ="./userlist.txt";

                   file_put_contents($file,'['.date('Y-m-d H:i:s').']content:'.$content.PHP_EOL, FILE_APPEND);

                   $content =json_decode($content);

                   $users =$content->data->openid;

                   return $users;

         }

         /**

          * 获取用户列表

          */

         public function _getUserlist()

         {

                   //获取所有用户的openid

                   $users =$this->_getUserOpenid();

                   $jsonUsers = array();

                   foreach ($users as $k =>$v)

                   {

                            $jsonUsers['user_list'][$k]['openid']= $v;

                            $jsonUsers['user_list'][$k]['lang']= "zh_CN";

                   }

                   $jsonUsers =json_encode($jsonUsers);

                   $url ='https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token='.$this->_getAccesstoken();

                   $userInfolist =$this->_request($url, true, 'post', $jsonUsers);

                   $userInfolist =json_decode($userInfolist)->user_info_list;

                   //var_dump($userInfolist);die;

                   //拼写html代码将用户信息以表格输出

                   $html = "<tableborder='1' cellspacing='0'>";

                   $html.="<tr><td>openid</td><td>昵称</td><td>性别</td><td>国家</td><td>订阅否</td><td>订阅时间</td></tr>";

                   foreach ($userInfolist as $k=> $v)

                   {

                            $html .="<tr>";

                            $html .='<td>'.$v->openid.'</td>';

                            $html .='<td>'.$v->nickname.'</td>';

                            if($v->sex == 1)

                            {

                                     $html .='<td>男</td>';

                            }

                            else

                            {

                                     $html .='<td>女</td>';

                            }

                            $html .='<td>'.$v->country.'</td>';

                            if($v->subscribe== 1)

                            {

                                     $html .='<td>是</td>';

                            }

                            else

                            {

                                     $html .='<td>否</td>';

                            }

                            $html .='<td>'.date('Y-m-d H:i:s', $v->subscribe_time).'</td>';

                            $html .="</tr>";

                   }

                   $html.="</table>";

                  

                   return $html;

         }

创建调用获取列表的php脚本

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

//header('Content-type:image/jpg');

header('content-type:text/html;charset=utf-8');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

echo$wechat->_getUserlist();

12.    群发文本信息到用户

使用群发文本信息的接口。

注意对发送的文本内容先urlencode,后urldecode,以防止内容被unicode编码化。

         /**

          * 群发信息

          */

         public function _sendAll($content)

         {

                   //获取所有用户的openid

                   $users =$this->_getUserOpenid();

                   //根据平台提供的模版制作post数据

                   /*

                   {

                      "touser":[

                       "OPENID1",

                       "OPENID2"

                      ],

                       "msgtype": "text",

                       "text": { "content":"hello from boxer."}

                   }

                   */

                   $data = array();

                   foreach ($users as $k =>$v)

                   {

                            $data['touser'][] =$v;

                   }

                   $data['msgtype'] = 'text';

                   $data['text']['content'] =urlencode($content);//对文本内容进行urlencode,以防止被解析为unicode

                   $data = urldecode(json_encode($data));//在对urlencode的内容进行urldecode,返回原来的编码格式

                   $url ='https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token='.$this->_getAccesstoken();

                   $result =$this->_request($url, true, 'post', $data);

                   $result =json_decode($result);

                   if($result->errcode == 0)

                   {

                            echo '发送成功';

                   }

                   else

                   {

                            echo '系统异常,请联系管理员';

                   }

                   exit;

         }

编写群发消息的php脚本

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

//header('Content-type:image/jpg');

header('content-type:text/html;charset=utf-8');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

$content = '可以';

$wechat->_sendAll($content);

13.    添加素材

可以新增临时或永久多媒体素材。新增素材存放在平台上,在调用时速度更快。

在微信工具类中创建_addMedia()方法

         /**

          * 添加素材

          */

         public function _addMedia($type, $file)

         {

                   $curl ="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=".$this->_getAccesstoken()."&type=".$type;     

                   $data['type'] = $type;

                   $data['media'] = '@'.$file;

                   $result = $this->_request($curl,true, 'post', $data);

                   echo $result;

         }

编写脚本调用这个方法

<?php

define("APPID","wx49119aeb8923abfd");

define("APPSECRET","96e13016d1cb24026545e5ed7c133fac");

define("TOKEN","testwechat");

require("./WeChat.class.php");

// header('Content-type:image/jpg');

header('content-type:text/html;charset=utf-8');

$wechat = newWeChat(APPID, APPSECRET, TOKEN);

$type = 'image';

$file = './php1.jpg';

$wechat->_addMedia($type,$file);

14.    搜索音乐的功能

使用音乐搜索引擎实现搜索音乐,听歌的功能。

当用户输入歌曲歌名@歌手名,后得到音乐消息。

在doText()方法中,添加关键字开头二字为歌曲的分支结构

                if(mb_substr($keyword, 0,2, 'utf-8') == '歌曲')

                {

                          $this->_sendMusic($postObj);

                          exit;

                }

创建处理音乐消息的方法

         /**

          * 搜索歌曲的方法

          */

         private function _sendMusic($postObj)

         {

                   $content =$postObj->Content;

                   $content =mb_substr($content, 2,strlen($content)-2, 'utf-8');

                   $arr = explode('@',$content);

                   $singer = '';

                   $song = '';

                   if(isset($arr[1]))

                   {

                            $singer = $arr[1];

                            $song = $arr[0];

                            $curl ='http://www.xiami.com/search?key='.$arr[0].'+'.$arr[1];

                   }

                   else

                   {

                            $song = $arr[0];

                            $curl ='http://www.xiami.com/search?key='.$arr[0];

                   }

                   $response =$this->_request($curl, false);

                   $file =('./searchMusic.txt');

                   $response =mb_strstr($response, '</thead>', false, 'utf-8');

                   $response = mb_strstr($response,'</tbody>', true, 'utf-8');

                   $response = strstr($response,'http');

                   $response = strstr($response,'"', true);

                   $response =$this->_request($response, false);

                   $response = strstr($response,'<a onclick="play');

                   $response = strstr($response,"'");

                   $response = strstr($response,",", true);

                   $response = substr($response,1, strlen($response)-2);

                   file_put_contents($file,$response);



                   $fromUsername =$postObj->FromUserName;

        $toUsername = $postObj->ToUserName;

        $time = time();                      

             $title= $song.'>>>'.$singer;

             $desc= '欢迎收听'.$song.'&&&';

             $musicUrl= 'http://www.xiami.com/play?ids=/song/playlist/id/'.$response;

             $thumbMediaId= 'AoR3l2l-cNv6_fsns4SnKev1_riF8yvpTP3TJ7y9SLdl6ug9BlZXV9te_Pgcu_pT';

             $resultStr= sprintf($this->tpl['music'], $fromUsername, $toUsername, $time, $title,$desc, $musicUrl, '', $thumbMediaId);

             echo$resultStr;

        exit;

 

相关文章:

  • [one_demo_4]不使用第3个变量交换两个变量的值
  • [one_demo_5]命令行输入输出
  • [one_demo_6]逆置整数
  • [one_demo_7]求走到第50个台阶的走法多少种
  • [one_demo_8]十进制转二进制
  • [one_demo_9]判断数组是否递增
  • [one_demo_10]递归解决汉诺塔问题
  • [one_demo_11]二分查找法
  • [one_demo_12]递归打印*\n*.*.\n*..*..\n图形
  • c
  • network
  • 使用javadoc生成项目的帮助文档
  • [one_demo_13]ArrayList去除重复的元素
  • web项目发布到tomcat的两种方式
  • androidBasic
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • C++11: atomic 头文件
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Promise面试题,控制异步流程
  • React-redux的原理以及使用
  • 安装python包到指定虚拟环境
  • 创建一个Struts2项目maven 方式
  • 从0到1:PostCSS 插件开发最佳实践
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 关于List、List?、ListObject的区别
  • 前端
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 算法---两个栈实现一个队列
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 消息队列系列二(IOT中消息队列的应用)
  • 原生js练习题---第五课
  • 在Unity中实现一个简单的消息管理器
  • 智能合约开发环境搭建及Hello World合约
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • ​水经微图Web1.5.0版即将上线
  • #ifdef 的技巧用法
  • #include<初见C语言之指针(5)>
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (03)光刻——半导体电路的绘制
  • (1)bark-ml
  • (2015)JS ES6 必知的十个 特性
  • (4)事件处理——(7)简单事件(Simple events)
  • (arch)linux 转换文件编码格式
  • (HAL库版)freeRTOS移植STMF103
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (九)信息融合方式简介