获取微信用户信息_微信公众号调微信接口获取用户信息,对于微信用户有没有条件 - CSDN
精华内容
参与话题
  • asp获取微信公众号网页授权和用户信息(code、access_token、openid等) 01-asp获取微信公众号网页授权和用户信息演示 02-asp获取远程网页内容 03-官方文档概要 04-获取用户同意授权 05-拿到code后获取返回信息 06-...
  • 近排在做微信接口开发,所以总结一下微信授权登录并获取用户信息 这个接口的开发流程。 一、首先你的微信公众号要获得相应的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

    复制代码
     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 
    51 
    52 
    53 
    54 
    55 
    56 
    57 
    58 
    59 
    60 
    61     }
    62 ?>
    复制代码

       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()方法,此时

    1
    2
    //获取授权临时票据(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 
    76 
    77 
    78 
    79 
    80 
    81 
    82 
    83 
    84 
    85 
    86     }
    87 ?>
    复制代码

      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 
    115 
    116 
    117 
    118 
    119 
    120 
    121 ?>
    复制代码

      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 
    107 
    108     }
    109 
    110 
    111 
    112 
    113 
    114 
    115 
    116 
    117 
    118 
    119 
    120 
    121 
    122 ?>
    复制代码

      

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

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

      

     

      如果此博文有哪里讲得让人难以理解的,欢迎留言交流,如文章有解释出的地方,欢迎指出。

      

      如果您觉得能在此博文学到新知识,请在下方为我顶一个,如文章有解释错的地方,欢迎指出。

       互相学习,共同进步!

    展开全文
  • 最近,对微信公众号有点兴趣,就自己研究了研究里面的一些内容,发现还挺... 我想,做微信公众号开发的,对于想获取关注了公众号的用户信息,或者说是当前与后台服务器进行交互的当前用户信息,这个功能是很重要...

        最近,对微信公众号有点兴趣,就自己研究了研究里面的一些内容,发现还挺有意思的,而且通过微信公众号可以调用一些比较有意思的接口,就比如百度开发服务平台 点击进入 里面的很有接口,就比较常见的翻译,语音识别,地理位置等等,都挺好的。好了,不多说,进入正题好了。

        我想,做微信公众号开发的,对于想获取关注了公众号的用户信息,或者说是当前与后台服务器进行交互的当前用户信息,这个功能是很重要的吧。因为,通过这个,可以直接获取到当前的用户信息,而不需要,每次都是进行自己输入信息,这个只会让用户感觉到很不适。。。所以,为了解决这个需求,那咱们来研究研究,如何获取微信的个人信息~!

    大家可以关注我的微信公众号:Java菜鸟进阶之路

     (一)思路

    我们来研究一下,要想获取到个人信息,是如何一个流程呢?

    路线图:

    上面,画了一个简单的一个流程图,我想,看着这个应该觉得不难吧。是的,确实思路很简单,但是,,里面的坑也不少。接下来,我对两种情况都进行讲解。

    (二)情况一:通过用户与服务器进行消息交互,来获取用户信息

    思路:针对这种情况的话,比较简单,因为,我们在做用户与服务器进行消息交互的时候,我们可以知道,用户发送的内容是以XML的形式进行发送的,然后服务器,首先接受到XML,然后再把XML转为Map对象,再从Map对象中获取对应的内容即可。那么,发送的XML的字段是个怎么样呢?

    字段信息:

    ToUserName:发送给谁的ID
    FromUserName:发消息方的ID(其实也就是用户的OpenId)
    CreateTime:消息发送时间,时间戳
    MsgType:消息类似,有文本,图片,音频,视频,事件推送等
    Content:发送的内容

    通过这个,我想大家,再结合上面给的流程图,是不是发现了什么呢?是的,这个OpenId,我们已经获取了呀,那是不是可以直接获取到用户信息了呢?。。。。emmmmmm,这样说吧。差不多是可以的,那具体是怎么做呢?紧接着往下看,仔细看我其中的注释

    步骤:

    1:解析发送过来的XML信息格式,将其转为Map格式

    /**
         * XML格式转为map格式
         * @param request
         * @return
         */
        public static Map<String , String> xmlToMap(HttpServletRequest request){
            Map<String ,String> map = new HashMap<String , String>();
            try {
                InputStream inputStream =null;
                inputStream = request.getInputStream();
                SAXReader reader = new SAXReader();
                Document doc = reader.read(inputStream);
                Element rootElement = doc.getRootElement();
                List<Element> elements = rootElement.elements();
                for (Element el:elements) {
                    map.put(el.getName() , el.getText());
                }
                inputStream.close();
                return map ;
            } catch (Exception e) {
                e.printStackTrace();
                return null ;
            }
        }

    备注:记得导入相应的包哦。。比如dom4j还有xsreader。。

    2:获取用户的个人信息

    package com.hnu.scw.utils;
    
    import com.hnu.scw.model.AccessToken;
    import net.sf.json.JSONObject;
    
    /**
     * @author scw
     * @create 2018-01-18 16:42
     * @desc 用于获取微信用户的信息
     **/
    public class WeiXinUserInfoUtils {
        private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
        /**
         * 获取微信用户账号的相关信息
         * @param opendID  用户的openId,这个通过当用户进行了消息交互的时候,才有
         * @return
         */
        public static String getUserInfo(String opendID){
            AccessToken accessToken = WeiXinUtils.getAccessToken();
            //获取access_token
            String token = accessToken.getToken();
            String url = GET_USERINFO_URL.replace("ACCESS_TOKEN" , token);
            url = url.replace("OPENID" ,opendID);
            JSONObject jsonObject = WeiXinUtils.doGetStr(url);
            return jsonObject.toString();
        }
    }

    备注:传入的参数就是咱们之前说过的,FromUserName的值,这个应该不用多解释吧。因为,对于传入的XML,我们已经存入了Map中,那么直接从Map取出对应的字段信息就可以了,

    String fromUserName = map.get("FromUserName");

    3:通过上面,我们就得到了具体的用户信息的Json格式了,当然,我上面的方法将Json内容转为了String,我这里只是用于查看是否获取到信息了而已,所以,你们就根据各自的需求进行处理就可以了,该解析的就解析即可。。

    总结:

    上面的这种方法是不是很简单,这个没什么难的,而且这个根据微信公众号的开发手册也可以分析出来。

    缺点:我们发现了,这种方法,只有当用户进行了消息交互,才会有FromUserName(这时候可以等价看成是OpenId),那么我们在实际开发中,肯定遇到了一种情况,就是用户没有进行消息交互,直接点击一个菜单按钮,然后就把用户信息自动显示到了一个页面中,那这样是怎么做,方法是一样吗?不多说,继续看下面~~~~~~~~~

    (三)情况二:通过点击按钮,来直接获取到用户信息

    思路:首先,点击菜单按钮,要先到网页授权的接口去请求(主要是获取Code,这是必须要的一个参数),然后再重定向到我们自己菜单按钮实际想去的URL,然后再获取OpenId,再通过OpenId,获取用户信息。。哇塞,咦,思路挺简单的嘛。。那么,我们开始工作。。

    步骤:

    1:创建菜单

    对于这个自定义菜单的话,不是主要介绍的了,这个如果做过微信公众号开发的,应该都明白吧。所以,我这就贴一点关键代码:

    ViewButton viewButton = new ViewButton();
            viewButton.setName("view菜单");
            viewButton.setType("view");
            //viewButton.setUrl("http://myjava.ngrok.xiaomiqiu.cn/tomainpage");
            viewButton.setUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXXXX&redirect_uri=http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect");

    备注:大家,请注意,这个view菜单的URL,和我们平常的跳转的区别再哪里。。

     

    分析:

    知识点1:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXX

    这个就是网页授权的接口地址,其中的appid就是我们自己微信公众号申请的时候,给我们的唯一值,这个大家去微信公众号查看即可。

     

    知识点2:

    redirect_uri=http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect");

    这个就是我们实际想要点击按钮,跳转到的页面,这个就和咱们平常的跳转是一样的,所以一定要记住,要先去授权页面,再重定向回去(主要是为了获取code参数)。

     

    2:配置微信公众号的网页授权域名

    备注:这个是在自己微信公众号的开发管理模块里面的,而且,我这里用的是测试号进行的(当然,如果有企业号这更加好呀。界面也是一样)

    注意点:对添加的回调页面域名:首先,不能加入http://这个,对于平常的链接,我想都有这个,这个是请求协议,但这里千万不能加入;另外,只需要写总的域名地址,不需要精确到最内层。打个比方:

    一般的:

    http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo

    这里就配置就只需要:(其实就是配置我们的服务器域名即可)

    myjava.ngrok.xiaomiqiu.cn

    3:编写,相应的处理内容(关键代码,请仔细看)

    备注:我用的是SSH(SpringMVC+Spring+Hibernate)框架来进行开发的,当然,用Servlet也可以,用SSM(SpringMVC+Spring+Mybatis)或者用SSH(Struts+Spring+Hibernate)都可以,这个根据自己的需求即可相应的改变呢!!(另外,这个几个框架,我其他的文章都有很详细的介绍了,所以自己看看相应配置即可)

    Controller层代码:

    package com.hnu.scw.controller;
    import com.hnu.scw.bean.WeiXinUser;
    import com.hnu.scw.service.WeiXinUserInfoService;
    import com.hnu.scw.utils.WeiXinUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * @author scw
     * @create 2018-01-18 17:47
     * @desc 获取微信用户的所有信息,这个主要是为了不要用户自己填写个人信息
     **/
    @Controller
    public class WeiXinUserInfoController {
    
        @Autowired
        private WeiXinUserInfoService userService;
    
        /**
         * 进行网页授权,便于获取到用户的绑定的内容
         * @param request
         * @param session
         * @param map
         * @return
         */
        @RequestMapping("/tologin/userinfo")
        public String check(HttpServletRequest request , HttpSession session, Map<String, Object> map) {
            //首先判断一下session中,是否有保存着的当前用户的信息,有的话,就不需要进行重复请求信息
            WeiXinUser  weiXinUser = null ;
            if(session.getAttribute("currentUser") != null){
                weiXinUser = (WeiXinUser) session.getAttribute("currentUser");
            }else {
                /**
                 * 进行获取openId,必须的一个参数,这个是当进行了授权页面的时候,再重定向了我们自己的一个页面的时候,
                 * 会在request页面中,新增这个字段信息,要结合这个ProjectConst.Get_WEIXINPAGE_Code这个常量思考
                 */
                String code = request.getParameter("code");
                try {
                    //得到当前用户的信息(具体信息就看weixinUser这个javabean)
                    weiXinUser = getTheCode(session, code);
                    //将获取到的用户信息,放入到session中
                    session.setAttribute("currentUser", weiXinUser);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            map.put("weiXinUser", weiXinUser);
            return "hello";
        }
    
        /**
         * 获取用户的openId
         * @param session
         * @param code
         * @return 返回封装的微信用户的对象
         */
        private WeiXinUser getTheCode(HttpSession session, String code) {
            Map<String , String>  authInfo = new HashMap<>();
            String openId = "";
            if (code != null)
            {
                // 调用根据用户的code得到需要的授权信息
                authInfo= userService.getAuthInfo(code);
               //获取到openId
                openId = authInfo.get("Openid");
            }
            // 获取基础刷新的接口访问凭证(目前还没明白为什么用authInfo.get("AccessToken");这里面的access_token就不行)
            String accessToken = WeiXinUtils.getAccessToken().getToken();
            //获取到微信用户的信息
            WeiXinUser userinfo = userService.getUserInfo(accessToken ,openId);
    
            return userinfo;
        }
    }

    Service层接口:

    package com.hnu.scw.service;
    import com.hnu.scw.bean.WeiXinUser;
    import java.util.Map;
    /**
     * 用于进行微信用户个人信息的操作接口
     */
    public interface WeiXinUserInfoService {
         /**
          * 获取到微信个人用户的信息
          * @param accessToken
          * @param openId
          * @return
          */
         WeiXinUser getUserInfo(String accessToken, String openId);
    
         /**
          *用于获取网页授权后的信息字段,其中主要是获取openId
          * @param code  授权码
          * @return
          */
         Map<String , String > getAuthInfo(String code);
    
         /**
          * 进行网页授权的认证
          * @param code 授权码
          * @return
          */
         Map<String,String> oauth2GetOpenid(String code);
    }
    

    Service层实现:

     

    package com.hnu.scw.service.imp;
    import com.hnu.scw.bean.WeiXinUser;
    import com.hnu.scw.projectconst.ProjectConst;
    import com.hnu.scw.service.WeiXinUserInfoService;
    import com.hnu.scw.utils.WeiXinUtils;
    import net.sf.json.JSONObject;
    import org.springframework.stereotype.Service;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * @author scw
     * @create 2018-01-18 17:51
     * @desc 用于获取微信用户的信息
     **/
    @Service
    public class WeiXinUserInfoImlp implements WeiXinUserInfoService {
        /**
         * 获取微信用户的信息
         * @param accessToken
         * @param openId
         * @return
         */
        @Override
        public WeiXinUser getUserInfo(String accessToken, String openId) {
            WeiXinUser weixinUserInfo = null;
            // 拼接获取用户信息接口的请求地址
            String requestUrl = ProjectConst.GET_WEIXIN_USER_URL.replace("ACCESS_TOKEN", accessToken).replace(
                    "OPENID", openId);
            // 获取用户信息(返回的是Json格式内容)
            JSONObject jsonObject = WeiXinUtils.doGetStr(requestUrl);
    
            if (null != jsonObject) {
                try {
                    //封装获取到的用户信息
                    weixinUserInfo = new WeiXinUser();
                    // 用户的标识
                    weixinUserInfo.setOpenId(jsonObject.getString("openid"));
                    // 昵称
                    weixinUserInfo.setNickname(jsonObject.getString("nickname"));
                    // 用户的性别(1是男性,2是女性,0是未知)
                    weixinUserInfo.setSex(jsonObject.getInt("sex"));
                    // 用户所在国家
                    weixinUserInfo.setCountry(jsonObject.getString("country"));
                    // 用户所在省份
                    weixinUserInfo.setProvince(jsonObject.getString("province"));
                    // 用户所在城市
                    weixinUserInfo.setCity(jsonObject.getString("city"));
                    // 用户头像
                    weixinUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                } catch (Exception e) {
                    if (0 == weixinUserInfo.getSubscribe()) {
                        System.out.println("用户并没有关注本公众号");
                    } else {
                        int errorCode = jsonObject.getInt("errcode");
                        String errorMsg = jsonObject.getString("errmsg");
                        System.out.println("由于"+errorCode +"错误码;错误信息为:"+errorMsg+";导致获取用户信息失败");
                    }
                }
            }
            return weixinUserInfo;
        }
    
        /**
         * 进行用户授权,获取到需要的授权字段,比如openId
         * @param code 识别得到用户id必须的一个值
         * 得到网页授权凭证和用户id
         * @return
         */
        @Override
        public Map<String, String> oauth2GetOpenid(String code) {
            //自己的配置appid(公众号进行查阅)
            String appid = ProjectConst.PROJECT_APPID;
            //自己的配置APPSECRET;(公众号进行查阅)
            String appsecret = ProjectConst.PROJECT_APPSECRET;
            //拼接用户授权接口信息
            String requestUrl = ProjectConst.GET_WEBAUTH_URL.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);
            //存储获取到的授权字段信息
            Map<String, String> result = new HashMap<String, String>();
            try {
                JSONObject OpenidJSONO = WeiXinUtils.doGetStr(requestUrl);
                //OpenidJSONO可以得到的内容:access_token expires_in  refresh_token openid scope
                String Openid = String.valueOf(OpenidJSONO.get("openid"));
                String AccessToken = String.valueOf(OpenidJSONO.get("access_token"));
                //用户保存的作用域
                String Scope = String.valueOf(OpenidJSONO.get("scope"));
                String refresh_token = String.valueOf(OpenidJSONO.get("refresh_token"));
                result.put("Openid", Openid);
                result.put("AccessToken", AccessToken);
                result.put("scope", Scope);
                result.put("refresh_token", refresh_token);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 获取到微信用户的唯一的OpendID
         * @param code  这是要获取OpendId的必须的一个参数
         * @return
         */
        @Override
        public Map<String , String> getAuthInfo(String code) {
            //进行授权验证,获取到OpenID字段等信息
            Map<String, String> result = oauth2GetOpenid(code);
            // 从这里可以得到用户openid
            String openId = result.get("Openid");
    
            return result;
        }
    }

    4:GET请求接口的代码:

    package com.hnu.scw.utils;
    import com.hnu.scw.menu.BaseButton;
    import com.hnu.scw.menu.ClickButton;
    import com.hnu.scw.menu.CustomeMenu;
    import com.hnu.scw.menu.ViewButton;
    import com.hnu.scw.model.AccessToken;
    import net.sf.json.JSONObject;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    
    /**
     * @author scw
     * @create 2018-01-17 14:13
     * @desc 用户获取access_token,众号调用各接口时都需使用access_token
     **/
    public class WeiXinUtils {
        /**
         * Get请求,方便到一个url接口来获取结果
         * @param url
         * @return
         */
        public static JSONObject doGetStr(String url){
            DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            JSONObject jsonObject = null;
            try{
                HttpResponse response = defaultHttpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                if(entity != null){
                    String result = EntityUtils.toString(entity, "UTF-8");
                    jsonObject = JSONObject.fromObject(result);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return jsonObject;
        }

    5:获取Access_Token代码:(这个就是在4中的类中的方法)

    /**
         * 获取access_token
         * @return
         */
        public static AccessToken getAccessToken(){
            AccessToken accessToken = new AccessToken();
            String url = ACCESS_TOKEN_URL.replace("APPID" ,APPID).replace("APPSECRET",APPSECRET);
            JSONObject jsonObject = doGetStr(url);
            if(jsonObject !=null){
                accessToken.setToken(jsonObject.getString("access_token"));
                accessToken.setExpireIn(jsonObject.getInt("expires_in"));
            }
            return accessToken;
        }

    6:Access_Token的实体类

    package com.hnu.scw.model;
    /**
     * @author scw
     * @create 2018-01-17 14:35
     * @desc 封装AccessToken的实体
     **/
    public class AccessToken {
        private String token;
        private int expireIn;
    
        public String getToken() {
            return token;
        }
        public void setToken(String token) {
            this.token = token;
        }
        public int getExpireIn() {
            return expireIn;
        }
        public void setExpireIn(int expireIn) {
            this.expireIn = expireIn;
        }
    }

    7:用户信息的实体类

    package com.hnu.scw.bean;
    /**
     * @author scw
     * @create 2018-01-18 17:11
     * @desc 对于微信用户本身存在的信息的一个javabean,不需要在数据库中进行处理
     **/
    public class WeiXinUser {
        // 用户的标识
        private String openId;
        // 关注状态(1是关注,0是未关注),未关注时获取不到其余信息
        private int subscribe;
        // 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
        private String subscribeTime;
        // 昵称
        private String nickname;
        // 用户的性别(1是男性,2是女性,0是未知)
        private int sex;
        // 用户所在国家
        private String country;
        // 用户所在省份
        private String province;
        // 用户所在城市
        private String city;
        // 用户的语言,简体中文为zh_CN
        private String language;
        // 用户头像
        private String headImgUrl;
        public String getOpenId() {
            return openId;
        }
        public void setOpenId(String openId) {
            this.openId = openId;
        }
        public int getSubscribe() {
            return subscribe;
        }
        public void setSubscribe(int subscribe) {
            this.subscribe = subscribe;
        }
        public String getSubscribeTime() {
            return subscribeTime;
        }
        public void setSubscribeTime(String subscribeTime) {
            this.subscribeTime = subscribeTime;
        }
        public String getNickname() {
            return nickname;
        }
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
        public int getSex() {
            return sex;
        }
        public void setSex(int sex) {
            this.sex = sex;
        }
        public String getCountry() {
            return country;
        }
        public void setCountry(String country) {
            this.country = country;
        }
        public String getProvince() {
            return province;
        }
        public void setProvince(String province) {
            this.province = province;
        }
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
        public String getLanguage() {
            return language;
        }
        public void setLanguage(String language) {
            this.language = language;
        }
        public String getHeadImgUrl() {
            return headImgUrl;
        }
        public void setHeadImgUrl(String headImgUrl) {
            this.headImgUrl = headImgUrl;
        }
    }

    8:一些静态常量的接口地址:

    package com.hnu.scw.projectconst;
    
    /**
     * @author scw
     * @create 2018-01-18 15:31
     * @desc 项目相关的静态量
     **/
    public class ProjectConst {
        /**
         * 用于获取当前与微信公众号交互的用户信息的接口(一般是用第一个接口地址)
         */
        public static final String GET_WEIXIN_USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";
        public final static String GetPageUsersUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
        /**
         * 用于进行网页授权验证的接口URL,通过这个才可以得到opendID等字段信息
         */
        public final static String GET_WEBAUTH_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    
        /**
         * 用于进行当点击按钮的时候,能够在网页授权之后获取到code,再跳转到自己设定的一个URL路径上的接口,这个主要是为了获取之后于
         * 获取openId的接口相结合
         * 注意:参数:toselfURL  表示的是当授权成功后,跳转到的自己设定的页面,所以这个要根据自己的需要进行修改
         */
        public final static String Get_WEIXINPAGE_Code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=toselfURL&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
        /**
         * 获取access_token的URL
         */
        private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    
    }

    9:大功告成。。。。哇塞,完美解决。。

    总结:

    这种方式,相对于上面的话,好处就在于,不需要进行消息交互就可以获取到用户的信息,这样其实更符合我们的业务需求,相对于更加好。但是,第一种情况也是有实用价值的,所以,我们要客观的进行评价和使用~~~~当然,这里面还有很多的可以优化的地方,就是,比如获取Access_Token,我们一般都是弄到本地,因为微信公众号一天请求的次数有限制(2000),所以这可以进行优化哦。。。。其他的根据需求来就可以啦!!!!!!!!

         好了,这个就介绍这个多了,都是经过本人亲自测试通过后的代码,所以,大家可以放心的使用,有问题的话,可以进行留言交流哦。。。

    Github仓库地址:

    https:https://github.com/qq496616246/WeChatCode.git

    git:git@github.com:qq496616246/WeChatCode.git

    彩蛋:

    如果你想利用闲暇零散的学习技术,那么不妨关注我的公众号阅读你想要的文章哦!

    公众号搜索:Java菜鸟进阶之路

    展开全文
  • 微信公众号网页获取用户信息

    千次阅读 2019-06-04 14:21:43
    微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 效果图 html 代码: <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, ...

    微信小程序开发交流qq群   173683895

       承接微信小程序开发。扫码加微信。

    效果图

    html 代码:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
    		<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.js"></script>
    	</head>
    	<body>
    		<script type="text/javascript">
    			$(document).ready(function() {
    				var url = "http://weixin.njkeren.cn/open/login.php";
    				$.post(url, {}, function(msg) {
    					 window.location.href=msg;
    				})
    			});
    		</script>
    	</body>
    
    </html>

    login.php 代码:

    <?php
    
    	header("Content-Type:text/html;charset=utf8"); 
    	header("Access-Control-Allow-Origin: *"); //解决跨域
    	header('Access-Control-Allow-Methods:POST');// 响应类型  
    
        $appid = "wxec203d9218b4892a";
        $appsecret = "cfe989c3cf5d89767f257953b9e0eec0";
    	
    	$redirect_uri = urlencode ( 'http://weixin.njkeren.cn/open/getUserInfo.php');
    	
    	//第一步:取得code
    	$codeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
    	
    	function getJson($url){
    		$ch = curl_init();
    		curl_setopt($ch, CURLOPT_URL, $url);
    		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
    		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
    		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    		$output = curl_exec($ch);
    		curl_close($ch);
    		return json_decode($output, true);
    	}
    	 print_r($codeUrl);
    ?>   
    

     

    getUserInfo.php 代码:

    <?php
    	//header("Content-Type:text/html;charset=utf8"); 
    	//header("Access-Control-Allow-Origin: *"); //解决跨域
    	//header('Access-Control-Allow-Methods:POST');// 响应类型  
        
        $appid = "wxec203d9218b4892a";
        $appsecret = "cfe989c3cf5d89767f257953b9e0eec0";
    	
    	$code = $_GET["code"];
    	//第一步:取得openid
    	$oauth2Url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";
    	$oauth2 = getJson($oauth2Url);
    	
    	//第二步:根据全局access_token和openid查询用户信息  
    	$access_token = $oauth2["access_token"];  
    	$openid = $oauth2['openid'];  
    	//print_r($oauth2);
    	$get_user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
    	$userinfo = getJson($get_user_info_url);
    	 
    	//打印用户信息
    	echo urldecode(json_encode($userinfo));
    	 
    	function getJson($url){
    		$ch = curl_init();
    		curl_setopt($ch, CURLOPT_URL, $url);
    		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
    		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
    		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    		$output = curl_exec($ch);
    		curl_close($ch);
    		return json_decode($output, true);
    	}
    ?>
    

    正确时返回的JSON数据包如下:

    {   
        "openid":" OPENID",
        " nickname": NICKNAME,
        "sex":"1",
        "province":"PROVINCE"
        "city":"CITY",
        "country":"COUNTRY",
        "headimgurl":       "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
        "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
        "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
    }
    
    参数 描述
    openid 用户的唯一标识
    nickname 用户昵称
    sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
    province 用户个人资料填写的省份
    city 普通用户个人资料填写的城市
    country 国家,如中国为CN
    headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
    privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
    unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
    展开全文
  • 现在,我们要实现一个微信内网页,通过微信访问网页时,网页会展示微信用户的个人信息。因为涉及到用户的个人信息,所以需要有用户授权才可以。当用户授权后,我们的网页服务器(开发者服务器)会...

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

    一丶概述

    • 微信网页授权

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

    现在,我们要实现一个微信内网页,通过微信访问网页时,网页会展示微信用户的个人信息。因为涉及到用户的个人信息,所以需要有用户授权才可以。当用户授权后,我们的网页服务器(开发者服务器)会拿到用户的“授权书”(code),我们用这个code向微信服务器领取访问令牌(accecc_token)和用户的身份号码(openid),然后凭借access_token和openid向微信服务器提取用户的个人信息。

    1. 第一步:用户同意授权,获取code
    2. 第二步:通过code换取网页授权access_token
    3. 第三步:拉取用户信息(需scope为 snsapi_userinfo)

    那么,如何拿到用户的授权code呢?

    授权是由微信发起让用户进行确认,在这个过程中是微信在与用户进行交互,所以用户应该先访问微信的内容,用户确认后再由微信将用户导向到我们的网页链接地址,并携带上code参数。我们把这个过程叫做网页回调,类似于我们在程序编写时用到的回调函数,都是回调的思想。

    • 关于网页授权回调域名的说明 

    1、在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;关于网页授权回调域名的说明

    2、授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

    3、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可。

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

    在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    尤其注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问

    参考链接(请在微信客户端中打开此链接体验):
    scope为snsapi_base
    https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
    scope为snsapi_userinfo
    https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirec

    尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。

    参数说明

    参数 是否必须 说明
    appid 公众号的唯一标识
    redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
    response_type 返回类型,请填写code
    scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
    state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
    #wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

     下图为scope等于snsapi_userinfo时的授权页面:

    用户同意授权后

    如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。

    code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。 

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

    首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

    尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。

    请求方法

    获取code后,请求以下链接获取access_token:  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

    参数说明

    参数 是否必须 说明
    appid 公众号的唯一标识
    secret 公众号的appsecret
    code 填写第一步获取的code参数
    grant_type 填写为authorization_code

    返回说明

    正确时返回的JSON数据包如下:

    { "access_token":"ACCESS_TOKEN",
    "expires_in":7200,
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID",
    "scope":"SCOPE" }
    参数 描述
    access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
    expires_in access_token接口调用凭证超时时间,单位(秒)
    refresh_token 用户刷新access_token
    openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
    scope 用户授权的作用域,使用逗号(,)分隔

     

    错误时微信会返回JSON数据包如下(示例为Code无效错误):

    {"errcode":40029,"errmsg":"invalid code"}

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

    如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

    请求方法

    http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

    参数说明

    参数 描述
    access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
    openid 用户的唯一标识
    lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

    返回说明

    正确时返回的JSON数据包如下:

    {    "openid":" OPENID",
    " nickname": NICKNAME,
    "sex":"1",
    "province":"PROVINCE"
    "city":"CITY",
    "country":"COUNTRY",
    "headimgurl":    "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
    "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
    "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
    }
    参数 描述
    openid 用户的唯一标识
    nickname 用户昵称
    sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
    province 用户个人资料填写的省份
    city 普通用户个人资料填写的城市
    country 国家,如中国为CN
    headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
    privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
    unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

    错误时微信会返回JSON数据包如下(示例为openid无效):

    {"errcode":40003,"errmsg":" invalid openid "}

     二丶代码实现

    • 思路分析
    • 首选在我们的flask程序中需要定义一个视图函数路由规则为/wechat8007/index,定义微信服务器重定向网址redirect_uri为服务器域名+/wechat8007/index(例如http://www.xxxx.com/wechat8007/index),通过访问微信提供的引导页面,让用户同意授权,然后重定向到我们定义的网址,此时微信服务器就会给我们的服务一个code,我们的服务器再通过code向微信服务器换取网页授权access_token(存取令牌),如果网页授权作用域为snsapi_userinfo,则此时可以通过access_token和openid拉取用户信息了。
    • step1 同意授权,这一块不需要代码实现,只需要提供授权链接即可
    • step2 定义视图函数,当用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE ,在flask程序中定义一个是视图函数接口index,让用户同意授权后,去访问的视图
    • 上一篇博客定义的wechat视图,是由微信服务器访问,现在定义的index视图为用户访问的
    @app.route("/wechat8007/index")
    def index():
        """让用户通过微信访问的网页页面视图"""
    • step3  刚开始还没拉去用户资料时,可直接返回一个模板
    return render_template("index.html")
    • step4 从微信服务器中获取用户的资料数据,将用户的资料数据填充到index.html模板中
    • 1.获取code参数
    code = request.args.get("code")
    • 2.当code不存在时,返回字符串
    if not code:
        return u"缺失code参数"
    url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" %(WECHAT_APPID,WECHAT_APPSECRET,code)
    
    response = urllib2.urlopen(url)
    
    # 获取响应体数据,微信返回的json数据
    json_str = response.read()
    resp_dict = json.loads(json_str)
    • 4.提取access_token,首先对获取到的响应体数据进行判断,如果不存在,直接返回提示字符串,存在则通过get方式拿去字典中的access_token键的值以及用户编号openid的值
    if "errcode" in resp_dict:
        return u"获取access_token失败"
    
    access_token = resp_dict.get("access_token")
    open_id = resp_dict.get("openid")  # 用户的编号
    • step5 向微信服务器发送http请求,获取用户的资料数据 
    url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" %(access_token,open_id)
    
    response = urllib2.urlopen(url)
    
    # 读取微信传回的json的响应体数据
    user_json_str = response.read()
    user_dict_data = json.loads(user_json_str)
    • step6 判断微信返回的响应体数据中是否有errorcode字段,如果存在则返回失败信息,不存在说明微信返回的json数据为正确数据,则将该数据传给index.html模板,当用户访问 http://xxx/wechat8007/index地址时,会渲染出我们定义的index.html模板
    if "errcode" in user_dict_data:
        return u"获取用户信息失败"
    else:
        # 将用户的资料数据填充到页面中
        return render_template("index.html", user=user_dict_data)
    •  step7 当前目录下创建templates模板目录,在该目录中创建index.html文件 ,代码如下
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>{{user["nickname"]}}的个人主页</title>
    </head>
    <body>
        <img alt="头像" src="{{user['headimgurl']}}" width="60">
        <table>
            <tr>
                <th>openid</th>
                <td>{{user["openid"]}}</td>
            </tr>
            <tr>
                <th>昵称</th>
                <td>{{user["nickname"]}}</td>
            </tr>
            <tr>
                <th>性别</th>
                <td>
                    {% if 1 == user["sex"] %}
                        男
                    {% elif 2 == user["sex"] %}
                        女
                    {% else %}
                        未知
                    {% endif %}
                </td>
            </tr>
            <tr>
                <th>省份</th>
                <td>{{user["province"]}}</td>
            </tr>
            <tr>
                <th>城市</th>
                <td>{{user["city"]}}</td>
            </tr>
            <tr>
                <th>国家</th>
                <td>{{user["country"]}}</td>
            </tr>
        </table>
    </body>
    </html>

     三丶部署测试

    • step1 将代码推送到服务器上

    成功推送到服务器上

    •  step2 在服务器上进入虚拟环境,运行此程序

     

    In [1]: import urllib
    
    In [2]: urllib.quote("http://www.xxx.com/wechat8007/index")
    Out[2]: 'http%3A//www.xxx.com/wechat8007/index'
    
    
    

     

    • 拼接好的用户访问的url地址为

    • step4 可以将该网址生成二维码,使用微信扫一扫,也可以在接口公众号直接发送此链接地址
    •  使用谷歌浏览器的二维码插件,将网址生成对应的二维码(这里以百度首页网址为例)

    • 直接在浏览器中输入此地址会提示请在微信客户端打开链接

    •  step5 测试,在手机微信上打开此链接,出现授权登录提示,点击允许即可获取用户个人信息

    点击允许后,进入如下界面

    点击继续访问,则出现博主个人的微信信息了,如下图 

    此时查看服务器上程序运行日志 

    四丶完整代码

    # coding:utf-8
    from flask import Flask, request, render_template
    import json, urllib2
    
    
    WECHAT_APPID = "yourappid"
    WECHAT_APPSECRET = "yoursecret"
    
    app = Flask(__name__)
    
    
    
    @app.route("/wechat8007/index")
    def index():
    
        code = request.args.get("code")
    
        if not code:
            return u"缺失code参数"
    
        url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" % (WECHAT_APPID, WECHAT_APPSECRET, code)
    
        response = urllib2.urlopen(url)
    
        json_str = response.read()
        resp_dict = json.loads(json_str)
    
        if "errcode" in resp_dict:
            return u"获取access_token失败"
    
        access_token = resp_dict.get("access_token")
        open_id = resp_dict.get("openid")
    
        url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" % (access_token, open_id)
    
        response = urllib2.urlopen(url)
        user_json_str = response.read()
        user_dict_data = json.loads(user_json_str)
    
        if "errcode" in user_dict_data:
            return u"获取用户信息失败"
        else:
            return render_template("index.html", user=user_dict_data)
    
    
    if __name__ == '__main__':
        app.run(port=8007, debug=True)

    总结:微信公众号接口开发,根据官方提供的开发文档,进行开发,逻辑实现都很简单,多想多思考多练习,你会越来越棒的!

    展开全文
  • 微信开发文档中写的不够清楚,做出来的是网页授权后获取用户信息,不是自己想要的,自己想做的是获取用户基本信息,在开发中总结了一下思路,开始的时候使用的是https://api.weixin.qq.com/sns/oauth2/ 去获取用户...
  • 微信小程序授权 获取用户信息

    万次阅读 2019-07-15 18:02:21
    获取用户信息(用户信息获取unionId、openId)请移步到这里 用户打开小程序时,直接弹框获取用户信息授权,可能会立马懵圈: 你是谁? 我在哪里? 我为什么要同意?…… 相当一部分用户下意识会拒绝...
  • 步骤一:申请微信开发者测试账号 ...amp;amp;...步骤二:需要一个服务器,用来获取你要的信息,我使用的是阿里云 https://www.aliyun.com/?utm_content=se_1000301881 有了阿里云后推荐使用最近挺火的...
  • 前言: 在微信公众号请求用户网页授权之前,开发者需要先在自己的公众平台配置好基本配置,修改授权回调域名JS安全域名。并且需要先获取到全局access_token,这里不对全局access_token的获取做详细讲解,可以参考...
  • 微信使用https协议,so,编写https工具类:[/b] [code="java"] package com.lishidao.app.controller; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; ...
  • JAVA 获取微信用户信息,看完这篇你必须得学会

    千次阅读 热门讨论 2020-09-29 16:56:53
    很多IT搬砖员,磕磕碰碰,都比较生怕遇到自己未接触过的东西,但是作为开发,迟早有一天,某个领导跟你说,某个需求,需要接入微信公众号,需要获取微信用户信息。 虽然说微信提供了相关的文档,但是免不了还是很多...
  • 微信H5页面 1 静默授权 2 用户未关注公众号 如何获取用户信息(昵称、头像、性别等)
  • 如题如何,二维码生成用的是QrCode,里面放了一个地址。扫描后可以挑战到二维码中存储的那个地址。 请教一下。我跳转到我指定的请求地址的时候如何获取扫描用户的openid
  • 微信关注公众号获取用户信息

    千次阅读 2018-10-20 16:33:25
    原本以为,获取用户信息,只能通过微信授权,后来才知道在关注公众号的时候,也可以获取用户信息,而且这两种获取用户信息的方式是不同的,也没有什么交集 关注公众号,是通过接收事件推送,事件推送:关注成功,...
  • 微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: bug示例图: 导致这个bug的原因是wx.getUserInfo(OBJECT) 接口做了调整; 请看官方文档的描述: wx.getUserInfo(OBJECT) ...
  • 老板让做一个项目,PC端的已经写完了,可是手机端的完全不懂该怎么做,JSSDK那些也看不是很懂,手机端的功能主要就是通过微信扫一扫获取用户的微信号等一些资料,翻了各种资料,网上也没有什么实例,求大神指导,该...
  • 因年会需要,需要抓取微信群内个人id的方法,请各位大神不吝赐教
  • 微信公众号开发--获取用户信息中文乱码的解决方案,获取自定义菜单中文乱码解决方案
  • 接下来博主将会分享用户登录授权,以及获取用户信息进行授权相关的一些东西,帮助大家避坑,最后附上源码! 收货地址的api接口 在真机运行的情况下,会出现小程序编写好的一个填写地址的页面 在不同账号...
  • 有没有人知道怎么样才能获取微信上某个用户的IP地址?不是微信公众号的服务器IP。
1 2 3 4 5 ... 20
收藏数 192,373
精华内容 76,949
关键字:

获取微信用户信息