一、说明

1、根据慕课网上的教程为基础,这是前两个基础教程:
PHP实现微信公众平台开发—基础篇:https://www.imooc.com/video/9316
PHP实现微信公众平台开发—提升篇 :https://www.imooc.com/video/10231
2、慕课上视频讲解用的是thinkphp早期版本,我用的是thinkphp3.2.3版本。可以看慕课视频进行学习,讲的比较详细
PHP微信公众平台开发高级篇—自定义菜单:https://www.imooc.com/video/11332
3、代码亲测有效

二、IndexController控制器代码

<?php
namespace Weixin\Controller;
use Think\Controller;

class IndexController extends Controller{
    public function __construct(){
    
    }//可以不写
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'weixin';
        $timestamp = $_GET['timestamp'];
        $echostr   = $_GET['echostr'];
        $signature = $_GET['signature'];
        //形成数组,然后按字典序排序
        $array = array();
        $array = array($nonce, $timestamp, $token);
        sort($array);
        //拼接成字符串,sha1加密 ,然后与signature进行校验
        $str = sha1( implode( $array ) );
        if( $str  == $signature && $echostr ){
            //第一次接入weixin api接口的时候
            echo  $echostr;
            exit;
        }else{
            $this->definedItem();
            $this->reponseMsg();
        }
    }
    // 接收事件推送并回复
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        //$postArr = $GLOBALS['HTTP_RAW_POST_DATA'];//php7开始不支持
        $postArr = file_get_contents("php://input"); 
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );
        
        //判断该数据包是否是订阅的事件推送
        if( strtolower( $postObj->MsgType) == 'event'){
            //如果是关注 subscribe 事件
            if( strtolower($postObj->Event == 'subscribe') ){
                /* //回复用户消息(纯文本格式)    
                $toUser   = $postObj->FromUserName;
                $fromUser = $postObj->ToUserName;
                $time     = time();
                $msgType  =  'text';
                //$content  = '欢迎关注我们的微信公众账号'.$postObj->FromUserName.'-'.$postObj->ToUserName;
                $content  = '欢迎关注放哥的微信公众账号';
                $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
                $info = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
                echo $info; */ 
                //回复一个单图文
                $arr = array(
                    array(
                        'title'=>'程序员的天堂',
                        'description'=>"欢迎来到放哥的公众号",
                        'picUrl'=>'http://www.imooc.com/static/img/common/logo.png',
                        'url'=>'http://www.imooc.com',
                    ),
                );
                $model = new \Weixin\Model\IndexModel();
                $model -> responseSubscribe($postObj, $arr);
            }
        }
         //dump($postObj->Event); 
         //dump($postObj->Eventkey);
        //自定义菜单中event->click事件
         if( strtolower($postObj->Event) == 'click'){
             $key = (string)$postObj->EventKey;
            if(strtolower($key == 'item1')){
                $content = "这是item1菜单的事件推送";
            }elseif(strtolower($key == 'songs')){
                $content = "这是歌曲菜单的事件推送";
            } else {
                $content = '未匹配'.print_r($postObj->EventKey, true);
            }
            $model = new \Weixin\Model\IndexModel();
            $model -> responseText($postObj, $content);
        }
        
        //如果是自定义菜单中的event->view
        if(strtolower($postObj->Event) == 'view'){
            $content="跳转的链接是".$postObj->EventKey;
            $model = new \Weixin\Model\IndexModel();
            $model -> responseText($postObj, $content);
        }    
        
        //用户发送tuwen1关键字的时候,回复一个单图文
        if( strtolower($postObj->MsgType) == 'text' && trim($postObj->Content)=='tuwen2' ){
            //从数据库中查询得到
            $arr = array(
                array(
                    'title'=>'imooc',
                    'description'=>"imooc is very cool",
                    'picUrl'=>'http://www.imooc.com/static/img/common/logo.png',
                    'url'=>'http://www.imooc.com',
                ),
                array(
                    'title'=>'hao123',
                    'description'=>"hao123 is very cool",
                    'picUrl'=>'https://www.baidu.com/img/bdlogo.png',
                    'url'=>'http://www.hao123.com',
                ),
                array(
                    'title'=>'qq',
                    'description'=>"qq is very cool",
                    'picUrl'=>'http://www.imooc.com/static/img/common/logo.png',
                    'url'=>'http://www.qq.com',
                ),
            );
            //实例化模型
            $model = new \Weixin\Model\IndexModel();
            $model -> responseNews($postObj, $arr);

            //注意:进行多图文发送时,子图文个数不能超过10个
        }else{
            switch(trim($postObj->Content)){
                case 1:
                    $content = '您输入的数字是1';
                break;
                case 2:
                    $content = '您输入的数字是2';
                break;
                case 3:
                    $content = '您输入的数字是3';
                break;
                case 4:
                    $content = "<a href='http://www.imooc.com'>慕课</a>";
                break;
                case '英文':
                    $content = 'imooc is ok';
                break;
                default:
                    $content = '没有找到相关信息';
            }    
            //实例化模型
            $model = new \Weixin\Model\IndexModel();
            $model -> responseText($postObj, $content);
        }//if end
    }//reponseMsg end

