2018年6月

1 第一步:用户同意授权,获取code

2 第二步:通过code换取网页授权access_token

3 第三步:刷新access_token(如果需要)

4 第四步:拉取用户信息(需scope为 snsapi_userinfo)

简单网页授权

//简单授权
    function getBaseInfo(){
        //1.获取到code
        $appid = "wxde8d3eacc9f91cae";
        $redirect_uri = urlencode("http://wx.sunxiaoning.com/index.php/Wx/index/getUserOpenId");
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
        header('location:'.$url);
        
    }
    function getUserOpenId(){
        //2.获取到网页授权的access_token
        $appid = "wxde8d3eacc9f91cae";
        $appsecret = "3ae10c48de0ec193a7cc695f098c2817";
        $code = $_GET['code'];
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code."&grant_type=authorization_code";
        //3.拉取用户的openid
        $res = $this->http_curl($url,'get');
        var_dump($res);

    }

详细授权

    function getUserDetail(){
        //1.获取到code
        $appid = "wxde8d3eacc9f91cae";
        $redirect_uri = urlencode("http://wx.sunxiaoning.com/index.php/Wx/index/getUserInfo");
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
        header('location:'.$url);
    }
    function getUserInfo(){
        //2.获取到网页授权的access_token
        $appid = "wxde8d3eacc9f91cae";
        $appsecret = "3ae10c48de0ec193a7cc695f098c2817";
        $code = $_GET['code'];
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code."&grant_type=authorization_code";
        //3.拉取用户的openid
        $res = $this->http_curl($url,'get');
        $access_token = $res['access_token'];
        $openid = $res['openid'];
        //4.拉取用户的详细信息
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $res = $this->http_curl($url);
        var_dump($res);

    }

自定义菜单的创建

自定义菜单基本要求:
1.自定义菜单最多包含3个一级菜单,每个一级菜单最多包含5个二级菜单。
2.一级菜单最多4个汉字,二级菜单最多包含7个汉字,多出来的部分以"..."的形式来展现。
3.在创建自定义菜单后,微信不会立即生效,为了更快的看到效果,可以取消关注后,重新进行关注。

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

下面简单介绍两种常用的请求:
click和view的请求示例

 {
     "button":[
     {    
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {    
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

参数说明

参数是否必须说明
button一级菜单数组,个数应为1~3个
sub_button二级菜单数组,个数应为1~5个
type菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型
name菜单标题,不超过16个字节,子菜单不超过60个字节
keyclick等点击类型必须菜单KEY值,用于消息接口推送,不超过128字节
urlview、miniprogram类型必须网页 链接,用户点击菜单可打开链接,不超过1024字节。 type为miniprogram时,不支持小程序的老版本客户端将打开本url。
media_idmedia_id类型和view_limited类型必须调用新增永久素材接口返回的合法media_id
appidminiprogram类型必须小程序的appid(仅认证公众号可配置)
pagepathminiprogram类型必须小程序的页面路径

返回结果:

  • 正确时的返回JSON数据包如下:

    {"errcode":0,"errmsg":"ok"}

  • 错误时的返回JSON数据包如下(示例为无效菜单名长度):

    {"errcode":40018,"errmsg":"invalid button name size"}

示例代码:(thinkphp3.2.3)

  /**
     * 创建自定义菜单
     * @return [type]
     */
    public function defineditem(){
        //创建微信菜单
        //目前微信接口的调用都是通过curl  post/get
        header('content-type:text/html;charset=utf-8');
        $access_token = $this->getWxAccessToken();
        $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.sunxiaoning.com',
                            )//第一个二级菜单
                        )
                    ),//第二个一级菜单
                    array(
                        'name'=>urlencode('菜单三'),
                        'type'=>'view',
                        'url'=>'http://bbs.sunxiaoning.com',
                    )//第三个一级菜单
                )
            
        );
        $postJson = urldecode(json_encode($postArr));
        //echo "$postJson"."<br>";
        $res = $this->http_curl($url,'post','json',$postJson);
        //var_dump($res);
    }
    /**
     * 返回access_token
     * @return [type] [description]
     */
    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不存在或者已经过期,重新获取access_token
            $appid = 'wxde8d3eacc9f91cae';
            $appsecret = '3ae10c48de0ec193a7cc695f098c2817';
            $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['expire_time'] = time()+7000;
            return $access_token;
        }
    }
