Yii官方寫的第三方登陸擴展,能夠封裝了基於OpenId,OAuth1,OAuth2標準的第三方受權登陸過程,能夠輕鬆實現Facebook,GitHub,Google,LinkedIn等第三方登陸集成。無奈官方自帶的幾個第三方(Facebook,Google)等在天朝基本沒有意義,基本上只有借鑑學習的做用了。不過按照AuthClient的預約義接口,能夠輕鬆實現微信的OAuth登錄。php
AuthClient的每一個第三方登錄實現,都是經過擴展OAuth2這個類實現。先看下第一個函數:api
OAuth2.php /** * Composes user authorization URL. * @param array $params additional auth GET params. * @return string authorization URL. */ public function buildAuthUrl(array $params = []) { $defaultParams = [ 'client_id' => $this->clientId, 'response_type' => 'code', 'redirect_uri' => $this->getReturnUrl(), 'xoauth_displayname' => Yii::$app->name, ]; if (!empty($this->scope)) { $defaultParams['scope'] = $this->scope; } return $this->composeUrl($this->authUrl, array_merge($defaultParams, $params)); }
用於構建發起OAuth受權的URL,因爲微信的請求URL要求帶有'#wechat_redirect',而這個函數實現沒有爲這個額外的字符串預留位置,所以,須要重載這個函數:微信
//WeChat.php public function buildAuthUrl(array $params = []) { $defaultParams = [ 'appid' => $this->clientId, 'redirect_uri' => $this->getReturnUrl(), 'response_type'=>'code', 'scope'=>$this->scope, 'state'=>base64_encode(\Yii::$app->user->returnUrl) ]; $url = $this->composeUrl($this->authUrl, array_merge($defaultParams, $params)); return $url . '#wechat_redirect'; }
注意,基類用的是client_id,而微信要求的是appid,須要在重載的函數裏改爲appidyii2
第二個函數是fetchAccessToken,一樣的,須要重載,這裏只給出重載後的代碼:app
//WeChat.php public function fetchAccessToken($authCode, array $params = []) { $defaultParams = [ 'appid' => $this->clientId, 'secret' => $this->clientSecret, 'code' => $authCode, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->getReturnUrl(), ]; $response = $this->sendRequest('GET', $this->tokenUrl, array_merge($defaultParams, $params)); $token = null; if(isset($response['access_token'])) { $arr['oauth_token_secret'] = $this->clientSecret; $token = $this->createToken(['params' => array_merge($arr,$response),'class'=>WeChatToken::className()]); $this->setAccessToken($token); } return $token; }
第三個須要重載的函數是apiInternal,該函數在BaseOAuth基類的中被調用,用於獲取受權後的用戶信息。一樣的緣由,須要重載以下:yii
protected function apiInternal($accessToken, $url, $method, array $params, array $headers) { /** @var $accessToken WeChatToken */ $params['access_token'] = $accessToken->getToken(); $params['openid'] = $accessToken->getOpenID(); $params['lang'] = 'zh_CN'; return $this->sendRequest($method, $url, $params, $headers); }
自此,首次受權是沒問題了,再完善下刷新token的接口吧:函數
public function refreshAccessToken(OAuthToken $token) { /** * @var $token WeChatToken */ $params = [ 'appid' => $this->clientId, 'refresh_token' => $token->getRefreshToken(), 'grant_type' => 'refresh_token' ]; $response = $this->sendRequest('GET', $this->refreshTokenUrl, $params); $token = null; if(isset($response['access_token'])) { $arr['oauth_token_secret'] = $this->clientSecret; $token = $this->createToken(['params' => array_merge($arr,$response),'class'=>WeChatToken::className()]); $this->setAccessToken($token); } return $token; }
若是使用的是yii2-user的擴展,還有一些額外的接口須要實現,具體查看ClientInterface接口。學習