PHP微信公众号开发常用功能

最近学习了关于微信公众号开发的相关知识,为了帮助自己更好的理解,在此重新再梳理一遍 
更多关于微信公众号开发的功能可以参考微信公众平台的开发技术文档

完成开发者配置

第一步,需要在微信公众平台配置我们的服务器 

在接口的文件需要写入以下代码以完成验证:

class Wxapi
{
    public function __construct()
    {
        $this->index();
    }

    public function index()
    {
        $echostr = isset($_GET[‘echostr‘]) ? $_GET[‘echostr‘] : ‘‘;
        if($$this->checkSignature && $echostr){
            echo $echostr; //输出微信服务器传过来的验证通过的字符串
        } else {
            $this->responseMsg(); //后面部分再提这个方法
        }
    }

    public function checkSignature()
    {
        //获取微信服务器传过来的signature、token、nonce和timestamp
        $token = "weixin"; //这是我自己设置的token值
        $timestamp() = $_GET[‘timestamp‘];
        $nonce = $_GET[‘nonce‘];
        $signature = $_GET[‘signature‘];
        //对token、nonce和timestamp按字典序排序
        $tmpArr = array($token, $nonce, $timestamp);
        sort($tmpArr);

        //与singnature进行对比校验
        if($tmpArr == $signature){
            return true;
        } else {
            return false;
        }
    }
}

curl方法

在微信公众号开发过程中,我们的第三方服务器(公众号中配置的接口服务器)与微信之间的通信都是用curl的方式来完成的,下面写一下我开发过程中用到的curl实例方法

class Wxapi
{
    public function httpCurl($url, $type=‘get‘, $postData=‘‘)
    {
        //1.初始化
        $ch = curl_init();
        //2.设置curl参数
        curl_setopt($ch, CURLOPT_URL, $url); //要链接的url
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以字符串返回,而不是直接输出。
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//部分链接url要以https协议进行,设定以跳过证书验证
        if($type == ‘post‘){
            curl_setopt($ch, CURLOPT_POST, true); //true时发送post请求;
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        }
        //3.执行curl请求
        $res = curl_exec($ch); //将返回一个json格式的字符串
        //4.返回结果并关闭curl连接
        if(curl_errno($ch)){
            return curl_error($ch);
        }
        curl_close($ch);
        return $res;
    }
}

获取access_token

这里的access_token是指的全局access_token 在调用很多微信后台的接口时都需要用access_token验证,通过后才可以调用相关接口实现相应的功能,我们可以通过appid和appsecret获取到我们的access_token 

class Wxapi
{
    public function getWxAccessToken()
    {
        if($_SESSION[‘access_token‘] && $_SESSION[‘expire_time‘] > time()){
            return $_SESSION[‘access_token‘];
        } else {
            $appid = ‘‘; //填入自己的appid
            $appsecret = ‘‘;
            $url = ‘https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=‘.$appid.‘&secret=‘.$appsecret;
            $res = $this->httpCurl($url); //调用上面提到的curl方法
            $res = json_decode($res, true);
            $access_token = $res[‘access_token‘];
            $_SESSION[‘access_token‘] = $access_token; //将access_token存入缓存,也可用redis、memcache等方式
            $_SESSION[‘expire_time‘] = time()+7000; //获取的access_token的有效期为7200秒,因此缓存的时间应小于7200秒;
            return $access_token();
    }
}

获取微信服务器的IP地址

很多时候我们会收到微信传过来的信息,但是我们并不清楚这些信息是不是真的是由微信服务器传过来的,因此微信也提供了一个接口,返回微信服务器的地址以便我们验证信息来源;

class Wxapi
{
    public function getWxServerIp()
    {
        $access_token = $this->getWxAccessToken();
        $url = ‘https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=‘.$access_token;
        $res = $this->httpCurl($url);
        $arr = json_decode($res,true);
        return $arr;
    }
}

自定义菜单

自定义菜单是公众号常用的一个功能,每个公众号有自己的定位,菜单的内容当然也不同,自定义菜单也需要使用全局access_token来完成。下面用实例写两种常用的菜单类型,更多内容请参考开发文档

public function defineMenu()
{
    $access_token = $this->getWxAccessToken();
    $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
    //菜单内容
    $postArr = array(
        ‘button‘ => array(
            //第一个一级菜单
            array(
                ‘name‘ => ‘菜单名‘,
                ‘type‘ => ‘click‘, //分为click和view两种,click为点击事件,view为跳转到指定url
                ‘key‘  => ‘EventKey‘ // type为click时为key,可针对传入的eventkey设定回复内容,见下面的事件回复
            ),
            //第二个一级菜单
            array(
                ‘name‘ => ‘‘,
                ‘sub_button‘ => array(
                    //二级菜单
                    array(
                        ‘name‘ => ‘‘,
                        ‘type‘ => ‘view‘,
                        ‘url‘  => ‘‘ //type为view时key值为url
                    )
                )
            )
        )
    );
    $postJson = json_encode($postArr); //post数据的格式为json
    $res = $this->httpCurl($url, ‘post‘, $postJson);
}

事件回复及关键字回复

验证通过后,可以开始配置我们公众号常用的一些功能,这部分主要是事件回复以及关键回复 
事件回复我这里主要指的用户关注的事件,具体消息的模版参考微信公众平台开发模版的消息管理

class Wxapi
{
    public function responseMsg()
    {
        //1.获取微信推过来的post数据(xml格式)
        $postArr = $GLOBALS[‘HTTP_RAW_POST_DATA‘];
        //2.根据消息类型进行回复
        if(!empty($postArr)){
            $postObj = simplexml_load_string($postArr); //将xml数据转换为对象
            //2.1.判断消息类型
            if(strtolower($postObj->MsgType) == ‘event‘){
                //关注事件,新用户关注后自动回复
                if(strtolower($postObj->Event) == ‘subcribe‘){
                    $content = ‘‘; //自定义回复内容
                    $info = $this->responseText($postObj, $content);
                    echo $info;
                } elseif(strtolower($postObj->Event) == ‘click‘){
                    //点击菜单事件
                    switch($postObj->EventKey){
                        case ‘‘: //自定义菜单关键字
                            $content = ‘‘; //自定义回复内容
                            $info = $this->responseText($postObj, $content);
                            echo $info;
                            break;
                        case ‘‘: //
                            //也可回复图文消息
                            $arr = array(
                                array(
                                    ‘title‘ => ‘潮图|你的姆爷Slim Shady‘,
                                    ‘description‘ => ‘高能预警‘,
                                    ‘picUrl‘ => ‘‘,
                                    ‘url‘ => ‘‘,
                                )
                            );
                            $info = $this->responseNews($postObj, $arr);
                            echo $info;
                            break;
                    }
                } elseif(strtolower($postObj->Event) == ‘scan‘) {
                    //扫码事件,用户扫码后会跳转至公众号,可自动回复相关内容
                    switch ($postObj->EventKey){
                        case 2000:
                            $content = "";
                            $info = $this->responseText($postObj, $content);
                            echo $info;
                            break;
                    }
                }
            }
            //用户输入关键字回复
            if(strtolower($postObj->MsgType) == ‘text‘){
                $keyword = trim($postObj->Content);
                if(!empty($keyword)) {
                    //返回图文信息
                    if($keyword == ‘slimshady‘){
                        $arr = array(
                            array(
                                ‘title‘ => ‘‘,
                                ‘description‘ => ‘‘,
                                ‘picUrl‘ => ‘‘,
                                ‘url‘ => ‘‘,
                            ),
                        );
                        $info = $this->responseNews($postObj, $arr);
                        echo $info;
                    }
                    //返回文本消息
                    switch ($keyword) {
                        case ‘shadypop‘:
                            //返回的文本消息也可以是链接形式
                            $content = "<a href=‘http://jason9351.get.vip‘>欢迎访问我的主页</a>";
                            break;
                        default:
                            $content = "表示看不懂你说的";
                            break;
                    }
                    $info = $indexModel->responseText($postObj, $content);
                    echo $info;
                }
            }
        }
    }