/**
     * @param  url
     * @param  获取方式
     * @param  获取到的格式
     * @param  string
     * @return [type]
     */
    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.关闭
        if($res == 'json'){
            if(curl_errno($ch)){
                return curl_error($ch);
            }else{
                return json_decode($output,true);
            }
        }
        curl_close($output);
    }

自定义菜单事件消息回复

点击菜单拉取消息时的事件推送

推送XML数据包示例:

<xml>
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>
    <FromUserName>< ![CDATA[FromUser] ]></FromUserName>  
    <CreateTime>123456789</CreateTime>
    <MsgType>< ![CDATA[event] ]></MsgType>
    <Event>< ![CDATA[CLICK] ]></Event>
    <EventKey>< ![CDATA[EVENTKEY] ]></EventKey>
</xml>

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,CLICK
EventKey事件KEY值,与自定义菜单接口中KEY值对应

点击菜单跳转链接时的事件推送

推送XML数据包示例:

<xml>
   <ToUserName>< ![CDATA[toUser] ]></ToUserName>
   <FromUserName>< ![CDATA[FromUser] ]></FromUserName>
   <CreateTime>123456789</CreateTime>
   <MsgType>< ![CDATA[event] ]></MsgType>
   <Event>< ![CDATA[VIEW] ]></Event>
   <EventKey>< ![CDATA[www.qq.com] ]></EventKey>
</xml> 

参数说明:

参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgType消息类型,event
Event事件类型,VIEW
EventKey事件KEY值,设置的跳转URL

示例代码(thinkphp3.2.3)

  public function reponseMsg(){
    if (strtolower($postObj->Event)=='click') {
        //如果是自定义菜单中的event -> click
        if(strtolower($postObj->EventKey)=='item1'){
             $content  = "您点击了自定义菜单item1";
        }
        if(strtolower($postObj->EventKey)=='songs'){
             $content  = "您点击了自定义菜单songs";
        }
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $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;
    }
}

在微信开发的过程中,调用接口的时候都需使用公众号的全局唯一接口调用凭据access_token,在使用之前我们需要获取它。目前Access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器可对外继续输出的老access_token,此时公众平台后台会保证在5分钟内,新老access_token都可用,这保证了第三方业务的平滑过渡。
接口调用请求说明
https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

参数是否必须说明
grant_type获取access_token填写client_credential
appid第三方用户唯一凭证
secret第三方用户唯一凭证密钥,即appsecret

返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

参数说明

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

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{"errcode":40013,"errmsg":"invalid appid"}

返回码说明

返回码说明
-1系统繁忙,此时请开发者稍候再试
0请求成功
40001AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性
40002请确保grant_type字段值为client_credential
40164调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。(小程序及小游戏调用不要求IP地址在白名单内。)

以上的信息均来源于微信公众平台的开发者文档。但不保证是最新的,使用者可以自己上官网查看。
由于access_token的存活时间有时间上的限制,而且目前每天只能调用2000次,所有我们必须对access_token进行有效的利用,我们可以把它保存在session中,并设置有效的时间,如果有效,我们直接返回,无需重新获取。
示例代码:(thinkphp3.2.3)

    /**
     * 返回access_token
     * @return [type] [description]
     */
    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不存在或者已经过期,重新获取access_token
            $appid = 'wxde8d3eacc9f91cae';
            $appsecret = '3ae10c48de0ec193a7cc695f098c2817';
            $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['expire_time'] = time()+7000;
            return $access_token;
        }
    }


    /**
     * @param  url
     * @param  获取方式
     * @param  获取到的格式
     * @param  string
     * @return [type]
     */
    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.关闭
        if($res == 'json'){
            if(curl_errno($ch)){
                return curl_error($ch);
            }else{
                return json_decode($output,true);
            }
        }
        curl_close($output);
    }

