热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

一、首先你的微信公众号要获得相应的AppID和AppSecret,申请微信登录且通过审核后,才可开始接入流程。
  近排在做微信接口开发,所以总结一下微信授权登录并获取用户信息 这个接口的开发流程。

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

二、授权流程

1、流程说明

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

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

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

2、获取access_token时序图:

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

1、请求CODE

  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['code'];
            if (empty($code)) {
                if (empty($url)) {
                    $url = rtirm($_SERVER['QUERY_STRING'], '/');
                    //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
                    redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
                }
            }


        }

    }
?>

获取code的Controller代码

  Wxmodel.php

appId = 'wx0000000000000000';
            $this->appSecret = '00000000000000000000000000000';
            $this->token = '00000000';
        }

        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
       public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
        $redirectUrl = urlencode($redirectUrl);
        $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
        $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['code'];

这行也已经能获取得到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['code'];
            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

appId = 'wx0000000000000000';
            $this->appSecret = '00000000000000000000000000000';
            $this->token = '00000000';
        }


        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
        public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
            $redirectUrl = urlencode($redirectUrl);
            $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
            $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代码

这里附上参数说明

  请求参数说明:

  获取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['code'];
            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

appId = 'wx0000000000000000';
            $this->appSecret = '00000000000000000000000000000';
            $this->token = '00000000';
        }


        /**
         * 获取微信授权url
         * @param string 授权后跳转的URL
         * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
         *   
        */
        public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
            $redirectUrl = urlencode($redirectUrl);
            $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
            $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 = 'https://api.weixin.qq.com/sns/userinfo';
            //获取用户微信账号信息
            $userInfo = $this->callApi("$url?access_token=$accessToken&openid=$openId&lang=zh-CN");

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

            $userInfo['wx_id'] = $openId;

            return $userInfo;
        }

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

            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), 'access_token=');
                        if ($pos !==false ) {
                            $pos += strlen('access_token=');
                            $pos2 = strpos($apiUrl, '&' ,$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('Weixin:AccessToken');
            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['access_token'];
                $expire = max(1, intval($result['expires_in']) - 60);
                //将access_token缓存到redis里去
                $this->library->redisCache->set('Weixin:AccessToken', $accessToken, $expire);
            }
            return $accessToken;
        }

?>

获取用户信息的Model

  Common.php

 0) {
            $respOnse= json_decode($responseText, true);

            if ($respOnse== null) {
                $error = array('errorCode'=>-1, 'errorMessage'=>'json decode fail', 'responseText'=>$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 = 'GET', $timeout = 15, $exOptiOns= NULL) {
        //判断是否开启了curl扩展
        if (!function_exists('curl_init')) exit('please open this curl extension');

        //将请求方法变大写
        $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['HTTP_USER_AGENT'])) curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        if (isset($_SERVER['HTTP_REFERER'])) curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        switch ($method) {
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, true);
                if (!empty($param)) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($param)) ? http_build_query($param) : $param);
                }
                break;
            
            case 'GET':
            case 'DELETE':
                if ($method == 'DELETE') {
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                }
                if (!empty($param)) {
                    $url = $url.(strpos($url, '?') ? '&' : '?').(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('errorCode'=>$errorCode, 'errorMessage'=>$errorMessage);
            //将报错写入日志文件里
            $logText = "$method $url: [$errorCode]$errorMessage";
            if (!empty($param)) $logText .= ",$param".json_encode($param);
            file_put_contents('/data/error.log', $logText);
        }

        curl_close($ch);

        return $response;



    }


?>

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

  

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

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

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

推荐阅读
  • Windows 7 64位系统下Redis的安装与PHP Redis扩展配置
    本文详细介绍了在Windows 7 64位操作系统中安装Redis以及配置PHP Redis扩展的方法,包括下载、安装和基本使用步骤。适合对Redis和PHP集成感兴趣的开发人员参考。 ... [详细]
  • 本文介绍了如何使用PHP代码实现微信平台的媒体素材上传功能,详细解释了API接口的使用方法和注意事项,确保文件路径正确以避免常见的错误。 ... [详细]
  • Java项目分层架构设计与实践
    本文探讨了Java项目中应用分层的最佳实践,不仅介绍了常见的三层架构(Controller、Service、DAO),还深入分析了各层的职责划分及优化建议。通过合理的分层设计,可以提高代码的可维护性、扩展性和团队协作效率。 ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 本文将深入探讨PHP编程语言的基本概念,并解释PHP概念股的含义。通过详细解析,帮助读者理解PHP在Web开发和股票市场中的重要性。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
  • 随着Redis功能的不断增强和稳定性提升,其应用范围日益广泛,成为软件开发人员不可或缺的技能之一。本文将深入探讨Redis集群的部署与优化,包括主从备份机制、哨兵模式以及集群功能,帮助读者全面理解并掌握Redis集群的应用。 ... [详细]
  • 本文介绍了数据库体系的基础知识,涵盖关系型数据库(如MySQL)和非关系型数据库(如MongoDB)的基本操作及高级功能。通过三个阶段的学习路径——基础、优化和部署,帮助读者全面掌握数据库的使用和管理。 ... [详细]
  • Spring Boot单元测试中Redis连接失败的解决方案
    本文探讨了在Spring Boot项目中进行单元测试时遇到Redis连接问题的原因及解决方法,详细分析了配置文件加载路径不当导致的问题,并提供了有效的解决方案。 ... [详细]
  • 本文详细介绍了如何使用 PHP 接收并处理微信支付的回调结果,确保支付通知能够被正确接收和响应。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 在PHP后端开发中遇到一个难题:通过第三方类文件发送短信功能返回的JSON字符串无法解析。本文将探讨可能的原因并提供解决方案。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
author-avatar
洋洋哥2602913063
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有