微信授權登錄並獲取用戶信息接口開發


一、首先你的微信公眾號要獲得相應的AppID和AppSecret,申請微信登錄且通過審核后,才可開始接入流程。

二、授權流程

1、流程說明

 

(1). 第三方發起微信授權登錄請求,微信用戶允許授權第三方應用后,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數;

 

(2). 通過code參數加上AppID和AppSecret等,通過API換取access_token;

 

(3). 通過access_token進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操作。

2、獲取access_token時序圖:

三、開發(我的用是CI框架,其實用什么框架都一樣,MVC模式就行了)

1、請求CODE

  weixin.php

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


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

//只要用戶一訪問此模塊,就登錄授權,獲取用戶信息
$this->userInfo = $this->getWxUserInfo();
}

/**
* 確保當前用戶是在微信中打開,並且獲取用戶信息
*
* @param string $url 獲取到微信授權臨時票據(code)回調頁面的URL
*/
private function getWxUserInfo($url = '') {
//微信標記(自己創建的)
$wxSign = $this->input->cookie('wxSign');
//先看看本地cookie里是否存在微信唯一標記,
//假如存在,可以通過$wxSign到redis里取出微信個人信息(因為在第一次取到微信個人信息,我會將其保存一份到redis服務器里緩存着)
if (!empty($wxSign)) {
//如果存在,則從Redis里取出緩存了的數據
$userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
if (!empty($userInfo)) {
//獲取用戶的openid
$this->wxId = $userInfo['openid'];
//將其存在cookie里
$this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
return $userInfo;
}
}

//獲取授權臨時票據(code)
$code = $_GET['code'];
if (empty($code)) {
if (empty($url)) {
$url = rtirm($_SERVER['QUERY_STRING'], '/');
//到WxModel.php里獲取到微信授權請求URL,然后redirect請求url
redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
}
}


}

}
?>

Wxmodel.php

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

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

//審核通過的移動應用所給的AppID和AppSecret
$this->appId = 'wx0000000000000000';
$this->appSecret = '00000000000000000000000000000';
$this->token = '00000000';
}

/**
* 獲取微信授權url
* @param string 授權后跳轉的URL
* @param bool 是否只獲取openid,true時,不會彈出授權頁面,但只能獲取用戶的openid,而false時,彈出授權頁面,可以通過openid獲取用戶信息
*
*/
public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
$redirectUrl = urlencode($redirectUrl);
$scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
$oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state";
return $oAuthUrl;
}

這里附上請求參數說明和返回值說明

  請求參數說明:

響應返回值說明:

當請求成功,會redirect到請求參數中的redirect_uri的值中去,其實又回到weixin.php的$this->userInfo = $this->getWxUserInfo();這行去,然后再一次進入到getWxUserInfo()方法,此時

//獲取授權臨時票據(code)

$code  $_GET [ 'code' ];

 這行也已經能獲取得到code的值了。接着進行第二步。

2、通過code獲取access_token

  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 = '') {
//微信標記(自己創建的)
$wxSign = $this->input->cookie('wxSign');
//先看看本地cookie里是否存在微信唯一標記,
//假如存在,可以通過$wxSign到redis里取出微信個人信息(因為在第一次取到微信個人信息,我會將其保存一份到redis服務器里緩存着)
if (!empty($wxSign)) {
//如果存在,則從Redis里取出緩存了的數據
$userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
if (!empty($userInfo)) {
//獲取用戶的openid
$this->wxId = $userInfo['openid'];
//將其存在cookie里
$this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
return $userInfo;
}
}

//獲取授權臨時票據(code)
$code = $_GET['code'];
if (empty($code)) {
if (empty($url)) {
$url = rtirm($_SERVER['QUERY_STRING'], '/');
//到WxModel.php里獲取到微信授權請求URL,然后redirect請求url(這里的redirect是請求微信,相當於302跳轉)
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);

WxModel.php

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

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

//審核通過的移動應用所給的AppID和AppSecret
$this->appId = 'wx0000000000000000';
$this->appSecret = '00000000000000000000000000000';
$this->token = '00000000';
}


/**
* 獲取微信授權url
* @param string 授權后跳轉的URL
* @param bool 是否只獲取openid,true時,不會彈出授權頁面,但只能獲取用戶的openid,而false時,彈出授權頁面,可以通過openid獲取用戶信息
*
*/
public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
$redirectUrl = urlencode($redirectUrl);
$scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
$oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
return $oAuthUrl;
}


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

這里附上參數說明

  請求參數說明:

響應返回值說明:

當返回錯誤時是這樣子的:

3、通過access_token調用接口(獲取用戶信息)
  獲取access_token后,進行接口調用,有以下前提:

  (1)access_tokec有效且未超時;

  (2)微信用戶已授權給第三方應用賬號相應的接口作用域(scope)。

  

  以下是獲取用戶信息的代碼

  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 = '') {
//微信標記(自己創建的)
$wxSign = $this->input->cookie('wxSign');
//先看看本地cookie里是否存在微信唯一標記,
//假如存在,可以通過$wxSign到redis里取出微信個人信息(因為在第一次取到微信個人信息,我會將其保存一份到redis服務器里緩存着)
if (!empty($wxSign)) {
//如果存在,則從Redis里取出緩存了的數據
$userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}");
if (!empty($userInfo)) {
//獲取用戶的openid
$this->wxId = $userInfo['openid'];
//將其存在cookie里
$this->input->set_cookie('wxId', $this->wxId, 60*60*24*7);
return $userInfo;
}
}