当用户输入一个地名的时候,回复该地区的当前天气预报。使用的api接口为https://www.sojson.com/open/api/weather/json.shtml?city=北京返回的数据为json。自己提取相关的信息,为了方便演示,我只是回复了天气情况,有需要的可以自己添加相关的功能。
实例代码:

<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $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->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //判断是否是用户回复过来的消息
        //用户发送过来消息后回复图文消息或者是单文本消息
        if( strtolower($postObj->MsgType) == 'text' ){
            $toUser = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $content = $this->weather($postObj->Content);
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $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;
    }
}
     public function weather($city){
        //1.初始化curl
        $ch = curl_init();
        $url = 'https://www.sojson.com/open/api/weather/json.shtml?city='.$city;
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //3.采集
        $output = curl_exec($ch);
        //4.关闭
        curl_close($ch);
        $wt = (array) json_decode($output,true);
        $wet = $wt["data"]["forecast"][0]["type"];
        return $wet;
    }
}

以下的格式和参数说明均参考的开发手册

回复纯文本

格式:

<xml> 
    <ToUserName>< ![CDATA[toUser] ]></ToUserName> 
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName> 
    <CreateTime>12345678</CreateTime> 
    <MsgType>< ![CDATA[text] ]></MsgType> 
    <Content>< ![CDATA[你好] ]></Content> 
</xml>

参数说明:

参数是否必须描述
ToUserName接收方帐号(收到的OpenID)
FromUserName开发者微信号
CreateTime消息创建时间 (整型)
MsgTypetext
Content回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

回复图文

格式

<xml>
   <ToUserName>< ![CDATA[toUser] ]></ToUserName>
   <FromUserName>< ![CDATA[fromUser] ]></FromUserName>
   <CreateTime>12345678</CreateTime>
   <MsgType>< ![CDATA[news] ]></MsgType>
   <ArticleCount>1</ArticleCount>
   <Articles>
      <item>
         <Title>< ![CDATA[title1] ]></Title> 
         <Description>< ![CDATA[description1] ]></Description>
         <PicUrl>< ![CDATA[picurl] ]></PicUrl>
         <Url>< ![CDATA[url] ]></Url>
      </item>
   </Articles>
</xml>

参数说明:

参数是否必须说明
ToUserName接收方帐号(收到的OpenID)
FromUserName开发者微信号
CreateTime消息创建时间 (整型)
MsgTypenews
ArticleCount图文消息个数,限制为8条以内
Articles多条图文消息信息,默认第一个item为大图,注意,如果图文数超过8,则将会无响应
Title图文消息标题
Description图文消息描述
PicUrl图片链接,支持JPG、PNG格式,较好的效果为大图360200,小图200200
Url点击图文消息跳转链接

示例代码:(ThinkPHP3.2.3)

<?php
<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $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->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //判断是否是用户回复过来的消息
        //用户发送过来消息后回复图文消息或者是单文本消息
        if( strtolower($postObj->MsgType) == 'text' && trim($postObj->Content)=='孙肖宁' ){
            $toUser = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $arr = array(
                //注意:进行多图文发送时,子图文个数不能超过8个
                array(
                    'title'=>'孙肖宁',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
                array(
                    'title'=>'小宁博客',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
                array(
                    'title'=>'孙肖宁的个人博客',
                    'description'=>"孙肖宁的个人博客",
                    'picUrl'=>'http://www.sunxiaoning.com/usr/themes/handsome/usr/img/aaa.jpg',
                    'url'=>'http://www.sunxiaoning.com',
                ),
            );
            $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');
        }else{
            switch( trim($postObj->Content) ){
                case 1:
                    $content = '您输入的数字是1';
                break;
                case 2:
                    $content = '您输入的数字是2';
                break;
                case 3:
                    $content = '您输入的数字是3';
                break;
                case '博客':
                    $content = "<a href='http://www.sunxiaoning.com'>小宁博客</a>";
                break;
                default:
                    $content = '暂无选项';

            }    
            $toUser   = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time     = time();
            $msgType  =  'text';
            $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;
        }
    }
}

