WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

高洛峰
풀어 주다: 2017-03-01 09:19:18
원래의
10892명이 탐색했습니다.

저는 최근 WeChat 인터페이스를 개발하고 있으므로 WeChat 로그인을 승인하고 사용자 정보를 얻기 위한 이 인터페이스의 개발 프로세스를 요약하겠습니다.

1. 먼저, WeChat 공개 계정은 해당 AppID와 AppSecret을 받아야 합니다. WeChat 로그인을 신청하고 검토를 통과한 후에만 액세스 프로세스를 시작할 수 있습니다.

2. 승인 프로세스

1. 프로세스 설명

(1) 제3자가 WeChat 승인 로그인 요청을 시작한 후 WeChat 사용자가 승인을 허용합니다. 타사 애플리케이션 중 WeChat은 애플리케이션을 실행하거나 타사 웹사이트로 리디렉션하고 인증 임시 티켓 코드 매개변수를 가져옵니다.

(2). , 등을 통해 API를 통해 access_token;

(3)을 통해 사용자의 기본 데이터 리소스를 얻거나 사용자가 기본을 구현하도록 돕습니다. 운영.

2. access_token 시퀀스 다이어그램을 얻습니다:

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

3. 개발(저는 CI 프레임워크를 사용합니다. 사실 모든 프레임워크는 동일합니다. MVC 모드가 됩니다)

1. 코드 요청

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)));
                }
            }


        }

    }
?>
로그인 후 복사

컨트롤러 코드 가져오기

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代码
로그인 후 복사

코드의 모델 코드 가져오기

여기 첨부된 내용은 요청 매개변수 설명과 반환 값 설명입니다

요청 매개변수 설명:

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

응답 반환값 설명:

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

요청이 성공하면 요청 매개변수의 Redirect_uri 값으로 리디렉션됩니다. 실제로 weixin.php의 $this->userInfo = $this->getWxUserInfo(); 라인으로 반환됩니다. 그런 다음 getWxUserInfo()를 다시 입력합니다. 이 때

            //获取授权临时票据(code)
            $code = $_GET[&#39;code&#39;];
로그인 후 복사

줄에서도 코드 값을 가져올 수 있습니다. 그런 다음 두 번째 단계로 진행합니다.

2. 코드를 통해 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의 모델 코드 가져오기

여기에 매개변수 설명이 첨부되어 있습니다

매개변수 설명 요청:

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

응답 반환 값 설명:

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

오류가 반환되면 다음과 같습니다.

WeChat 인증 로그인 및 사용자 정보 획득 인터페이스

3. access_token을 통해 인터페이스 호출(사용자 정보 획득)
access_token을 얻은 후 다음 전제 조건으로 인터페이스 호출을 수행합니다.

(1) access_tokec이 유효하고 시간 초과되지 않았습니다.

(2) WeChat 사용자가 타사 애플리케이션 계정의 해당 인터페이스 범위(범위)를 승인했습니다.

 

다음은 사용자 정보를 얻는 코드

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
로그인 후 복사

사용자 정보를 얻는 컨트롤러

 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;
        }

?>
로그인 후 복사

사용자 정보를 가져오는 모델

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;



    }


?>
로그인 후 복사

사용자 정보를 가져오는 사용자 정의 기능

 

위의 세 단계에 걸쳐 인터페이스를 호출하면 사용자의 위챗 계정 정보를 얻을 수 있습니다.

코드를 자세히 보시면 이해하기 쉽도록 여러 곳에 주석을 달았습니다. 배우고 싶은 친구들이 자세히 살펴 볼 수 있기를 바랍니다.

WeChat 인증 로그인 및 사용자 정보 인터페이스 접근과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