如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑(oauth2机制)。

注意,在开发的时候,我们先设置网页授权回调域名


先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。

注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;  

参考https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842


4.png

5.png


获取微信用户信息的具体步骤

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

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

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

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

在第一步的时候,scope参数有两个值

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

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


以snsapi_base为scope的网页授权,就静默授权的,用户无感知,对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。


具体实现

<?php
require APP_PATH . '/Controller/CommonController.php';

class UserController extends CommonController
{
    // 下面三个常量来至微信公众平台配置
    // 注意这里只是演示,在项目开发中请将下面的配置移到配置文件中
    const TOKEN     = ''; // token值自定义,必须和公众平台的设置一致
    const APPID     = '';
    const APPSECRET = '';

    public function __construct() {
        if (!session_id()) {
            session_start();
        }

        parent::__construct();
    }

    /**
     * 页面权限判断
     */
    public function index() {
        $user_info_cache = $this->getCache('userinfo');

        if (!$user_info_cache) {
            $redirect_uri = urlencode ( 'http://xxx.com/user/getUserInfo');
            // 以snsapi_base静默授权
            // 以snsapi_userinfo授权需要用户手动同意,无须关注
            $url ='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.self::APPID.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect';
            header('Location:' . $url);
            exit;
        }

        var_dump(json_decode($user_info_cache['value'], JSON_UNESCAPED_UNICODE));
        echo "<hr/>";
    }

    /**
     * 拉取用户信息
     * 注意:sns/userinfo接口需scope为 snsapi_userinfo
     */
    public function getUserInfo() {
        $code          = $_GET['code'];
        $get_token_uri = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.self::APPID.'&secret='.self::APPSECRET.'&code='.$code.'&grant_type=authorization_code';

        // 获取网页授权access_token和openid
        $result = json_decode($this->http_request($get_token_uri), true);
        $access_token = $result['access_token'];
        $open_id      = $result['openid'];

        // 拉取用户详细信息
        $userinfo_uri = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$open_id}&lang=zh_CN";
        //$userinfo_uri = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$open_id}&lang=zh_CN";
        $result       = json_decode($this->http_request($userinfo_uri), true);

        $this->setCache('userinfo', json_encode($result, JSON_UNESCAPED_UNICODE), 7200);

        var_dump($userinfo_uri);
        var_dump($result);
    }

    /**
     * 获取全局TOKEN
     * @return mixed
     */
    public function getAccessToken() {
        $access_token_cache = $this->getCache('access_token');

        if(!$access_token_cache)
        {
            $url    = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.self::APPID.'&secret='.self::APPSECRET;
            $result = json_decode($this->http_request($url), true);

            $access_token = $result['access_token'];
            $this->setCache('access_token', $access_token, $result['expires_in']);
        } else {
            $access_token = $access_token_cache['value'];
        }

        return $access_token;
    }

    /**
     * 获取缓存数据
     * @param $cacheKey
     * @return bool
     */
    private function getCache($cacheKey) {
        if (isset($_SESSION[$cacheKey])) {
            return ($_SESSION[$cacheKey]['expire'] > time()) ? $_SESSION[$cacheKey] : false;
        } else {
            return false;
        }
    }

    /**
     * 设置缓存
     * @param $cacheKey
     * @param $value
     * @param $expire
     */
    private function setCache($cacheKey, $value, $expire) {
        $_SESSION[$cacheKey] = [
            'value'  => $value,
            'expire' => time() + $expire
        ];
    }

    /**
     * 发起请求
     * @param $url
     * @param null $data
     * @return mixed
     */
    private function http_request($url, $data = null) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        if (!empty($data))
        {
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($data))
            );
        }

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
}

7.png