/*     function http_curl(){
        //获取imooc
        //1.初始化curl
        $ch = curl_init();
        $url = 'http://www.baidu.com';
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        curl_close($ch);
        var_dump($output);
    } */
    /*
    *$url 接口url string
    *$type 请求类型 string
    *$res 返回数据类型 string
    *%$arr post 请求参数 string
    */
    public function http_curl($url,$type='get',$res='json',$arr=''){
        //1.初始化curl
        $ch = curl_init();
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if($type == 'post'){
            curl_setopt($ch, CURLOPT_POST,1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
        }
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        curl_close($ch);
        if($res=='json'){
            if(curl_error($ch)){
                //请求失败,返回错误信息
                return curl_error($ch);
            }else{
                //请求成功,返回错误信息
                return json_decode($output,true);
            }
        }
    }

    /* function getWxAccessToken(){
        //1.请求url地址
        $appid = 'wxb20bebb764546087';
        $appsecret =  '64e22d215895d52af21c8fcbf6da3241';
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
        //2初始化
        $ch = curl_init();
        //3.设置参数
        curl_setopt($ch , CURLOPT_URL, $url);
        curl_setopt($ch , CURLOPT_RETURNTRANSFER, 1);
        //4.调用接口 
        $res = curl_exec($ch);
        //5.关闭curl
        curl_close( $ch );
        if( curl_errno($ch) ){
            var_dump( curl_error($ch) );
        }
        $arr = json_decode($res, true);
        var_dump( $arr );
    } */

    function getWxServerIp(){
        $accessToken = "10_GeE-KKSKq5PE_K3gLKJE7bmAJKJS2hh0qwM5ZwTSJaGtY6DJ3o5moOvT0TjpScimSG4g4LfjShJc6unkfKThjAcdinCJsWyS0RIIdWJLnJ_yBN3Qa06DTf63ZgkC86N7lmfRNcsVuwdthW35AXIdABAKHS";
        $url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=".$accessToken;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $res = curl_exec($ch);
        curl_close($ch);
        if(curl_errno($ch)){
            var_dump(curl_error($ch));
        }
        $arr = json_decode($res,true);
        echo "<pre>";
        var_dump( $arr );
        echo "</pre>";
    }
    /*
    *返回access_token *session解决办法 存mysql memcache
    */
    public function getWxAccessToken(){
        //将access_token 存在session/cookie中
        if($_SESSION['access_token'] && $_SESSION['expire_time'] > time()){
            //如果access_token在session中没有过期
            return $_SESSION['access_token'];
        }else{
            //如果access_token在session中不存在或者已经过期
            $appid = 'wxb20bebb764546087';
            $appsecret = '64e22d215895d52af21c8fcbf6da3241';
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
            $res = $this->http_curl($url,'get','json');
            $access_token = $res['access_token'];
            //将重新获取到的access_token存到session中
            $_SESSION['access_token'] = $access_token;
            $_SESSION['erpire_time'] = time() + 7000;
            return $access_token;
        }
    }
    /* 创建微信菜单
    目前微信接口的调用方式都是curl post/get */
    public function definedItem(){
        header('content-type:text/html;charset=utf-8');
        echo $access_token = $this->getWxAccessToken();
        echo '<br />';
        $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
        $postArr = array(
            'button' => array(
                    array(
                        'name' => urlencode('菜单一'),
                        'type' => 'click',
                        'key' => 'item1',
                    ),//第一个一级菜单
                    array(
                        'name' => urlencode('菜单二'),
                        'sub_button' => array(
                            array(
                                'name' => urlencode('歌曲'),
                                'type' => 'click',
                                'key' => 'songs',
                            ),//第一个二级菜单
                            array(
                                'name' => urlencode('电影'),
                                'type' => 'view',
                                'url' => 'http://www.baidu.com',
                            ),//第二个二级菜单
                        ),
                    ),//第二个一级菜单
                    array(
                        'name' => urlencode('菜单三'),
                        'type' => 'view',
                        'url' => 'http://www.qq.com',
                    ),//第三个一级菜单
                ),
            );
        echo '<hr />';
        var_dump($postArr);
        echo '<hr />';
        echo $postJson = urldecode(json_encode($postArr));
        $res = $this->http_curl($url,'post','json',$postJson);
        echo '<hr />';
        var_dump($res);
    }
}//class end

三、IndexModel模型代码

<?php
namespace Weixin\Model;

class IndexModel{
    //回复多图文类型的微信消息
    public function responseNews($postObj ,$arr){
        $toUser = $postObj->FromUserName;
        $fromUser = $postObj->ToUserName;
        $template = "<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[%s]]></MsgType>
                    <ArticleCount>".count($arr)."</ArticleCount>
                    <Articles>";
        foreach($arr as $k=>$v){
            $template .="<item>
                        <Title><![CDATA[".$v['title']."]]></Title> 
                        <Description><![CDATA[".$v['description']."]]></Description>
                        <PicUrl><![CDATA[".$v['picUrl']."]]></PicUrl>
                        <Url><![CDATA[".$v['url']."]]></Url>
                        </item>";
        }
        
        $template .="</Articles>
                    </xml> ";
        echo sprintf($template, $toUser, $fromUser, time(), 'news');
    }

    // 回复单文本
    public function responseText($postObj,$content){
        $template = "<xml>
        <ToUserName><![CDATA[%s]]></ToUserName>
        <FromUserName><![CDATA[%s]]></FromUserName>
        <CreateTime>%s</CreateTime>
        <MsgType><![CDATA[%s]]></MsgType>
        <Content><![CDATA[%s]]></Content>
        </xml>";
        //注意模板中的中括号 不能少 也不能多
        $fromUser = $postObj->ToUserName;
        $toUser   = $postObj->FromUserName; 
        $time     = time();
        $msgType  = 'text';
        echo sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
    }

    //回复微信用户的关注事件
    public function responseSubscribe($postObj, $arr){
        $this->responseNews($postObj,$arr);
    }
}

本文由 一切随风 创作,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论