微信个性化菜单开发

问题描述:

继上一篇的《自定义微信公众号的个性化菜单栏》的文章,为了“根据不同用户标签显示不同的功能菜单并且点击菜单跳转到外网”这个功能需求,研究了一天的微信开发文档关于个性化菜单,消息接口事件推送,用户标签的问题,将自己在开发过程中遇到的问题分享出来,让更多的小伙伴少走弯路。

 

梳理问题:

其一 :接触过微信公众号开发的小伙伴都知道,微信公众号(认证服务号)的后台是给用户提供有自定义菜单设置,并且在那里可以设置菜单并且设置url连接来跳转到网页

其二:我们可以通过微信提供的自定义菜单创建接口,(如何获取AccessToken请参考上一篇文章)

//生成自定义菜单(默认菜单)
    public function createMenu(){
        $access_token = $this->getAccessToken();
        $url = "//api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;

        //拼装要生成的菜单
        $array = array(
            'button'=>array(
                //第一个一级菜单
//                array(
//                    'type'=>'click',
//                    'name'=>'hello',
//                    'key' =>'front',
//
//                ),
                array(
                    "type"=>"view",
                    "name"=> 'world',
                    "url"=>"//www.baidu.com"
                ),

                //第二个一级菜单
//                array(
//                    'type'=>'click',
//                    'name' => urlencode($data['second_name']),
//                    'key' =>'behind',
//                ),
            ),

        );
        //转化成json的格式
        $arrayJson = urldecode(json_encode($array));
        $this->http_curl($url,'post','json',$arrayJson);
    }

  CURL请求:

public function http_curl($url,$type='get',$res='json',$arr=''){
        //1.初始化
        $ch = curl_init();
        //2.设置参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if( $type == 'post' ){
            //如果是post请求的话,设置post的一些参数
            curl_setopt($ch , CURLOPT_POST , 1);
            curl_setopt($ch , CURLOPT_POSTFIELDS, $arr);
        }
        //3.执行
        $result = curl_exec($ch);
        if( curl_errno($ch)){
            //打印错误日志
            var_dump(curl_error($ch));
        }
        if( $res == 'json' ){
            //将json转化成数组的形式
            $result = json_decode($result , TRUE);
        }
        //4.关闭
        curl_close($ch);
        return $result;
    }

说明:这里的菜单是定义的二级菜单,定义二级菜单的作用是可以通过其url参数实现点击跳转(特别提示:官方文档中并没有说明在没有一级菜单的情况下不允许定义二级菜单,所以通过自定义接口我们可以直接创建二级菜单)

  小插曲:开始按照官方文档指示,并没有创建二级菜单,而是创建一级菜单,然而一级菜单的type事件跟二级的type事件不一样,一级菜单需要开启公众号后台的服务器配置,并且需要配置相关服务器接口,微信根据所配置的接口,将用户操作的内容发送到该接口,一级菜单的click事件绑定的EventKey参数可以用来在接口中识别是点击了哪个自定义菜单,可以根据EventKey的值来进行相关业务逻辑的处理。

其三:创建个性化菜单

根据微信官方文档说明:

个性化菜单匹配规则说明:

个性化菜单的更新是会被覆盖的。 例如公众号先后发布了默认菜单,个性化菜单1,个性化菜单2,个性化菜单3。那么当用户进入公众号页面时,将从个性化菜单3开始匹配,如果个性化菜单3匹配成功,则直接返回个性化菜单3,否则继续尝试匹配个性化菜单2,直到成功匹配到一个菜单。 根据上述匹配规则,为了避免菜单生效时间的混淆,决定不予提供个性化菜单编辑API,开发者需要更新菜单时,需将完整配置重新发布一轮。

//创建个性化匹配菜单
    public function characterMenu()
    {
        $access_token = $this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/menu/addconditional?access_token='.$access_token;

        $array = array(
            'button'=>array(
                array(
                    "type"=>"view",
                    "name"=> 'hello',
                    "url"=>"要跳转的url"
                ),
                array(
                    "type"=>"view",
                    "name"=> 'world',
                    "url"=>"要跳转的url"
                ),
            ),
            "matchrule"=>array(
                "tag_id"=>100//标签匹配,微信官方放回给你的标签id
            )
        );
        //转化成json的格式
        $arrayJson = urldecode(json_encode($array));
        $this->http_curl($url,'post','json',$arrayJson);
    }

  说明:个性化菜单的创建也是直接创建的二级菜单,如何创建标签id接下来说明(申请标签应在创建个性化菜单之前)

     matchrule的匹配规则项我们在这里只使用tag_id标签匹配,其他匹配项请参考微信开放文档(//developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Personalized_menu_interface.html)

其四:创建用户标签

创建用户标签也非常简单,直接上代码

 /**
     * 生成用户标签接口
     **/
    public function createTag()
    {
        $access_token = $this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/tags/create?access_token='.$access_token;
        $data['tag']['name']=urlencode('管理员');
        $res=$this->http_curl($url,'post','json',json_encode($data));
        dump($res);
        //成功返回的参数包括tag_id
    }

其五:为用户添加标签

该接口是批量为用户添加标签,参数为数组形式,里面只包含用户在该公众号下的唯一的openid值

//批量为用户打上微信公众号的标签类型
    public function pasteTag($arr_openid)
    {
        $access_token=$this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token='.$access_token;
        $data['openid_list']=$arr_openid;
        $data['tagid']=你的标签id;
        $data=$this->http_curl($url,'post','json',json_encode($data));
        dump($data);
    }

在此,当用户访问该公众号的时候,根据用户身上的标签,会显示不同的菜单栏内容,实现个性化菜单的展示功能

Additional:

为用户取消标签:

openid为数组形式,数组里面是你要取消的该公众号下的唯一的用户的openid

//为用户取消标签
    public function cancelTag($openid,$tagid)
    {
        $access_token = $this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token='.$access_token;
        $data['openid_list']=$openid;
        $data['tagid']=$tagid;
        $res = $this->http_curl($url,'post','json',json_encode($data));
        wxlogging('cancel_user_tag',json_encode($res));
    }

获取该公众号创建的标签:

 //获取微信公众号所创建的标签
    public function getTag()
    {
        $access_token=$this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/tags/get?access_token='.$access_token;
        $data=$this->http_curl($url);
        dump($data);
    }

获取某个标签下的用户:

//获取某个标签下面的粉丝openid
    public function getFans()
    {
        $access_token=$this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/user/tag/get?access_token='.$access_token;
        $data['tagid']=100;
        $data=$this->http_curl($url,'post','json',json_encode($data));
        dump($data);
    }

删除所有菜单

 public function delete()
    {
        $access_token=$this->getAccessToken();
        $url='//api.weixin.qq.com/cgi-bin/menu/delete?access_token='.$access_token;
        $res=$this->http_curl($url,'get','json');
        dump($res);

    }