//獲取授權臨時票據(code)
$code = $_GET['code'];
if (empty($code)) {
if (empty($url)) {
$url = rtirm($_SERVER['QUERY_STRING'], '/');
//到WxModel.php里獲取到微信授權請求URL,然后redirect請求url
redirect($this->model->wx->getOAuthUrl(baseUrl($url)));
}
}
/***************這里開始第二步:通過code獲取access_token****************/
$result = $this->model->wx->getOauthAccessToken($code);

//如果發生錯誤
if (isset($result['errcode'])) {
return array('msg'=>'授權失敗,請聯系客服','result'=>$result);
}

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

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

/*******************這里開始第三步:通過access_token調用接口,取出用戶信息***********************/
$this->userInfo = $this->model->wx->getUserInfo($openId, $accessToken);

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

 

 

 

 

 


}
?>

WxModel.php

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

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

//審核通過的移動應用所給的AppID和AppSecret
$this->appId = 'wx0000000000000000';
$this->appSecret = '00000000000000000000000000000';
$this->token = '00000000';
}


/**
* 獲取微信授權url
* @param string 授權后跳轉的URL
* @param bool 是否只獲取openid,true時,不會彈出授權頁面,但只能獲取用戶的openid,而false時,彈出授權頁面,可以通過openid獲取用戶信息
*
*/
public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') {
$redirectUrl = urlencode($redirectUrl);
$scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo';
$oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect";
return $oAuthUrl;
}


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

/**
* 獲取用戶信息
*/
public function getUserInfo($openId, $accessToken) {
$url = 'https://api.weixin.qq.com/sns/userinfo';
//獲取用戶微信賬號信息
$userInfo = $this->callApi("$url?access_token=$accessToken&openid=$openId&lang=zh-CN");

if ($userInfo['errcode']) {
return array('msg'=>'獲取用戶信息失敗,請聯系客服', $userInfo);
}

$userInfo['wx_id'] = $openId;

return $userInfo;
}

/**
* 發起Api請求,並獲取返回結果
* @param string 請求URL
* @param mixed 請求參數 (array|string)
* @param string 請求類型 (GET|POST)
* @return array
*/
public function callApi($apiUrl, $param = array(), $method = 'GET') {
$result = curl_request_json($error, $apiUrl, $params, $method);
//假如返回的數組有錯誤碼,或者變量$error也有值
if (!empty($result['errcode'])) {
$errorCode = $result['errcode'];
$errorMsg = $result['errmsg'];
} else if ($error != false) {
$errorCode = $error['errorCode'];
$errorMsg = $error['errorMessage'];
}

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

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

}
}
//這里拋出異常,具有的就不詳說了
throw new WeixinException($errorMessage, $errorCode);
}
return $result;
}

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

 

 

 

?>

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 = 'GET', $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('errorCode'=>-1, 'errorMessage'=>'json decode fail', 'responseText'=>$responseText);
//將錯誤信息記錄日志文件里
$logText = "json decode fail : $url";
if (!empty($param)) {
$logText .= ", param=".json_encode($param);
}
$logText .= ", responseText=$responseText";
file_put_contents("/data/error.log", $logText);
}
}
return $response;
}

/**
* 發起一個HTTP(S)請求,並返回響應文本
* @param array 錯誤信息 array($errorCode, $errorMessage)
* @param string 請求Url
* @param array 請求參數
* @param string 請求類型(GET|POST)
* @param int 超時時間
* @param array 額外配置
*
* @return string
*/
public function curl_request_text(&$error, $url, $param = array(), $method = 'GET', $timeout = 15, $exOptions = NULL) {
//判斷是否開啟了curl擴展
if (!function_exists('curl_init')) exit('please open this curl extension');

//將請求方法變大寫
$method = strtoupper($method);

$ch = curl_init();
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HEADER, false);
if (isset($_SERVER['HTTP_USER_AGENT'])) curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
if (isset($_SERVER['HTTP_REFERER'])) curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
switch ($method) {
case 'POST':
curl_setopt($ch, CURLOPT_POST, true);
if (!empty($param)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($param)) ? http_build_query($param) : $param);
}
break;

case 'GET':
case 'DELETE':
if ($method == 'DELETE') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
}
if (!empty($param)) {
$url = $url.(strpos($url, '?') ? '&' : '?').(is_array($param) ? http_build_query($param) : $param);
}
break;
}
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_URL, $url);
//設置額外配置
if (!empty($exOptions)) {
foreach ($exOptions as $k => $v) {
curl_setopt($ch, $k, $v);
}
}
$response = curl_exec($ch);

$error = false;
//看是否有報錯
$errorCode = curl_errno($ch);
if ($errorCode) {
$errorMessage = curl_error($ch);
$error = array('errorCode'=>$errorCode, 'errorMessage'=>$errorMessage);
//將報錯寫入日志文件里
$logText = "$method $url: [$errorCode]$errorMessage";
if (!empty($param)) $logText .= ",$param".json_encode($param);
file_put_contents('/data/error.log', $logText);
}

curl_close($ch);

return $response;

 

}

 

?>

 小提示:1、先申請一個微信測試號(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login),這樣可以獲取到測試所需要的appID和appsecret;

     2、在測試號里面網頁授權獲取用戶基本信息里面輸入域名,如下圖

    

   3、把客戶端的微信請求鏈接放到微信里面就可以進行調試,看到測試結果了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM