zoukankan      html  css  js  c++  java
  • 微信授权登录并获取用户信息接口开发

    总结一下微信授权登录并获取用户信息 这个接口的开发流程。

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

    二、授权流程

    1、流程说明

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

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

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

    2、获取access_token时序图:

    三、开发(使用CI框架,框架其实没什么区别,整体大概都是MVC思路)

    1、请求CODE

    Weixin.php

     1 <?php
     2     class weixinController extends CI_Controller {
     3         public $userInfo;
     4         public $wxId;
     5 
     6 
     7         public function __construct(){
     8             parent::__construct();
     9 
    10             //只要用户一访问此模块,就登录授权,获取用户信息
    11             $this->userInfo = $this->getWxUserInfo();
    12         }
    13     
    14 
    15         /**
    16          * 确保当前用户是在微信中打开,并且获取用户信息
    17          *
    18          * @param string $url 获取到微信授权临时票据(code)回调页面的URL
    19          */
    20         private function getWxUserInfo($url = '') {
    21             //微信标记(自己创建的)
    22             $wxSign = $this->input->cookie('wxSign');
    23             //先看看本地cookie里是否存在微信唯一标记,
    24             //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
    25             if (!empty($wxSign)) {
    26                 //如果存在,则从Redis里取出缓存了的数据
    27                 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
    28                 if (!empty($userInfo)) {
    29                     //获取用户的openid
    30                     $this->wxId = $userInfo['openid'];
    31                     //将其存在cookie里
    32                     $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
    33                     return $userInfo;
    34                 }
    35             }
    36 
    37             //获取授权临时票据(code)
    38             $code = $_GET['code'];
    39             if (empty($code)) {
    40                 if (empty($url)) {
    41                     $url = rtirm($_SERVER['QUERY_STRING'], '/');
    42                     //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
    43                     redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
    44                 }
    45             }
    46 
    47 
    48         }
    49     }
    50 ?>

    Wxmodel.php

     1 <?php
     2     class WxModel extends ModelBase{
     3         public $appId;
     4         public $appSecret;
     5         public $token;
     6 
     7         public function __construct() {
     8             parent::__construct();
     9 
    10             //审核通过的移动应用所给的AppID和AppSecret
    11             $this->appId = 'wx0000000000000000';
    12             $this->appSecret = '00000000000000000000000000000';
    13             $this->token = '00000000';
    14         }
    15 
    16         /**
    17          * 获取微信授权url
    18          * @param string 授权后跳转的URL
    19          * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
    20          *   
    21         */
    22        public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
    23         $redirectUrl = urlencode($redirectUrl);
    24         $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
    25         $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state";
    26         return $oAuthUrl;
    27        }

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

    请求参数说明:

    响应返回值说明:

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

        //获取授权临时票据(code)
        $code = $_GET['code'];
    这行也已经能获取得到code的值了。接着进行第二步。

    2、通过code获取access_token
    Weixin.php
     1 <?php
     2     class weixinController extends CI_Controller {
     3         public $userInfo;
     4         public $wxId;
     5 
     6 
     7         public function __construct(){
     8             parent::__construct();
     9 
    10             //只要用户一访问此模块,就登录授权,获取用户信息
    11             $this->userInfo = $this->getWxUserInfo();
    12         }
    13     
    14 
    15         /**
    16          * 确保当前用户是在微信中打开,并且获取用户信息
    17          *
    18          * @param string $url 获取到微信授权临时票据(code)回调页面的URL
    19          */
    20         private function getWxUserInfo($url = '') {
    21             //微信标记(自己创建的)
    22             $wxSign = $this->input->cookie('wxSign');
    23             //先看看本地cookie里是否存在微信唯一标记,
    24             //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
    25             if (!empty($wxSign)) {
    26                 //如果存在,则从Redis里取出缓存了的数据
    27                 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
    28                 if (!empty($userInfo)) {
    29                     //获取用户的openid
    30                     $this->wxId = $userInfo['openid'];
    31                     //将其存在cookie里
    32                     $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
    33                     return $userInfo;
    34                 }
    35             }
    36 
    37             //获取授权临时票据(code)
    38             $code = $_GET['code'];
    39             if (empty($code)) {
    40                 if (empty($url)) {
    41                     $url = rtirm($_SERVER['QUERY_STRING'], '/');
    42                     //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
    43                     redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
    44                 }
    45             }
    46             /***************这里开始第二步:通过code获取access_token****************/
    47             $result = $this->model->wx->getOauthAccessToken($code);
    48 
    49             //如果发生错误
    50             if (isset($result['errcode'])) {
    51                 return array('msg'=>'授权失败,请联系客服','result'=>$result);
    52             }
    53 
    54             //到这一步就说明已经取到了access_token
    55             $this->wxId = $result['openid'];
    56             $accessToken = $result['access_token'];
    57             $openId = $result['openid'];
    58 
    59             //将openid和accesstoken存入cookie中
    60             $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7);
    61             $this->input->set_cookie('access_token', $accessToken);

    WxModel.php

     1 <?php
     2     class WxModel extends ModelBase{
     3         public $appId;
     4         public $appSecret;
     5         public $token;
     6 
     7         public function __construct() {
     8             parent::__construct();
     9 
    10             //审核通过的移动应用所给的AppID和AppSecret
    11             $this->appId = 'wx0000000000000000';
    12             $this->appSecret = '00000000000000000000000000000';
    13             $this->token = '00000000';
    14         }
    15 
    16 
    17         /**
    18          * 获取微信授权url
    19          * @param string 授权后跳转的URL
    20          * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
    21          *   
    22         */
    23         public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
    24             $redirectUrl = urlencode($redirectUrl);
    25             $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
    26             $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
    27             return $oAuthUrl;
    28         }
    29 
    30 
    31         /**
    32         * 获取access_token
    33         */
    34         public function getoAuthAccessToken($code) {
    35             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);
    36         }

    附上参数说明

        请求参数说明:

     

    响应返回值说明:

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

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

      (1)access_tokec有效且未超时;

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

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

      Weixin.php

     1 <?php
     2     class weixinController extends CI_Controller {
     3         public $userInfo;
     4         public $wxId;
     5 
     6 
     7         public function __construct(){
     8             parent::__construct();
     9 
    10             //只要用户一访问此模块,就登录授权,获取用户信息
    11             $this->userInfo = $this->getWxUserInfo();
    12         }
    13     
    14 
    15         /**
    16          * 确保当前用户是在微信中打开,并且获取用户信息
    17          *
    18          * @param string $url 获取到微信授权临时票据(code)回调页面的URL
    19          */
    20         private function getWxUserInfo($url = '') {
    21             //微信标记(自己创建的)
    22             $wxSign = $this->input->cookie('wxSign');
    23             //先看看本地cookie里是否存在微信唯一标记,
    24             //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着)
    25             if (!empty($wxSign)) {
    26                 //如果存在,则从Redis里取出缓存了的数据
    27                 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
    28                 if (!empty($userInfo)) {
    29                     //获取用户的openid
    30                     $this->wxId = $userInfo['openid'];
    31                     //将其存在cookie里
    32                     $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
    33                     return $userInfo;
    34                 }
    35             }
    36 
    37             //获取授权临时票据(code)
    38             $code = $_GET['code'];
    39             if (empty($code)) {
    40                 if (empty($url)) {
    41                     $url = rtirm($_SERVER['QUERY_STRING'], '/');
    42                     //到WxModel.php里获取到微信授权请求URL,然后redirect请求url
    43                     redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
    44                 }
    45             }
    46             /***************这里开始第二步:通过code获取access_token****************/
    47             $result = $this->model->wx->getOauthAccessToken($code);
    48 
    49             //如果发生错误
    50             if (isset($result['errcode'])) {
    51                 return array('msg'=>'授权失败,请联系客服','result'=>$result);
    52             }
    53 
    54             //到这一步就说明已经取到了access_token
    55             $this->wxId = $result['openid'];
    56             $accessToken = $result['access_token'];
    57             $openId = $result['openid'];
    58 
    59             //将openid和accesstoken存入cookie中
    60             $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7);
    61             $this->input->set_cookie('access_token', $accessToken);
    62 
    63             /*******************这里开始第三步:通过access_token调用接口,取出用户信息***********************/
    64             $this->userInfo = $this->model->wx->getUserInfo($openId, $accessToken);
    65 
    66             //自定义微信唯一标识符
    67             $wxSign =substr(md5($this->wxId.'k2a5dd'), 8, 16);
    68             //将其存到cookie里
    69             $this->input->set_cookie('wxSign', $wxSign, 60*60*24*7);
    70             //将个人信息缓存到redis里
    71             $this->library->redisCache->set("weixin:sign_{$wxSign}", $userInfo, 60*60*24*7);
    72             return $userInfo;
    73         }
    74     }
    75 ?>

    WxModel.php

      1 <?php
      2     class WxModel extends ModelBase{
      3         public $appId;
      4         public $appSecret;
      5         public $token;
      6 
      7         public function __construct() {
      8             parent::__construct();
      9 
     10             //审核通过的移动应用所给的AppID和AppSecret
     11             $this->appId = 'wx0000000000000000';
     12             $this->appSecret = '00000000000000000000000000000';
     13             $this->token = '00000000';
     14         }
     15 
     16 
     17         /**
     18          * 获取微信授权url
     19          * @param string 授权后跳转的URL
     20          * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息
     21          *   
     22         */
     23         public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
     24             $redirectUrl = urlencode($redirectUrl);
     25             $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
     26             $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
     27             return $oAuthUrl;
     28         }
     29 
     30 
     31         /**
     32         * 获取access_token
     33         */
     34         public function getoAuthAccessToken($code) {
     35             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);
     36         }
     37 
     38         /**
     39         * 获取用户信息  
     40         */
     41         public function getUserInfo($openId, $accessToken) {
     42             $url = 'https://api.weixin.qq.com/sns/userinfo';
     43             //获取用户微信账号信息
     44             $userInfo = $this->callApi("$url?access_token=$accessToken&openid=$openId&lang=zh-CN");
     45 
     46             if ($userInfo['errcode']) {
     47                 return array('msg'=>'获取用户信息失败,请联系客服', $userInfo);
     48             }
     49 
     50             $userInfo['wx_id'] = $openId;
     51 
     52             return $userInfo;
     53         }
     54 
     55         /**
     56          * 发起Api请求,并获取返回结果
     57          * @param string 请求URL
     58          * @param mixed 请求参数 (array|string)
     59          * @param string 请求类型 (GET|POST)
     60          * @return array        
     61          */
     62         public function callApi($apiUrl, $param = array(), $method = 'GET') {
     63             $result = curl_request_json($error, $apiUrl, $params, $method);
     64             //假如返回的数组有错误码,或者变量$error也有值
     65             if (!empty($result['errcode'])) {
     66                 $errorCode = $result['errcode'];
     67                 $errorMsg = $result['errmsg'];
     68             } else if ($error != false) {
     69                 $errorCode = $error['errorCode'];
     70                 $errorMsg = $error['errorMessage'];
     71             }
     72 
     73             if (isset($errorCode)) {
     74                 //将其插入日志文件
     75                 file_put_contents("/data/error.log", "callApi:url=$apiUrl,error=[$errorCode]$errorMsg");
     76 
     77                 if ($errorCode === 40001) {
     78                     //尝试更正access_token后重试
     79                     try {
     80                         $pos = strpos(strtolower($url), 'access_token=');
     81                         if ($pos !==false ) {
     82                             $pos += strlen('access_token=');
     83                             $pos2 = strpos($apiUrl, '&' ,$pos);
     84                             $accessTokened = substr($apiUrl, $pos, $pos2 === false ? null : ($pos2 - $pos));
     85                             return $this->callApi(str_replace($accessTokened, $this->_getApiToken(true), $apiUrl), $param, $method);
     86                         }
     87                     }catch (WeixinException $e) { 
     88 
     89                     }
     90                 }
     91                 //这里抛出异常,具有的就不详说了
     92                 throw new WeixinException($errorMessage, $errorCode);
     93             }
     94             return $result;
     95         }
     96 
     97         /**
     98         * 获取微信 api 的 access_token 。 不同于 OAuth 中的 access_token ,参见  http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token
     99         *
    100         * @param bool 是否强制刷新 accessToken
    101         */
    102         private function _getApiToken($forceRefresh = false) {
    103             //先查看一下redis里是否已经缓存过access_token
    104             $accessToken = $this->library->redisCache->get('Weixin:AccessToken');
    105             if($forceRefresh || empty($accessToken)) {
    106                 $result = $this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}");
    107                 $accessToken = $result['access_token'];
    108                 $expire = max(1, intval($result['expires_in']) - 60);
    109                 //将access_token缓存到redis里去
    110                 $this->library->redisCache->set('Weixin:AccessToken', $accessToken, $expire);
    111             }
    112             return $accessToken;
    113         }
    114 ?>

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

      1 <?php
      2     /**
      3      *   发起一个HTTP(S)请求,并返回json格式的响应数据
      4      *   @param array 错误信息  array($errorCode, $errorMessage)
      5      *   @param string 请求Url
      6      *   @param array 请求参数
      7      *   @param string 请求类型(GET|POST)
      8      *   @param int 超时时间
      9      *   @param array 额外配置
     10      *   
     11      *   @return array
     12      */ 
     13     public function curl_request_json(&$error, $url, $param = array(), $method = 'GET', $timeout = 10, $exOptions = null) {
     14         $error = false;
     15         $responseText = curl_request_text($error, $url, $param, $method, $timeout, $exOptions);
     16         $response = null;
     17         if ($error == false && $responseText > 0) {
     18             $response = json_decode($responseText, true);
     19 
     20             if ($response == null) {
     21                 $error = array('errorCode'=>-1, 'errorMessage'=>'json decode fail', 'responseText'=>$responseText);
     22                 //将错误信息记录日志文件里
     23                 $logText = "json decode fail : $url";
     24                 if (!empty($param)) {
     25                     $logText .= ", param=".json_encode($param);
     26                 }
     27                 $logText .= ", responseText=$responseText";
     28                 file_put_contents("/data/error.log", $logText);
     29             }
     30         }
     31         return $response;
     32     }
     33 
     34     /**
     35     *  发起一个HTTP(S)请求,并返回响应文本
     36     *   @param array 错误信息  array($errorCode, $errorMessage)
     37     *   @param string 请求Url
     38     *   @param array 请求参数
     39     *   @param string 请求类型(GET|POST)
     40     *   @param int 超时时间
     41     *   @param array 额外配置
     42     *   
     43     *   @return string
     44     */
     45     public function curl_request_text(&$error, $url, $param = array(), $method = 'GET', $timeout = 15, $exOptions = NULL) {
     46         //判断是否开启了curl扩展
     47         if (!function_exists('curl_init')) exit('please open this curl extension');
     48 
     49         //将请求方法变大写
     50         $method = strtoupper($method);
     51 
     52         $ch = curl_init();
     53         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
     54         curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
     55         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     56         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
     57         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
     58         curl_setopt($ch, CURLOPT_HEADER, false);
     59         if (isset($_SERVER['HTTP_USER_AGENT'])) curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
     60         if (isset($_SERVER['HTTP_REFERER'])) curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']);
     61         curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
     62         switch ($method) {
     63             case 'POST':
     64                 curl_setopt($ch, CURLOPT_POST, true);
     65                 if (!empty($param)) {
     66                     curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($param)) ? http_build_query($param) : $param);
     67                 }
     68                 break;
     69             
     70             case 'GET':
     71             case 'DELETE':
     72                 if ($method == 'DELETE') {
     73                     curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
     74                 }
     75                 if (!empty($param)) {
     76                     $url = $url.(strpos($url, '?') ? '&' : '?').(is_array($param) ? http_build_query($param) : $param);
     77                 }
     78                 break;
     79         }
     80         curl_setopt($ch, CURLINFO_HEADER_OUT, true);
     81         curl_setopt($ch, CURLOPT_URL, $url);
     82         //设置额外配置
     83         if (!empty($exOptions)) {
     84             foreach ($exOptions as $k => $v) {
     85                 curl_setopt($ch, $k, $v);
     86             }
     87         }
     88         $response = curl_exec($ch);
     89 
     90         $error = false;
     91         //看是否有报错
     92         $errorCode = curl_errno($ch);
     93         if ($errorCode) {
     94             $errorMessage = curl_error($ch);
     95             $error = array('errorCode'=>$errorCode, 'errorMessage'=>$errorMessage);
     96             //将报错写入日志文件里
     97             $logText = "$method $url: [$errorCode]$errorMessage";
     98             if (!empty($param)) $logText .= ",$param".json_encode($param);
     99             file_put_contents('/data/error.log', $logText);
    100         }
    101 
    102         curl_close($ch);
    103 
    104         return $response;
    105     }
    106 ?>

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

  • 相关阅读:
    hdu6761 Mininum Index // lyndon分解 + duval贪心 + 秦九韶算法
    hdu6762 Mow // 半平面交 模拟 双端队列
    数据库增删改查操作
    移动端自动化概念
    范围查询和模糊查询
    软件测试技能要求总结
    继承
    luogu_P2024 [NOI2001]食物链
    luogu_P4092 [HEOI2016/TJOI2016]树
    luogu_P2887 [USACO07NOV]防晒霜Sunscreen
  • 原文地址:https://www.cnblogs.com/lonmyblog/p/7281786.html
Copyright © 2011-2022 走看看