通过上一篇,我们实现了测试号的自动回复

但是测试号连个菜单都没有,查看微信接口里,果然有创建菜单的接口
http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html

接口调用请求说明

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

所以调用接口前,我们先要把access_token保存下来,用来调用各种接口。

新建一个token.php文件

<?php

$appid = "wxad142631a1240e1b";
$secret = "9cf2780ea0db8401d8151448ddb381f6";
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$rs = curl_exec($ch);
$data = json_decode($rs);

var_dump($data);
?>

返回值:
object(stdClass)#1 (2) { ["access_token"]=> string(107) "sNqfCXh9rtLhoTiapfArrCErcSxhUhvE9-flJOZ3Sfdi59I3xKMmJ70OZbwAQrqsB6TzQ80wFZu3jeHV1lsk0_iAEcP4W01OXGAWXacCS6s" ["expires_in"]=> int(7200) }

access_token    获取到的凭证
expires_in  凭证有效时间,单位:秒

可以看到有效时间为7200秒,因为接口调用每天有限制,不能每次都去调用,产生一个新的access_token,所以将access_token保存起来,判断时间是否过期,如过期就重新再取一次。
如下代码,将接口返回的json数据存进tokenfile,然后通过tokenfile文件的修改时间,判断是否过期

<?php
$m_time = filemtime("tokenfile");
$n_time = time();
$fs = file_get_contents("tokenfile");
$data = json_decode($fs);
$expires_in = intval($data->expires_in);

if($n_time - $m_time > $expires_in) {
    
    $appid = "wxad142631a1240e1b";
    $secret = "9cf2780ea0db8401d8151448ddb381f6";
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $rs = curl_exec($ch);

    file_put_contents("tokenfile",$rs);

    $c_data = json_decode($rs);

    $access_token = $c_data->access_token;
    
} else {
    $access_token = $data->access_token;
}

?>

在调用时只需加上include("token.php"),即可在程序中使用$access_token 调用access_token。

得到$access_token后,就可以通过接口生成菜单了。

综合一下,写一个微信的操作class,保存为class/wxAction.class.php文件,代码如下

<?php
class wxAction {
    
    public function __construct() {
    
    }
    
    //取全局凭证access_token
    public function getAccessToken($appid,$secret) {
        $m_time = filemtime("tokenfile");
        $n_time = time();
        $fs = file_get_contents("tokenfile");
        $data = json_decode($fs);
        $expires_in = intval($data->expires_in);

        if($n_time - $m_time > $expires_in) {
            
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
            
            $rs = $this->doCurlGetRequest($url);

            file_put_contents("tokenfile",$rs);

            $c_data = json_decode($rs);

            $access_token = $c_data->access_token;
            
        } else {
            $access_token = $data->access_token;
        }
        return $access_token;
    }
    
    //curl调用微信https接口-get方式
    public function doCurlGetRequest($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    //curl调用微信https接口-post方式
    function doCurlPostRequest($url, $jsonData){
        $con = curl_init((string)$url);
        curl_setopt($con, CURLOPT_HEADER, false);
        curl_setopt($con, CURLOPT_POSTFIELDS,$jsonData);
        curl_setopt($con, CURLOPT_POST, true);
        curl_setopt($con, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($con, CURLOPT_SSL_VERIFYPEER,false);  //略过证书验证
        $result = curl_exec($con) ;
        if(curl_errno($con))
        {
          file_put_contents("tmp.txt", curl_errno($con).PHP_EOL,FILE_APPEND);
        }
        
        return $result;
    }


    //生成自定义菜单
    public function createMenu($access_token,$menu_arr) {
        

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

        $data = $menu_arr;
        
        $rs = $this->doCurlPostRequest($url,$data);
        return $rs;
    
    }

    //取用户信息
    public function getUserInfo($access_token,$openid,$lang) {

        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$openid}&lang={$lang}";

        $rs = $this->doCurlGetRequest($url);
        return $rs;

    }
}

生成菜单的代码:

<?php
$appid = "wxad142631a1240e1b";
$secret = "9cf2780ea0db8401d8151448ddb381f6";
include("class/wxAction.class.php");
$wx = new wxAction();

$menu_arr ='{
    "button":[
    {
        "name":"油卡服务",
        "sub_button":[
        {
            "type":"view",
            "name":"加油卡绑定",
            "url":"http://www.sinopecsales.com/"
        },
        {
            "type":"view",
            "name":"加油卡充值",
            "url":"http://www.sinopecsales.com/"
        },
        {
            "type":"view",
            "name":"加油卡查询",
            "url":"http://www.sinopecsales.com/"
        },
        {
            "type":"view",
            "name":"提油卡服务",
            "url":"http://www.sinopecsales.com/"
        },
        {
            "type":"view",
            "name":"业务咨询",
            "url":"http://www.sinopecsales.com/"
        }]
    },
    {
        "name":"乐享易捷",
        "sub_button":[
        {   
            "type":"view",
            "name":"精彩活动",
            "url":"http://www.sinopecsales.com/"
        },
        {   
            "type":"view",
            "name":"易捷精品",
            "url":"http://www.sinopecsales.com/"
        },
        {   
            "type":"view",
            "name":"在线易捷购",
            "url":"http://www.sinopecsales.com/"
        },
        {   
            "type":"view",
            "name":"我的易捷",
            "url":"http://www.sinopecsales.com/"
        },
        {   
            "type":"view",
            "name":"APP下载",
            "url":"http://www.sinopecsales.com/"
        }]
    },
    {
        "name":"便民服务",
        "sub_button":[
        {   
            "type":"view",
            "name":"附近油站",
            "url": "http://map.baidu.com/mobile/webapp/search/search/qt=s&wd=%E4%B8%AD%E7%9F%B3%E5%8C%96%E5%8A%A0%E6%B2%B9%E7%AB%99&c=163&searchFlag=bigBox&version=5&exptype=dep/vt=/?fromhash=1"
        },
        {   
            "type":"location_select",
            "name":"附近便利店",
            "key": "rselfmenu_2_1"
        },
        {   
            "type":"view",
            "name":"最新油价",
            "url":"http://www.sinopecsales.com/"
        },
        {   
            "type":"view",
            "name":"油气知识",
            "url":"http://www.sinopecsales.com/"
        },
        {
            "type":"view",
            "name":"会员服务",
            "url":"http://www.sinopecsales.com/"
        }]
    }]
 }';

$access_token = $wx->getAccessToken($appid,$secret);

$rs = $wx->createMenu($access_token,$menu_arr);
echo $rs;

假如通过数据库存取menu,通过php的json_encode函数构造menu_arr的话,要注意中文字符,因为json_encode默认会转义中文,导致

{"errcode":40033,"errmsg":"invalid charset. please check your request, if include \\uxxxx will create fail!"}

出现该报错,解决办法:
如果php版本是5.4+, 一个参数JSON_UNESCAPED_UNICODE就能搞定。

json_encode($data, JSON_UNESCAPED_UNICODE);