    //回复文字消息
    public function responseText($postObj, $content)
    {
        $toUser = $postObj->FromUserName;
        $fromUser = $postObj->ToUserName;
        $time = time();
        //返回文字消息的模板
        $textTpl = "<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[text]]></MsgType>
                    <Content><![CDATA[%s]]></Content>
                    </xml>";
        $info = sprintf($textTpl, $toUser, $fromUser, $time, $content);
        return $info;
    }

    //回复图文消息
    public function responseNews($postObj, $arr)
    {
        $toUser = $postObj->FromUserName;
        $fromUser = $postObj->ToUserName;
        $time = time();
        $newsTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[news]]></MsgType>
                        <ArticleCount>".count($arr)."</ArticleCount>
                        <Articles>";
        foreach ($arr as $k => $v) {
            $newsTpl .= "<item>
                        <Title><![CDATA[".$v[‘title‘]."]]></Title>
                        <Description><![CDATA[".$v[‘description‘]."]]></Description>
                        <PicUrl><![CDATA[".$v[‘picUrl‘]."]]></PicUrl>
                        <Url><![CDATA[".$v[‘url‘]."]]></Url>
                        </item>";
        }
        $newsTpl .= "</Articles>
                    </xml>";
        $info = sprintf($newsTpl, $toUser, $fromUser, $time);
        return $info;
    }
}

生成带参数的二维码

目前微信支持生成临时二维码和永久二维码两种。临时二维码有效期为30天,主要用于帐号绑定等不要求二维码永久保存的业务场景。永久二维码没有过期时间,但是数量有限,为10万个,主要用于适用于帐号绑定、用户来源统计等场景。

用户扫描带场景值二维码时,可能推送以下两种事件: 
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。 
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

生成二维码分为两步:首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。

创建二维码ticket 
每次创建二维码ticket需要提供一个开发者自行设定的参数(scene_id); 
临时二维码:

public function getTmpQRCode()
{
     //1.获取ticket票据
        $access_token = $this->getWxAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$access_token;
        $postArr = array(
            ‘expire_seconds‘ => 604800, //24*60*60*7
            ‘action_name‘    => ‘QR_SCENE‘,
            ‘action_info‘    => array(
                ‘scene‘      => array(‘scene_id‘ => ‘自行设定‘)//扫码事件中的EventKey
            )
        );
        $postJson = json_encode($postArr);
        $res = $this->httpCurl($url, ‘post‘, $postJson);
        $res = json_decode($res, true);
        $ticket = urlencode($res[‘ticket‘]);
        //2.使用ticket获取二维码图片
        $url = ‘https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=‘.$ticket;
        echo "<img src=‘{$url}‘ />";
}

永久二维码: 
永久二维码与临时二维码不同就在于action_name不同,并且没有expire_time:

public function getInsQRCode()
{
     //1.获取ticket票据
        $access_token = $this->getWxAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$access_token;
        $postArr = array(
            ‘action_name‘    => ‘QR_LIMIT_SCENE‘,
            ‘action_info‘    => array(
                ‘scene‘      => array(‘scene_id‘ => ‘‘)//扫码事件中的EventKey
            )
        );
        $postJson = json_encode($postArr);
        $res = $this->httpCurl($url, ‘post‘, $postJson);
        $res = json_decode($res, true);
        $ticket = urlencode($res[‘ticket‘]);
        //2.使用ticket获取二维码图片
        $url = ‘https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=‘.$ticket;
        echo "<img src=‘{$url}‘ />";
}

获取网页授权以及用户的基本信息

在用户同意授权的情况下,我们可以获取到用户的一些基本信息,来实现我们的业务逻辑

关于授权回调域名的两点说明:

1.在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;

2.授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

另外, 网页授权也分为两种类型,分别是scope_base和scope_userinfo,两者有以下区别:

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)//即无需用户点击同意

2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

具体而言,网页授权流程分为四步:

1、引导用户进入授权页面同意授权,获取code 
2、通过code换取网页授权access_token(与基础支持中的access_token不同) 
3、如果需要,开发者可以刷新网页授权access_token,避免过期 
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

