搜索
首页微信小程序微信开发微信授权登录并获取用户信息接口

微信授权登录并获取用户信息接口

Mar 01, 2017 am 09:19 AM
微信开发

  近排在做微信接口开发,所以总结一下微信授权登录并获取用户信息 这个接口的开发流程。

一、首先你的微信公众号要获得相应的AppID和AppSecret,申请微信登录且通过审核后,才可开始接入流程。

二、授权流程

1、流程说明

(1). 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数; 

(2). 通过code参数加上AppID和AppSecret等,通过API换取access_token;

(3). 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

2、获取access_token时序图:

微信授权登录并获取用户信息接口

三、开发(我的用是CI框架,其实用什么框架都一样,MVC模式就行了)

1、请求CODE

  weixin.php

<?php
    class weixinController extends CI_Controller {
        public $userInfo;
        public $wxId;


        public function __construct(){
            parent::__construct();

            //只要用户一访问此模块,就登录授权,获取用户信息
            $this->userInfo = $this->getWxUserInfo();
        }
    

        /**
         * 确保当前用户是在微信中打开,并且获取用户信息
         *
         * @param string $url 获取到微信授权临时票据(code)回调页面的URL
         */
        private function getWxUserInfo($url = &#39;&#39;) {
            //微信标记(自己创建的)
            $wxSign = $this->input->cookie(&#39;wxSign&#39;);
            //先看看本地cookie里是否存在微信唯一标记,
            //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
            if (!empty($wxSign)) {
                //如果存在,则从Redis里取出缓存了的数据
                $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
                if (!empty($userInfo)) {
                    //获取用户的openid
                    $this->wxId = $userInfo[&#39;openid&#39;];
                    //将其存在cookie里
                    $this->input->set_cookie(&#39;wxId&#39;, $this->wxId, 60*60*24*7);
                    return $userInfo;
                }
            }

            //获取授权临时票据(code)
            $code = $_GET[&#39;code&#39;];
            if (empty($code)) {
                if (empty($url)) {
                    $url = rtirm($_SERVER[&#39;QUERY_STRING&#39;], &#39;/&#39;);
                    //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
                    redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
                }
            }


        }

    }
?>

获取code的Controller代码

   Wxmodel.php

<?php
    class WxModel extends ModelBase{
        public $appId;
        public $appSecret;
        public $token;

        public function __construct() {
            parent::__construct();

            //审核通过的移动应用所给的AppID和AppSecret
            $this->appId = &#39;wx0000000000000000&#39;;
            $this->appSecret = &#39;00000000000000000000000000000&#39;;
            $this->token = &#39;00000000&#39;;
        }

        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
       public function getOAuthUrl($redirectUrl, $openIdOnly, $state = &#39;&#39;) {
        $redirectUrl = urlencode($redirectUrl);
        $scope = $openIdOnly ? &#39;snsapi_base&#39; : &#39;snsapi_userinfo&#39;;
        $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state";
        return $oAuthUrl;
       }

获取code的Model代码

获取code的Model代码

 

这里附上请求参数说明和返回值说明

  请求参数说明:

微信授权登录并获取用户信息接口

 

  响应返回值说明:

微信授权登录并获取用户信息接口

 

  当请求成功,会redirect到请求参数中的redirect_uri的值中去,其实又回到weixin.php的$this->userInfo = $this->getWxUserInfo();这行去,然后再一次进入到getWxUserInfo()方法,此时

            //获取授权临时票据(code)
            $code = $_GET[&#39;code&#39;];

 这行也已经能获取得到code的值了。接着进行第二步。

 

2、通过code获取access_token

  weixin.php

userInfo = $this->getWxUserInfo();
        }
    

        /**
         * 确保当前用户是在微信中打开,并且获取用户信息
         *
         * @param string $url 获取到微信授权临时票据(code)回调页面的URL
         */
        private function getWxUserInfo($url = '') {
            //微信标记(自己创建的)
            $wxSign = $this->input->cookie('wxSign');
            //先看看本地cookie里是否存在微信唯一标记,
            //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
            if (!empty($wxSign)) {
                //如果存在,则从Redis里取出缓存了的数据
                $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
                if (!empty($userInfo)) {
                    //获取用户的openid
                    $this->wxId = $userInfo['openid'];
                    //将其存在cookie里
                    $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
                    return $userInfo;
                }
            }

            //获取授权临时票据(code)
            $code = $_GET[&#39;code&#39;];
            if (empty($code)) {
                if (empty($url)) {
                    $url = rtirm($_SERVER['QUERY_STRING'], '/');
                    //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
                    redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
                }
            }
            /***************这里开始第二步:通过code获取access_token****************/
            $result = $this->model->wx->getOauthAccessToken($code);

            //如果发生错误
            if (isset($result['errcode'])) {
                return array('msg'=>'授权失败,请联系客服','result'=>$result);
            }

            //到这一步就说明已经取到了access_token
            $this->wxId = $result['openid'];
            $accessToken = $result['access_token'];
            $openId = $result['openid'];

            //将openid和accesstoken存入cookie中
            $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7);
            $this->input->set_cookie('access_token', $accessToken);

获取access_token的控制器代码

获取access_token的控制器代码

  WxModel.php

<?php
    class WxModel extends ModelBase{
        public $appId;
        public $appSecret;
        public $token;

        public function __construct() {
            parent::__construct();

            //审核通过的移动应用所给的AppID和AppSecret
            $this->appId = &#39;wx0000000000000000&#39;;
            $this->appSecret = &#39;00000000000000000000000000000&#39;;
            $this->token = &#39;00000000&#39;;
        }


        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
        public function getOAuthUrl($redirectUrl, $openIdOnly, $state = &#39;&#39;) {
            $redirectUrl = urlencode($redirectUrl);
            $scope = $openIdOnly ? &#39;snsapi_base&#39; : &#39;snsapi_userinfo&#39;;
            $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
            return $oAuthUrl;
        }


        /**
        * 获取access_token
        */
        public function getoAuthAccessToken($code) {
            return json_decode(file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->AppId}&secret={$this->AppSecret}&code={$authCode}&grant_type=authorization_code",true);
        }

获取access_token的Model代码

获取access_token的Model代码

这里附上参数说明

  请求参数说明:

微信授权登录并获取用户信息接口

 

  响应返回值说明:

微信授权登录并获取用户信息接口

  当返回错误时是这样子的:

微信授权登录并获取用户信息接口

 

3、通过access_token调用接口(获取用户信息)
  获取access_token后,进行接口调用,有以下前提:

  (1)access_tokec有效且未超时;

  (2)微信用户已授权给第三方应用账号相应的接口作用域(scope)。

  

  以下是获取用户信息的代码

  weixin.php

userInfo = $this->getWxUserInfo();
        }
    

        /**
         * 确保当前用户是在微信中打开,并且获取用户信息
         *
         * @param string $url 获取到微信授权临时票据(code)回调页面的URL
         */
        private function getWxUserInfo($url = '') {
            //微信标记(自己创建的)
            $wxSign = $this->input->cookie('wxSign');
            //先看看本地cookie里是否存在微信唯一标记,
            //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
            if (!empty($wxSign)) {
                //如果存在,则从Redis里取出缓存了的数据
                $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
                if (!empty($userInfo)) {
                    //获取用户的openid
                    $this->wxId = $userInfo['openid'];
                    //将其存在cookie里
                    $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
                    return $userInfo;
                }
            }

            //获取授权临时票据(code)
            $code = $_GET[&#39;code&#39;];
            if (empty($code)) {
                if (empty($url)) {
                    $url = rtirm($_SERVER['QUERY_STRING'], '/');
                    //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
                    redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
                }
            }
            /***************这里开始第二步:通过code获取access_token****************/
            $result = $this->model->wx->getOauthAccessToken($code);

            //如果发生错误
            if (isset($result['errcode'])) {
                return array('msg'=>'授权失败,请联系客服','result'=>$result);
            }

            //到这一步就说明已经取到了access_token
            $this->wxId = $result['openid'];
            $accessToken = $result['access_token'];
            $openId = $result['openid'];

            //将openid和accesstoken存入cookie中
            $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7);
            $this->input->set_cookie('access_token', $accessToken);

            /*******************这里开始第三步:通过access_token调用接口,取出用户信息***********************/
            $this->userInfo = $this->model->wx->getUserInfo($openId, $accessToken);

            //自定义微信唯一标识符
            $wxSign =substr(md5($this->wxId.'k2a5dd'), 8, 16);
            //将其存到cookie里
            $this->input->set_cookie('wxSign', $wxSign, 60*60*24*7);
            //将个人信息缓存到redis里
            $this->library->redisCache->set("weixin:sign_{$wxSign}", $userInfo, 60*60*24*7);
            return $userInfo;
        }

    }
?>

获取用户信息的Controller

获取用户信息的Controller

  WxModel.php

<?php
    class WxModel extends ModelBase{
        public $appId;
        public $appSecret;
        public $token;

        public function __construct() {
            parent::__construct();

            //审核通过的移动应用所给的AppID和AppSecret
            $this->appId = &#39;wx0000000000000000&#39;;
            $this->appSecret = &#39;00000000000000000000000000000&#39;;
            $this->token = &#39;00000000&#39;;
        }


        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
        public function getOAuthUrl($redirectUrl, $openIdOnly, $state = &#39;&#39;) {
            $redirectUrl = urlencode($redirectUrl);
            $scope = $openIdOnly ? &#39;snsapi_base&#39; : &#39;snsapi_userinfo&#39;;
            $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
            return $oAuthUrl;
        }


        /**
        * 获取access_token
        */
        public function getoAuthAccessToken($code) {
            return json_decode(file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->AppId}&secret={$this->AppSecret}&code={$authCode}&grant_type=authorization_code",true);
        }

        /**
        * 获取用户信息  
        */
        public function getUserInfo($openId, $accessToken) {
            $url = &#39;https://api.weixin.qq.com/sns/userinfo&#39;;
            //获取用户微信账号信息
            $userInfo = $this->callApi("$url?access_token=$accessToken&openid=$openId&lang=zh-CN");

            if ($userInfo[&#39;errcode&#39;]) {
                return array(&#39;msg&#39;=>&#39;获取用户信息失败,请联系客服&#39;, $userInfo);
            }

            $userInfo[&#39;wx_id&#39;] = $openId;

            return $userInfo;
        }

        /**
         * 发起Api请求,并获取返回结果
         * @param string 请求URL
         * @param mixed 请求参数 (array|string)
         * @param string 请求类型 (GET|POST)
         * @return array        
         */
        public function callApi($apiUrl, $param = array(), $method = &#39;GET&#39;) {
            $result = curl_request_json($error, $apiUrl, $params, $method);
            //假如返回的数组有错误码,或者变量$error也有值
            if (!empty($result[&#39;errcode&#39;])) {
                $errorCode = $result[&#39;errcode&#39;];
                $errorMsg = $result[&#39;errmsg&#39;];
            } else if ($error != false) {
                $errorCode = $error[&#39;errorCode&#39;];
                $errorMsg = $error[&#39;errorMessage&#39;];
            }

            if (isset($errorCode)) {
                //将其插入日志文件
                file_put_contents("/data/error.log", "callApi:url=$apiUrl,error=[$errorCode]$errorMsg");

                if ($errorCode === 40001) {
                    //尝试更正access_token后重试
                    try {
                        $pos = strpos(strtolower($url), &#39;access_token=&#39;);
                        if ($pos !==false ) {
                            $pos += strlen(&#39;access_token=&#39;);
                            $pos2 = strpos($apiUrl, &#39;&&#39; ,$pos);
                            $accessTokened = substr($apiUrl, $pos, $pos2 === false ? null : ($pos2 - $pos));
                            return $this->callApi(str_replace($accessTokened, $this->_getApiToken(true), $apiUrl), $param, $method);
                        }
                    }catch (WeixinException $e) { 

                    }
                }
                //这里抛出异常,具有的就不详说了
                throw new WeixinException($errorMessage, $errorCode);
            }
            return $result;
        }

        /**
        * 获取微信 api 的 access_token 。 不同于 OAuth 中的 access_token ,参见  http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token
        *
        * @param bool 是否强制刷新 accessToken
        */
        private function _getApiToken($forceRefresh = false) {
            //先查看一下redis里是否已经缓存过access_token
            $accessToken = $this->library->redisCache->get(&#39;Weixin:AccessToken&#39;);
            if($forceRefresh || empty($accessToken)) {
                $result = $this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}");
                $accessToken = $result[&#39;access_token&#39;];
                $expire = max(1, intval($result[&#39;expires_in&#39;]) - 60);
                //将access_token缓存到redis里去
                $this->library->redisCache->set(&#39;Weixin:AccessToken&#39;, $accessToken, $expire);
            }
            return $accessToken;
        }

?>

获取用户信息的Model

  Common.php

<?php
    /**
     *   发起一个HTTP(S)请求,并返回json格式的响应数据
     *   @param array 错误信息  array($errorCode, $errorMessage)
     *   @param string 请求Url
     *   @param array 请求参数
     *   @param string 请求类型(GET|POST)
     *   @param int 超时时间
     *   @param array 额外配置
     *   
     *   @return array
     */ 
    public function curl_request_json(&$error, $url, $param = array(), $method = &#39;GET&#39;, $timeout = 10, $exOptions = null) {
        $error = false;
        $responseText = curl_request_text($error, $url, $param, $method, $timeout, $exOptions);
        $response = null;
        if ($error == false && $responseText > 0) {
            $response = json_decode($responseText, true);

            if ($response == null) {
                $error = array(&#39;errorCode&#39;=>-1, &#39;errorMessage&#39;=>&#39;json decode fail&#39;, &#39;responseText&#39;=>$responseText);
                //将错误信息记录日志文件里
                $logText = "json decode fail : $url";
                if (!empty($param)) {
                    $logText .= ", param=".json_encode($param);
                }
                $logText .= ", responseText=$responseText";
                file_put_contents("/data/error.log", $logText);
            }
        }
        return $response;
    }

    /**
    *  发起一个HTTP(S)请求,并返回响应文本
    *   @param array 错误信息  array($errorCode, $errorMessage)
    *   @param string 请求Url
    *   @param array 请求参数
    *   @param string 请求类型(GET|POST)
    *   @param int 超时时间
    *   @param array 额外配置
    *   
    *   @return string
    */
    public function curl_request_text(&$error, $url, $param = array(), $method = &#39;GET&#39;, $timeout = 15, $exOptions = NULL) {
        //判断是否开启了curl扩展
        if (!function_exists(&#39;curl_init&#39;)) exit(&#39;please open this curl extension&#39;);

        //将请求方法变大写
        $method = strtoupper($method);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        if (isset($_SERVER[&#39;HTTP_USER_AGENT&#39;])) curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER[&#39;HTTP_USER_AGENT&#39;]);
        if (isset($_SERVER[&#39;HTTP_REFERER&#39;])) curl_setopt($ch, CURLOPT_REFERER, $_SERVER[&#39;HTTP_REFERER&#39;]);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        switch ($method) {
            case &#39;POST&#39;:
                curl_setopt($ch, CURLOPT_POST, true);
                if (!empty($param)) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($param)) ? http_build_query($param) : $param);
                }
                break;
            
            case &#39;GET&#39;:
            case &#39;DELETE&#39;:
                if ($method == &#39;DELETE&#39;) {
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, &#39;DELETE&#39;);
                }
                if (!empty($param)) {
                    $url = $url.(strpos($url, &#39;?&#39;) ? &#39;&&#39; : &#39;?&#39;).(is_array($param) ? http_build_query($param) : $param);
                }
                break;
        }
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
        curl_setopt($ch, CURLOPT_URL, $url);
        //设置额外配置
        if (!empty($exOptions)) {
            foreach ($exOptions as $k => $v) {
                curl_setopt($ch, $k, $v);
            }
        }
        $response = curl_exec($ch);

        $error = false;
        //看是否有报错
        $errorCode = curl_errno($ch);
        if ($errorCode) {
            $errorMessage = curl_error($ch);
            $error = array(&#39;errorCode&#39;=>$errorCode, &#39;errorMessage&#39;=>$errorMessage);
            //将报错写入日志文件里
            $logText = "$method $url: [$errorCode]$errorMessage";
            if (!empty($param)) $logText .= ",$param".json_encode($param);
            file_put_contents(&#39;/data/error.log&#39;, $logText);
        }

        curl_close($ch);

        return $response;



    }


?>

获取用户信息的自定义函数

  

通过以上三步调用接口,就可以获取到用户的微信账号信息了。

大家可以认真看看代码, 里面很多地方我都带上了注释,很容易理解。希望想学习的朋友可以认真看看。

更多微信授权登录并获取用户信息接口相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。