微信公众号开发之自动回复。
首先看下文档,用户关注公众号之后,会发送一段xml格式的文本给服务器。

<xml> 
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>  
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName>  
    <CreateTime>1348831860</CreateTime>  
    <MsgType>< ![CDATA[text] ]></MsgType>  
    <Content>< ![CDATA[this is a test] ]></Content>  
    <MsgId>1234567890123456</MsgId>  
</xml>
参数描述
ToUserName开发者微信号
FromUserName发送方帐号(一个OpenID)
CreateTime消息创建时间 (整型)
MsgTypetext
Content文本消息内容
MsgId消息id,64位整型

回复消息给用户同样也是一段xml

<xml> 
    <ToUserName>< ![CDATA[toUser] ]></ToUserName> 
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName>
    <CreateTime>12345678</CreateTime> 
    <MsgType>< ![CDATA[text] ]></MsgType> 
    <Content>< ![CDATA[你好] ]></Content> 
</xml>
参数是否必须说明
ToUserName接收方帐号(收到的OpenID)
FromUserName开发者微信号
CreateTime消息创建时间 (整型)
MsgTypeimage
MediaId通过素材管理中的接口上传多媒体文件,得到的id。

示例代码(thinkphp3.2.3)

<?php
namespace Wx\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        //获得参数 signature nonce token timestamp echostr
        $nonce     = $_GET['nonce'];
        $token     = 'xxxx';
        $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->reponseMsg();
        }
    }
    public function reponseMsg(){
        //1.获取到微信推送过来post数据(xml格式)
        $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
        //2.处理消息类型,并设置回复类型和内容
        $postObj = simplexml_load_string( $postArr );//xml转换成对象
        //$postObj->ToUserName
        //判断该数据包是否是订阅的事件推送
        if( strtolower( $postObj->MsgType) == 'event'){
            //如果是关注 subscribe 事件
            if( strtolower($postObj->Event == 'subscribe') ){
                //回复用户消息(纯文本格式)    
                $toUser   = $postObj->FromUserName;
                $fromUser = $postObj->ToUserName;
                $time     = time();
                $msgType  =  'text';
                $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;
            }
        }
    }
}

首先安装插件sftp,详情请访问Sublime Text3常用插件以及安装方法
点击文件->SFTP/FTP->Setup Server
1.png
然后就会自动生成sftp-config.json的配置文件,然后再填写配置文件就可以了。

  • 填入你服务器的ip地址host
  • 用户名user
  • 密码password
  • 路径remote_path
    2.png
    保存之后就配置完毕了。
    上传文件的时候,只需要在要上传的文件或者文件夹上面点击鼠标右键,选择SFTP/FTP,再选择Upload Folder。选择下载,也可以把服务器端的文件下载到本地。

第一步:拥有自己的公众号以及服务器(及域名)。
第二步:申请测试账号,一定记住开发者密码(AppSecret),不然就只能重置了。
第三步:进入微信公共平台,点击开发->基本配置->服务器配置->修改规则
填入以下信息
1.png

URL:就是你的服务器的URL(要能响应TOKEN验证,还要能在外网访问到这个服务器)

TOKEN:这个算是自己设置的一个验证码,要自己在代码里面设置的(并且当微信服务器器把GET请求发到你的服务器的时候,能返回这个值)