以下为实例: 
只获取用户openid,scope_base类型

public function getBaseInfo()
{
    $appid = ‘‘; //上文提及的公众号自己的appid
    $redirectUri = urlencode(‘调用getUserOpenId的uri‘);
    $url = ‘https://open.weixin.qq.com/connect/oauth2/authorize?appid=‘.$appId.‘&redirect_uri=‘.$redirectUri.‘&response_type=code&scope=snsapi_base&state=123#wechat_redirect‘;
    header(‘location:‘.$url); //此步仅做演示,实际业务中引导用户访问调用此方法的链接来跳转至redirectUrl
}

public function getUserOpenId()
{
    $appId = ‘wx693062b792d58274‘;
    $appSecret = ‘885cab15b3d47e0ccddfb065da734eff‘;
    $code = $_GET[‘code‘]; //getBaseInfo 方法传来的code
    $url = ‘https://api.weixin.qq.com/sns/oauth2/access_token?appid=‘.$appId.‘&secret=‘.$appSecret.‘&code=‘.$code.‘&grant_type=authorization_code‘;
    $res = $this->httpCurl($url);
    //返回值的格式:{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
}

至此,我们就获取到了我们需要的openid值。 
获取用户的详细信息

public function getBaseInfo()
{
    $appid = ‘‘; //上文提及的公众号自己的appid
    $redirectUri = urlencode(‘调用getUserInfo的uri‘);
    $url = ‘https://open.weixin.qq.com/connect/oauth2/authorize?appid=‘.$appId.‘&redirect_uri=‘.$redirectUri.‘&response_type=code&scope=snsapi_base&state=123#wechat_redirect‘;
    header(‘location:‘.$url); //此步仅做演示,实际业务中引导用户访问调用此方法的链接来跳转至redirectUrl
}

public function getUserInfo()
{
    //获取openid和网页授权access_token
    $appId = ‘wx693062b792d58274‘;
    $appSecret = ‘885cab15b3d47e0ccddfb065da734eff‘;
    $code = $_GET[‘code‘]; //getBaseInfo 方法传来的code
    $url = ‘https://api.weixin.qq.com/sns/oauth2/access_token?appid=‘.$appId.‘&secret=‘.$appSecret.‘&code=‘.$code.‘&grant_type=authorization_code‘;
    $res = $this->httpCurl($url);
    //返回值的格式:{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
    $res = json_decode($res, true);
    $access_token = $res[‘access_token‘];
    $openid = $res[‘openid‘];

    //获取用户的详细信息
    $url = ‘ https://api.weixin.qq.com/sns/userinfo?access_token=‘.$access_token.‘&openid=‘.$openid.‘&lang=zh_CN‘;
    $arr = $this->httpCurl($url);
}

此处返回以下格式的内容:

正确时返回的JSON数据包如下:
{"openid":" OPENID",
 "nickname": NICKNAME,
 "sex":"1",
 "province":"PROVINCE"
 "city":"CITY",
 "country":"COUNTRY",
 "headimgurl":
 "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
 "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
 "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
} 

原文地址:https://www.cnblogs.com/chenduzizhong/p/9167138.html

时间: 2024-10-19 10:50:50

PHP微信公众号开发常用功能的相关文章

微信公众号开发 常用脚本累计

关注指定公众号: //gh_ef65912f88f1 为被添加者的微信ID WeixinJSBridge.invoke("addContact", {webtype: "1",username: 'gh_ef65912f88f1'}, function(e) { WeixinJSBridge.log(e.err_msg); //e.err_msg:add_contact:added 已经添加 //e.err_msg:add_contact:cancel 取消添加 /

微信公众号开发工具包,封装常用接口等

微信公众号开发套件 涵盖微信提供的大多数常用接口,具体实现功能如下: 一.消息管理 1.模板消息.支持单个用户发送和批量发送,支持同步发送和一步发送. 2.一次性订阅消息. 3.客服消息.包括下发文本.图片等. 二.菜单管理 1.自定义菜单创建.查询.删除.个性化菜单配置等功能. 三.素材管理 1.获取临时素材 2.获取永久素材 3.删除素材 4.获取素材总数 5.获取素材列表 四.账号管理 1.生成带参数的二维码 2.长连接转短连接 五.用户管理 1.用户标签管理 2.设置用户备注名称 3.获

C#微信公众号开发系列教程五(接收事件推送与消息排重)

微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C#微信公众号开发系列教程四(接收普通消息) C#微信公众号开发系列教程五(接收事件推送与消息排重) 在上一篇的博文中讲到,微信的消息可以大体分为两种类型,一种是包括:文本,语音,图片等的普通消息,另一种就是本篇要将的事件类型.包括:关注/取消关注事件,扫描带参数二维码事件,上报地理位置事件,自定义菜

JAVA微信公众号开发入门

好久没进博客,最近应某人的要求,要每周写一篇博客,故此今天就把我这周刚学的微信公众号开发的知识在此总结总结,以供后人查阅.我写博客都是简要白话文,勿喷. 1.为什么要学微信公众号开发 微信的用户量庞大,微信公众号的完善和不断的开放力度,企业市场对公众号开发的需求不断增加 2.如何搭建微信开发平台 开发工具什么的就不说了,因为微信是要外网访问的,所有你必须有个网上的服务器资源,而且你必须申请一个微信公众号. 2.1申请微信公众号 公众号有3种:订阅号,服务号,企业号 区别是企业号适合内部人使用,因

微信公众号开发(2)---消息的接收发送

在微信公众号开发(1)中,我们进行了GET请求方法的开发编写,能够使微信与我们的服务器进行了关系的绑定,接下来我们进行开发接收用户消息与一些事件的回复:      开发必要了解:在我们微信与我们的服务器进行了关系的绑定后,微信会将用户所发过来的消息以及事件会以XML的格式以POST请求的方式发送给我们的服务器,所以我们需要开发POST请求的接口,接收用户的消息,我们可以根据用户的消息进行一些关键字回复,以及关注后的回复推送,微信事件里有很多功能,这里只进行开发关键字回复以及关注事件,其他的顺藤摸

微信公众号开发--接入

微信公众号开发 微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 需要绑定开发者账号:微信公众平台--开发者工具--web开发者工具--绑定开发者微信号 微信公众平台接口调试工具:https://mp.weixin.qq.com/debug/ 接口调试需要使用"access_token",access_token的获取需要从在基本设置中的url访问获取,其他终端基本无法获取 1

微信公众号开发总结

最近公司用到了微信公众平台,所以研究了一下微信公众号的开发技术,总体来说比较简单,结合现有的平台核技术,实现起来非常方便. 首先先来了解一下微信公众平台. "微信,是一个生活方式" ,这是微信的自我评价,是不是觉得如果那天不在朋友圈里分享一下自己的最新状态, 并且收到几个赞和评价的话,会觉得空虚寂寞呢?它实实在在的改变了我们的生活方式. " 微信,也是一个生意方式 ",在微信成为我们日常必备之app的同时,它同样具备巨大的的商业 或许不应该称为潜力,因为有很多人已经

C#微信公众号开发 -- (五)自定义菜单创建

公众号中,底部都是有自己定义的功能按钮,通过点击某个按钮来实现指定的业务逻辑操作. 下面就来说说这些按钮是怎样放到微信公众平台的,还是先来看看微信的官方解释: 请注意: 1.自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单. 2.一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替. 3.创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单, 如果菜单有更新,就会刷

nodejs + BAE 搭建微信公众号开发平台

闲来无事创建了一个微信公众账号,名曰“深圳生活小助手”, 关注的人不多,平时发一些深圳新闻,趣事啥的,为了丰富公众号的内容,准备添加一些便民查询功能,例如天气预报.快递查询等等. 于是就有了本文的内容. 深圳的读者扫描关注支持下啊... 闲话不多说,本文主要介绍的就是如何基于nodejs和百度云搭建微信公众号开发平台,下一节介绍如何基于该平台实现了一个简单的天气预报查询功能的小例子. 1. 使用Express搭建本地站点 Express 是一个简洁.灵活的 node.js Web 应用开发框架,