注:微信服务器的GET请求会带四个参数signature,token,timestamp,echostr;POST请求会带三个参数除了刚才的echostr

  • 获得参数 signature nonce token timestamp echostr
  • 形成数组,然后按字典序排序
  • 拼接成字符串,sha1加密 ,然后与signature进行校验
    实例代码:

    <?php
    /**
    * wechat php test
    */
    
    //define your token;TOKEN一定和你自己的对应起来
    define("TOKEN", "weixin");
    $wechatObj = new wechatCallbackapiTest();
    $wechatObj->valid();
    
    class wechatCallbackapiTest
    {
      public function valid()
      {
          $echoStr = $_GET["echostr"];
    
          //valid signature , option
          if($this->checkSignature()){
              echo $echoStr;
              exit;
          }
      }
    
      public function responseMsg()
      {
          //get post data, May be due to the different environments
          $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    
            //extract post data
          if (!empty($postStr)){
                  /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
                     the best way is to check the validity of xml by yourself */
                  libxml_disable_entity_loader(true);
                    $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()
      {
          // you must define TOKEN by yourself
          if (!defined("TOKEN")) {
              throw new Exception('TOKEN is not defined!');
          }
          
          $signature = $_GET["signature"];
          $timestamp = $_GET["timestamp"];
          $nonce = $_GET["nonce"];
                  
          $token = TOKEN;
          $tmpArr = array($token, $timestamp, $nonce);
          // use SORT_STRING rule
          sort($tmpArr, SORT_STRING);
          $tmpStr = implode( $tmpArr );
          $tmpStr = sha1( $tmpStr );
          
          if( $tmpStr == $signature ){
              return true;
          }else{
              return false;
          }
      }
    }
    
    ?>

EncodingAeskey:直接点击随机生成就好了。

提交之后,会提醒你配置成功。

  • 获得服务器的操作系统: <?PHP echo PHP_OS; ?>
  • 服务器端信息:<?PHP echo $_SERVER ['SERVER_SOFTWARE']; ?>
  • 服务器剩余空间大小:<?PHP echo disk_free_space("/目录"); ?>字节
  • 最大执行时间:<?PHP echo get_cfg_var("max_execution_time")."秒 "; ?>
  • 脚本运行占用最大内存:<?PHP echo get_cfg_var ("memory_limit")?get_cfg_var("memory_limit"):"无" ?>
  • 最大上传限制:<?PHP echo get_cfg_var ("upload_max_filesize")?get_cfg_var ("upload_max_filesize"):"不允许上传附件"; ?>
  • 服务器php版本:<?PHP echo PHP_VERSION; ?>
  • ZEND版本:<?PHP echo zend_version(); ?>
  • mysql版本:<?php @mysql_connect("127.0.0.1", "root", "root"); echo mysql_get_server_info(); ?>
  • MySQL最大连接数: <?php echo @get_cfg_var("mysql.max_links")==-1 ? "不限" : @get_cfg_var("mysql.max_links"); ?>
  • MySQL数据库持续连接:<?php echo @get_cfg_var("mysql.allow_persistent")?"是 ":"否"; ?>

附录:php中的header
浏览器访问http服务器,接收到响应时,会根据响应报文头的内容进行一些具体的操作,在php中,我们能够使用 header来设置这些内容

设置文本编码

设置编码格式为:utf-8
header('content-type:text/html; charset= utf-8');

设置页面跳转:设置跳转到百度首页
header('location:http://www.baidu.com');
设置页面间隔刷新
header('refresh:3; url=http://www.xiaomi.com');

动画是CSS3中具有颠覆性的特征之一,可通过设置多个节点来精确控制一个或一组动画,常用来实现复杂的动画效果。
1、必要元素:
a、通过@keyframes指定动画序列;
b、通过百分比将动画序列分割成多个节点;
c、在各节点中分别定义各属性
d、通过animation将动画应用于相应元素;
2、关键属性
a、animation-name设置动画序列名称。
b、animation-duration动画持续时间。
c、animation-delay动画延时时间。
d、animation-timing-function动画执行速度,linear、ease等。
e、animation-play-state动画播放状态,running、paused等。
f、animation-direction动画逆播,alternate等。
g、animation-fill-mode动画执行完毕后状态,forwards、backwards等。
h、animation-iteration-count动画执行次数,inifinate等。
i、steps(60) 表示动画分成60步完成。
参数值的顺序:关于几个值,除了名字,动画时间,延时有严格顺序要求其它随意。
3、CSS3中的动画:
定义动画:

@keyframes 动画名{
     from{ 初始状态}
       to{结束状态}
}

调用:基本语法格式
animation: 动画名称 持续时间;