diff --git a/.gitignore b/.gitignore index a106d9f..37683d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,28 +1,5 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - /vendor/ .idea/ .phpunit.* -composer.lock \ No newline at end of file +composer.lock +/test/Web/ \ No newline at end of file diff --git a/README.md b/README.md index eef201d..6d3bf59 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,23 @@ PHP 版 JustAuth ## TODO -- [x] 先能用 -- [x] 支持 GITEE 平台 -- [x] 支持 GITHUB 平台 -- [x] 支持 微博 平台 -- [ ] 支持 OSChina 平台 -- [ ] 支持 百度 平台 -- [ ] 支持 抖音 平台 -- [ ] 支持 钉钉 平台 +- [x] 先能用 +- [x] 支持 GITEE 平台 +- [x] 支持 GITHUB 平台 +- [x] 支持 OSChina 平台 +- [x] 支持 StackOverflow 平台 +- [x] 支持 钉钉 平台 +- [x] 支持 百度 平台 +- [x] 支持 微博 平台 +- [x] 支持 抖音 平台 +- [x] 支持 QQ 平台 +- [ ] 支持 微信 平台 +- [ ] 支持 华为 平台 +- [ ] 支持 Google 平台 - [ ] 支持 Coding 平台 - [ ] 支持 腾讯云开发者平台 平台 -- [ ] 支持 QQ 平台 -- [ ] 支持 微信 平台 - [ ] 支持 淘宝 平台 -- [ ] 支持 Google 平台 + # JustAuth 项目一览 diff --git a/composer.json b/composer.json index cd28bfa..6eadc56 100755 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "pfinal/justauth-php", - "description": "description", + "description": "library of third-party authorized login", "minimum-stability": "stable", "license": "MIT", "authors": [ @@ -26,7 +26,9 @@ "psr-4": { "JustAuth\\": "src/" }, - "files": [] + "files": [ + "src/helper.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/config/oauth.php b/config/oauth.php index cf50021..5c452a9 100644 --- a/config/oauth.php +++ b/config/oauth.php @@ -1,18 +1,67 @@ [ - 'client_id'=>env('GITHUB_CLIENT_ID','f4687fdd6801354516b3'), - 'redirect_url'=>env('GITHUB_CALLBACK','dev.local.justauth.cn/test/Github/index.php'), - 'client_secret'=>env('GITHUB_SECRET','03201d93b38f7eac722899420aaa35e6f375a8c4'), - ], - 'gitee' => [ - 'client_id'=>env('GITEE_CLIENT_ID',''), - 'redirect_url'=>env('GITEE_CALLBACK',''), - 'client_secret'=>env('GITEE_SECRET',''), - ], - 'weibo' => [ - 'client_id'=>env('WEIBO_CLIENT_ID',''), - 'redirect_url'=>env('WEIBO_CALLBACK',''), - 'client_secret'=>env('WEIBO_SECRET',''), + 'github' => [ + 'client_id' => env('GITHUB_CLIENT_ID', ''), + 'redirect_uri' => env('GITHUB_CALLBACK', ''), + 'client_secret' => env('GITHUB_SECRET', ''), + ], + 'gitee' => [ + 'client_id' => env('GITEE_CLIENT_ID', ''), + 'client_secret' => env('GITEE_SECRET', ''), + 'redirect_uri' => env('GITEE_CALLBACK', ''), + ], + 'weibo' => [ + 'client_id' => env('WEIBO_CLIENT_ID', ''), + 'redirect_url' => env('WEIBO_CALLBACK', ''), + 'client_secret' => env('WEIBO_SECRET', ''), + ], + 'douyin' => [ + 'client_id' => env('WEIBO_CLIENT_ID', ''), + 'redirect_uri' => env('WEIBO_CALLBACK', ''), + 'client_secret' => env('WEIBO_SECRET', ''), + 'state' => env('WEIBO_STATE', ''), + ], + 'weixin' => [ + 'client_id' => env('WEIXIN_CLIENT_ID', ''), + 'redirect_uri' => env('WEIXIN_CALLBACK', ''), + 'client_secret' => env('WEIXIN_SECRET', ''), + ], + 'qq' => [ + 'client_id' => env('QQ_CLIENT_ID', ''), + 'redirect_uri' => env('QQ_CALLBACK', ''), + 'client_secret' => env('QQ_SECRET', ''), + ], + 'huawei' => [ + 'client_id' => env('HUAWEI_CLIENT_ID', ''), + 'redirect_uri' => env('HUAWEI_CALLBACK', ''), + 'client_secret' => env('HUAWEI_SECRET', ''), + 'scope' => env('HUAWEI_SECRET', ''), + 'state' => env('HUAWEI_STATE', ''), + ], + 'google' => [ + 'client_id' => env('GOOGLE_CLIENT_ID', ''), + 'redirect_uri' => env('GOOGLE_CALLBACK', ''), + 'client_secret' => env('GOOGLE_SECRET', ''), + ], + 'baidu' => [ + 'client_id' => env('BAIDU_CLIENT_ID', ''), + 'redirect_uri' => env('BAIDU_CALLBACK', ''), + 'client_secret' => env('GOOGLE_SECRET', ''), + ], + 'oschina' => [ + 'client_id' => env('OSCHINA_CLIENT_ID', ''), + 'redirect_uri' => env('OSCHINA_CALLBACK', ''), + 'client_secret' => env('OSCHINA_SECRET', ''), + ], + 'stackoverflow' => [ + 'client_id' => env('OSCHINA_CLIENT_ID', ''), + 'redirect_uri' => env('OSCHINA_CALLBACK', ''), + 'client_secret' => env('OSCHINA_SECRET', ''), + 'client_key' => env('OSCHINA_SECRET', ''), + ], + 'dingtalk' => [ + 'client_id' => env('OSCHINA_CLIENT_ID', ''), + 'redirect_uri' => env('OSCHINA_CALLBACK', ''), + 'client_secret' => env('OSCHINA_SECRET', ''), ] ]; \ No newline at end of file diff --git a/src/Config/AuthDefaultSource.php b/src/Config/AuthDefaultSource.php index fbbc535..60c03d1 100644 --- a/src/Config/AuthDefaultSource.php +++ b/src/Config/AuthDefaultSource.php @@ -17,10 +17,18 @@ class AuthDefaultSource public $github; public $weibo; public $weixin; + public $douyin; + public $qq; + public $huawei; + public $google; + public $baidu; + public $oschina; + public $stackoverflow; + public $dingtalk; public function __construct() { - $this->gitee = new class extends AuthSource { + $this->gitee = new class extends AuthSource { public function authorize(): string { return "https://gitee.com/oauth/authorize"; @@ -36,7 +44,7 @@ public function userInfo(): string return "https://gitee.com/api/v5/user"; } }; - $this->github = new class extends AuthSource { + $this->github = new class extends AuthSource { public function authorize(): string { return "https://github.com/login/oauth/authorize"; @@ -49,10 +57,10 @@ public function accessToken(): string public function userInfo(): string { - return "https://api.github.com/user"; + return "https://api.github.com/user/repos"; } }; - $this->weibo = new class extends AuthSource { + $this->weibo = new class extends AuthSource { public function authorize(): string { return "https://api.weibo.com/oauth2/authorize"; @@ -73,7 +81,7 @@ public function userId(): string return "https://api.weibo.com/oauth2/get_token_info?access_token="; } }; - $this->weixin = new class extends AuthSource { + $this->weixin = new class extends AuthSource { public function authorize(): string { return "https://open.weixin.qq.com/connect/qrconnect"; @@ -89,6 +97,155 @@ public function userInfo(): string return "https://api.weixin.qq.com/sns/userinfo"; } }; + $this->douyin = new class extends AuthSource { + public function authorize(): string + { + return "https://open.douyin.com/platform/oauth/connect/"; + } + + public function accessToken(): string + { + return "https://open.douyin.com/oauth/access_token/"; + } + + public function userInfo(): string + { + return "https://open.douyin.com/oauth/userinfo/"; + } + }; + $this->qq = new class extends AuthSource { + public function authorize(): string + { + return "https://graph.qq.com/oauth2.0/authorize"; + } + + public function accessToken(): string + { + return "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code"; + } + + public function userInfo(): string + { + return "https://graph.qq.com/user/get_user_info"; + } + + public function getUid(): string + { + return "https://graph.qq.com/oauth2.0/me?access_token="; + } + + public function getUnionid(): string + { + return "https://graph.qq.com/oauth2.0/me?access_token="; + } + }; + $this->huawei = new class extends AuthSource { + public function authorize(): string + { + return "https://oauth-login.cloud.huawei.com/oauth2/v2/authorize"; + } + + public function accessToken(): string + { + return "https://oauth-login.cloud.huawei.com/oauth2/v3/token"; + } + + public function userInfo(): string + { + return "https://api.cloud.huawei.com/rest.php?nsp_fmt=JSON&nsp_svc=huawei.oauth2.user.getTokenInfo"; + } + }; + $this->google = new class extends AuthSource { + public function authorize(): string + { + return "https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline"; + } + + public function accessToken(): string + { + return "https://accounts.google.com/o/oauth2/token"; + } + + public function userInfo(): string + { + return "https://www.googleapis.com/oauth2/v1/userinfo"; + } + + public function scope(): string + { + return "https://www.googleapis.com/auth/userinfo.profile"; + } + }; + $this->baidu = new class extends AuthSource { + public function authorize(): string + { + return "http://openapi.baidu.com/oauth/2.0/authorize"; + } + + public function accessToken(): string + { + return "https://openapi.baidu.com/oauth/2.0/token"; + } + + public function userInfo(): string + { + return "https://openapi.baidu.com/rest/2.0/passport/users/getInfo"; + } + }; + $this->oschina = new class extends AuthSource { + public function authorize(): string + { + return "https://www.oschina.net/action/oauth2/authorize"; + } + + public function accessToken(): string + { + return "https://www.oschina.net/action/openapi/token"; + } + + public function userInfo(): string + { + return "https://www.oschina.net/action/openapi/my_information"; + } + }; + $this->stackoverflow = new class extends AuthSource { + public function authorize(): string + { + return "https://stackoverflow.com/oauth"; + } + + public function accessToken(): string + { + return "https://stackoverflow.com/oauth/access_token/json"; + } + + public function userInfo(): string + { + return "https://api.stackexchange.com/2.2/me"; + } + }; + $this->dingtalk = new class extends AuthSource { + public function authorize(): string + { + return "https://oapi.dingtalk.com/connect/qrconnect"; + } + + public function accessToken(): string + { + return "https://oapi.dingtalk.com/sns/gettoken"; + } + + public function userInfo(): string + { + return "https://oapi.dingtalk.com/sns/getuserinfo_bycode"; + } + + public function getPersistentCode(): string + { + return "https://oapi.dingtalk.com/sns/get_persistent_code"; + } + }; + } /** diff --git a/src/Enums/AuthResponseStatus.php b/src/Enums/AuthResponseStatus.php index 0e8836e..3202914 100644 --- a/src/Enums/AuthResponseStatus.php +++ b/src/Enums/AuthResponseStatus.php @@ -34,9 +34,12 @@ class AuthResponseStatus extends Enum /** @msg('Illegal state') */ const ILLEGAL_STATUS = 5009; /** @msg('Config Error') */ - const CONFIG_ERROR=5010; + const CONFIG_ERROR = 5010; /** @msg('Config Source Error') */ - const CONFIG_SOURCE_ERROR=5011; - + const CONFIG_SOURCE_ERROR = 5011; + /** @msg('Get user openid eroor') * */ + const GET_OPENID_ERROR = 5012; + /** @msg('Get user info eroor') * */ + const GET_USERINFO_ERROR = 5013; } \ No newline at end of file diff --git a/src/Request/AuthApi.php b/src/Request/AuthApi.php index be75c4d..8024ded 100644 --- a/src/Request/AuthApi.php +++ b/src/Request/AuthApi.php @@ -7,7 +7,6 @@ namespace JustAuth\Request; - use JustAuth\Enums\AuthResponseStatus; use JustAuth\Exception\AuthException; @@ -17,15 +16,15 @@ class AuthApi protected $driver; private $base_api_name_space = 'JustAuth\Request\Source\\'; - public function __construct($driver, array $config,$url) + public function __construct($driver, array $config, $url) { $this->driver = $driver; - $platform = ucfirst(strtolower($driver)); - $className = $this->base_api_name_space.'Auth'.$platform.'Request'; - if(!class_exists($className)) { + $platform = ucfirst(strtolower($driver)); + $className = $this->base_api_name_space . 'Auth' . $platform . 'Request'; + if (!class_exists($className)) { throw new AuthException(AuthResponseStatus::NOT_IMPLEMENTED()); } - return $this->api = new $className($config,$url); + return $this->api = new $className($config, $url); } public function authorization() @@ -35,12 +34,21 @@ public function authorization() public function getAccessToken(): string { - return $this->api->getAccessToken(); + try { + return $this->api->getAccessToken(); + }catch (AuthException $e) { + throw new AuthException($e->getCode(),$e->getMessage()); + } + } - public function getUserInfo(): object + public function getUserInfo(): array { - $oauth = $this->getAccessToken(); - return $this->api->getUserInfo($oauth); + try { + $oauth = $this->getAccessToken(); + return $this->api->getUserInfo($oauth); + }catch (AuthException $e) { + throw new AuthException($e->getCode(),$e->getMessage()); + } } } \ No newline at end of file diff --git a/src/Request/AuthBase.php b/src/Request/AuthBase.php index 243fd58..c79fe6a 100644 --- a/src/Request/AuthBase.php +++ b/src/Request/AuthBase.php @@ -14,33 +14,35 @@ class AuthBase { - private $driver = ['gitee', 'github','weibo']; + private $driver = ['gitee', 'github', 'dingtalk', 'weibo', 'weixin', 'douyin', 'qq', 'huawei', 'google', 'baidu', 'oschina', 'stackoverflow']; protected $source_config; protected $config = []; + public function __construct() { $this->source_config = new AuthDefaultSource(); } - public function OAuth2($config,$driver): AuthApi + public function OAuth2($config, $driver) { try { # 加载配置文件 $source_config = $this->source_config->getConfig($driver); - $this->config = $this->get_config($config,$driver); + $this->config = $this->get_config($config, $driver); $this->verified($driver); - return new AuthApi($driver,$this->config,$source_config); + return new AuthApi($driver, $this->config, $source_config); } catch (AuthException $e) { throw new \Exception($e->getMessage(), $e->getCode()); } } - protected function get_config($config_path,$driver) { + protected function get_config($config_path, $driver) + { if (!file_exists($config_path)) { throw new AuthException(AuthResponseStatus::CONFIG_ERROR()); } - $config = require_once $config_path; + $config = require $config_path; if (!isset($config[$driver])) { throw new AuthException(AuthResponseStatus::CONFIG_ERROR()); } diff --git a/src/Request/Source/AuthBaiduRequest.php b/src/Request/Source/AuthBaiduRequest.php new file mode 100644 index 0000000..af630f8 --- /dev/null +++ b/src/Request/Source/AuthBaiduRequest.php @@ -0,0 +1,62 @@ +source_url->authorize(); + $query = array_filter([ + 'response_type' => 'code', + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'display' => 'popup' + ]); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + 'redirect_uri' => $this->config['redirect_uri'], + ]); + try { + return $this->http->request('POST', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + } catch (\Throwable $throwable) { + var_dump($throwable->getCode()); + throw new AuthException($throwable->getCode(), $throwable->getMessage()); + } + + } + + public function getUserInfo($access_token) + { + $access_data = json_decode($access_token); + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'access_token' => $access_data->access_token + ]); + return json_decode($this->http->request('GET', $user_info_url, [ + 'query' => $query, + ])->getBody()->getContents(),true); + } +} \ No newline at end of file diff --git a/src/Request/Source/AuthCommonRequest.php b/src/Request/Source/AuthCommonRequest.php index e0ead80..6b1c5eb 100644 --- a/src/Request/Source/AuthCommonRequest.php +++ b/src/Request/Source/AuthCommonRequest.php @@ -8,8 +8,9 @@ use GuzzleHttp\Client; +use JustAuth\Config\AuthSource; -abstract class AuthCommonRequest +abstract class AuthCommonRequest { /** @@ -55,20 +56,19 @@ abstract class AuthCommonRequest public $loginAgentUrl; /** - * 接口地址 - * @var array + * @var AuthSource */ - public $source_url = []; + public $source_url; public $config = []; public $http = null; - public function __construct($config, $source) + public function __construct(array $config, AuthSource $source) { $this->http_driver(); $this->source_url = $source; - $this->config = $config; + $this->config = $config; } /** diff --git a/src/Request/Source/AuthDingtalkRequest.php b/src/Request/Source/AuthDingtalkRequest.php new file mode 100644 index 0000000..921b748 --- /dev/null +++ b/src/Request/Source/AuthDingtalkRequest.php @@ -0,0 +1,103 @@ +source_url->authorize(); + $query = array_filter([ + 'appid' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'response_type' => 'code', + 'scope' => 'snsapi_login', + 'state' => 'STATE', + ]); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'appid' => $this->config['client_id'], + 'appsecret' => $this->config['client_secret'], + ]); + return $this->http->request('GET', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + } + + + public function getUserInfo($access_token) + { + $access_data = json_decode($access_token, true); + //$permanent_code = $this->getPersistentCode($access_data['access_token'], Request::get('code')); + $time = millisecondWay(); + $signature = $this->_setSignature($time); + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'accessKey' => $this->config['client_id'], + 'signature' => $signature, + 'timestamp' => $time, + ]); + $result = json_decode($this->http->request('POST', $user_info_url, [ + 'query' => $query, + 'headers' => ['content-type' => 'application/json'], + 'body' => json_encode([ + 'tmp_auth_code' => Request::get('code') + ]) + ])->getBody()->getContents(), true); + if ($result && isset($result['errcode'])) { + throw new AuthException($result['errcode'], $result['errmsg']); + } + return $result; + } + + private function _setSignature($time) + { + $s = hash_hmac('sha256', $time, $this->config['client_secret'], true); + $signature = base64_encode($s); + return $signature; + //return urlencode($signature); + } + + public function getUid($access_token) + { + $user_id_url = $this->source_url->userId(); + $result = $this->http->post($user_id_url . $access_token); + $result = json_decode($result->getBody()->getContents(), true); + return $result['uid']; + } + + private function getPersistentCode($access_token, $tmp_auth_code) + { + $get_permanent_code_url = $this->source_url->getPersistentCode(); + $query = array_filter([ + 'access_token' => $access_token + ]); + try { + $result = $this->http->request('POST', $get_permanent_code_url, [ + 'query' => $query, + 'headers' => ['content-type' => 'application/json'], + 'body' => json_encode([ + 'tmp_auth_code' => $tmp_auth_code + ]) + ]); + return json_decode($result->getBody()->getContents(), true); + } catch (\Exception $e) { + return new AuthException(GET_OPENID_ERROR()); + } + } +} \ No newline at end of file diff --git a/src/Request/Source/AuthDouyinRequest.php b/src/Request/Source/AuthDouyinRequest.php new file mode 100644 index 0000000..c2de08d --- /dev/null +++ b/src/Request/Source/AuthDouyinRequest.php @@ -0,0 +1,75 @@ +source_url->authorize(); + $query = array_filter([ + 'response_type' => 'code', + 'client_key' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'scope' => '', + 'state' => $this->config['state'], + ]); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_key' => $this->config['client_id'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + 'redirect_uri' => $this->config['redirect_uri'], + ]); + $res = json_decode($this->http->request('GET', $token_url, [ + 'query' => $query, + ])->getBody()->getContents())->data(); + $this->openid = $res->open_id; + $this->unionid = $res->unionid; + return $res->access_token; + } + + /** + * 获取用户信息 + * @param $access_token + * @return mixed + */ + public function getUserInfo($access_token) + { + $query = array_filter([ + 'open_id' => $this->openid, + + 'access_token' => $access_token, + ]); + $userinfo_url = $this->source_url->userInfo(); + $userinfo = json_decode($this->http->request('GET', $userinfo_url, [ + 'query' => $query, + ])->getBody()->getContents())->data; + + $userinfo->openid = $userinfo->open_id; + $userinfo->unionid = $userinfo->union_id; + + return $userinfo; + } +} \ No newline at end of file diff --git a/src/Request/Source/AuthGiteeRequest.php b/src/Request/Source/AuthGiteeRequest.php index 9063790..9c2f627 100644 --- a/src/Request/Source/AuthGiteeRequest.php +++ b/src/Request/Source/AuthGiteeRequest.php @@ -7,6 +7,7 @@ namespace JustAuth\Request\Source; use pf\request\Request; +use JustAuth\Exception\AuthException; class AuthGiteeRequest extends AuthCommonRequest { @@ -16,13 +17,13 @@ class AuthGiteeRequest extends AuthCommonRequest public function authorization() { $auth_url = $this->source_url->authorize(); - $query = array_filter([ - 'client_id' => $this->config['client_id'], - 'redirect_uri' => $this->config['redirect_uri'], + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], 'response_type' => 'code', ]); - $url = $auth_url.'?'.http_build_query($query); - header('Location:'.$url); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); exit(); } @@ -30,16 +31,20 @@ public function authorization() public function getAccessToken() { $token_url = $this->source_url->accessToken(); - $query = array_filter([ - 'client_id' => $this->config['client_id'], - 'redirect_uri' => $this->config['redirect_uri'], - 'code' => Request::get('code'), - 'grant_type' => 'authorization_code', + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', 'client_secret' => $this->config['client_secret'], ]); - return $this->http->request('POST', $token_url, [ - 'query' => $query, - ])->getBody()->getContents(); + try { + return $this->http->request('POST', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + }catch (\Throwable $throwable) { + throw new AuthException($throwable->getCode(),$throwable->getMessage()); + } } /** @@ -49,7 +54,13 @@ public function getAccessToken() */ public function getUserInfo($access_token) { + $access_data = json_decode($access_token); $user_info_url = $this->source_url->userInfo(); - return json_decode($this->http->get($user_info_url)->getBody()->getContents()); + $query = array_filter([ + 'access_token'=>$access_data->access_token + ]); + return json_decode($this->http->request('GET', $user_info_url, [ + 'query' => $query + ])->getBody()->getContents(),true); } } \ No newline at end of file diff --git a/src/Request/Source/AuthGithubRequest.php b/src/Request/Source/AuthGithubRequest.php index 860d4f4..2e144d5 100644 --- a/src/Request/Source/AuthGithubRequest.php +++ b/src/Request/Source/AuthGithubRequest.php @@ -7,7 +7,7 @@ namespace JustAuth\Request\Source; use pf\request\Request; - +use JustAuth\Exception\AuthException; class AuthGithubRequest extends AuthCommonRequest { /** @@ -16,12 +16,12 @@ class AuthGithubRequest extends AuthCommonRequest public function authorization() { $auth_url = $this->source_url->authorize(); - $query = array_filter([ - 'client_id' => $this->config['client_id'], - 'redirect_uri' => $this->config['redirect_url'], + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], ]); - $url = $auth_url.'?'.http_build_query($query); - header('Location:'.$url); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); exit(); } @@ -29,10 +29,10 @@ public function authorization() public function getAccessToken() { $token_url = $this->source_url->accessToken(); - $query = array_filter([ - 'client_id' => $this->config['client_id'], - 'redirect_uri' => $this->config['redirect_url'], - 'code' => Request::get('code'), + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'code' => Request::get('code'), 'client_secret' => $this->config['client_secret'], ]); return $this->http->request('POST', $token_url, [ @@ -47,11 +47,16 @@ public function getAccessToken() */ public function getUserInfo($access_token) { + $access_data = []; + parse_str($access_token,$access_data); + if(count($access_data)<=0 || isset($access_data['error'])) { + throw new AuthException(401,$access_data['error_description']); + } $user_info_url = $this->source_url->userInfo(); return json_decode($this->http->request('GET', $user_info_url, [ 'headers' => [ - 'Authorization' => 'Bearer '.$access_token, + 'Authorization' => 'Bearer ' . $access_data['access_token'], ], - ])->getBody()->getContents()); + ])->getBody()->getContents(),true); } } \ No newline at end of file diff --git a/src/Request/Source/AuthGoogleRequest.php b/src/Request/Source/AuthGoogleRequest.php new file mode 100644 index 0000000..62194a6 --- /dev/null +++ b/src/Request/Source/AuthGoogleRequest.php @@ -0,0 +1,56 @@ +source_url->authorize(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => urlencode($this->config['redirect_uri']), + 'approval_prompt' => 'auto', + 'scope' => urlencode($this->source_url->scope()) + ]); + $url = $auth_url . '&state&' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + 'redirect_uri' => $this->config['redirect_uri'], + ]); + return $this->http->request('post', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + } + + public function getUserInfo($access_token) + { + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'access_token' => $access_token, + ]); + return json_decode($this->http->request('GET', $user_info_url, [ + 'query' => $query, + ])->getBody()->getContents()); + } + +} \ No newline at end of file diff --git a/src/Request/Source/AuthHuaweiRequest.php b/src/Request/Source/AuthHuaweiRequest.php new file mode 100644 index 0000000..6f577bb --- /dev/null +++ b/src/Request/Source/AuthHuaweiRequest.php @@ -0,0 +1,59 @@ +source_url->authorize(); + $query = array_filter([ + 'response_type' => 'code', + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'access_type' => 'offline', + 'scope' => $this->config['scope'], + 'state' => $this->config['state'], + ]); + + $url = $auth_url . '?' . http_build_query($query); + + header('Location:' . $url); + exit(); + } + + public function getAccessToken() + { + $token_Url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'code' => Request::get('code') ?? Request::get('authorization_code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + 'redirect_uri' => $this->config['redirect_uri'], + ]); + $res = json_decode($this->http->request('post', $token_Url, [ + 'form_params' => $query, + ])->getBody()->getContents()); + return $res->access_token; + + } + + public function getUserInfo($access_token) + { + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'openid' => 'OPENID', + + 'access_token' => $access_token, + ]); + return json_decode($this->http->request('POST', $user_info_url, [ + 'form_params' => $query, + ])->getBody()->getContents()); + } + +} \ No newline at end of file diff --git a/src/Request/Source/AuthOschinaRequest.php b/src/Request/Source/AuthOschinaRequest.php new file mode 100644 index 0000000..a287181 --- /dev/null +++ b/src/Request/Source/AuthOschinaRequest.php @@ -0,0 +1,66 @@ +source_url->authorize(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'response_type' => 'code', + ]); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + ]); + try { + return $this->http->request('POST', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + }catch (\Throwable $throwable) { + throw new AuthException($throwable->getCode(),$throwable->getMessage()); + } + } + + /** + * 获取用户信息 + * @param $access_token + * @return mixed + */ + public function getUserInfo($access_token) + { + $access_data = json_decode($access_token); + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'access_token'=>$access_data->access_token + ]); + return json_decode($this->http->request('GET', $user_info_url, [ + 'query' => $query + ])->getBody()->getContents(),true); + } +} \ No newline at end of file diff --git a/src/Request/Source/AuthQqRequest.php b/src/Request/Source/AuthQqRequest.php new file mode 100644 index 0000000..15e5782 --- /dev/null +++ b/src/Request/Source/AuthQqRequest.php @@ -0,0 +1,100 @@ +source_url->authorize(); + $query = array_filter([ + 'response_type' => 'code', + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'scope' => '', + 'state' => $this->config['state'], + ]); + $url = $auth_url . '?' . http_build_query($query); + + header('Location:' . $url); + exit(); + + } + + public function getAccessToken() + { + if (isset($_GET['access_token'])) {//兼容app授权登陆 dcloud返回access_token; + return $_GET['access_token']; + } + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'code' => Request::get('code'), + 'grant_type' => 'authorization_code', + 'client_secret' => $this->config['client_secret'], + 'redirect_uri' => $this->config['redirect_uri'], + 'fmt' => 'json', + ]); + $token_url = $this->source_url->accessToken(); + $res = $this->http->request('get', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + $data = json_decode($res); + if (isset($data->access_token)) { + return $data->access_token; + } else { + return new AuthException(AuthResponseStatus::FAILURE()); + } + } + + public function getUserInfo($access_token) + { + $result = $this->getUid($access_token); + $userinfo_url = $this->source_url->userInfo(); + $query = array_filter([ + 'openid' => $result->openid, + 'oauth_consumer_key' => $result->client_id, + 'access_token' => $access_token, + ]); + $userinfo = json_decode($this->http->request('GET', $userinfo_url, [ + 'query' => $query, + ])->getBody()->getContents()); + if (0 != $userinfo->ret) { + return new AuthException(AuthResponseStatus::GET_USERINFO_ERROR()); + } + $userinfo->openid = $this->getUid($access_token)->openid; + + $userinfo->unionid = $this->getUnionid($access_token)->unionid; + $user = new \stdClass(); + $user->openid = $userinfo->openid; + $user->unionid = $this->getUnionid($access_token)->unionid ?? ''; + $user->email = $user->openid . '@open.qq.com'; + $user->nickname = $userinfo->nickname; + $user->avatar = $userinfo->figureurl_2; + return $user; + } + + public function getUid($access_token) + { + $uid_url = $this->source_url->getUid(); + $str = $this->http->get($uid_url . $access_token . '&fmt=json')->getBody()->getContents(); + $user = json_decode($str); + if (isset($user->openid)) { + return $user; + } else { + return new AuthException(AuthResponseStatus::GET_OPENID_ERROR()); + } + } + + public function getUnionid($access_token) + { + $id_url = $this->source_url->getUnionid(); + $str = $this->http->get($id_url . $access_token . '&unionid=1&fmt=json')->getBody()->getContents(); + return json_decode($str); + } +} \ No newline at end of file diff --git a/src/Request/Source/AuthStackoverflowRequest.php b/src/Request/Source/AuthStackoverflowRequest.php new file mode 100644 index 0000000..75a01c6 --- /dev/null +++ b/src/Request/Source/AuthStackoverflowRequest.php @@ -0,0 +1,70 @@ +source_url->authorize(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'response_type' => 'code', + ]); + $url = $auth_url . '?' . http_build_query($query); + header('Location:' . $url); + exit(); + } + + + public function getAccessToken() + { + $token_url = $this->source_url->accessToken(); + $query = array_filter([ + 'client_id' => $this->config['client_id'], + 'redirect_uri' => $this->config['redirect_uri'], + 'code' => Request::get('code'), + 'client_secret' => $this->config['client_secret'], + ]); + try { + return $this->http->request('POST', $token_url, [ + 'query' => $query, + ])->getBody()->getContents(); + } catch (\Throwable $throwable) { + throw new AuthException($throwable->getCode(), $throwable->getMessage()); + } + } + + /** + * 获取用户信息 + * @param $access_token + * @return mixed + */ + public function getUserInfo($access_token) + { + $access_data = json_decode($access_token); + $user_info_url = $this->source_url->userInfo(); + $query = array_filter([ + 'order' => 'desc', + 'sort' => 'reputation', + 'site' => 'stackoverflow', + 'filter' => '!6W.6dPDp64PF2', + 'key' => $this->config['client_key'], + 'access_token' => $access_data->access_token + ]); + return json_decode($this->http->request('GET', $user_info_url, [ + 'query' => $query + ])->getBody()->getContents(), true); + } +} \ No newline at end of file diff --git a/src/helper.php b/src/helper.php index f618f57..eed15f9 100644 --- a/src/helper.php +++ b/src/helper.php @@ -2,4 +2,17 @@ /** * @author pfinal南丞 * @date 2021年04月06日 下午6:18 - */ \ No newline at end of file + */ + +if (!function_exists('millisecondWay')) { + /** + * 获取一个毫秒级的时间戳 13位 + * @return float + */ + function millisecondWay(): float + { + ini_set('date.timezone', 'PRC'); + list($msec, $sec) = explode(' ', microtime()); + return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000); + } +} \ No newline at end of file diff --git a/test/Gitee/login.php b/test/Gitee/login.php deleted file mode 100644 index 879aed7..0000000 --- a/test/Gitee/login.php +++ /dev/null @@ -1,15 +0,0 @@ -authorization(); -} catch (\Exception $e) { - echo $e->getMessage()."\n"; -} - diff --git a/test/GiteeTest.php b/test/GiteeTest.php new file mode 100644 index 0000000..e3184a5 --- /dev/null +++ b/test/GiteeTest.php @@ -0,0 +1,28 @@ +assertInstanceOf('JustAuth\Request\AuthApi', $authRequest); + return $authRequest; + } + +// /** +// * @depends testInstance +// * +// * @param \JustAuth\Request\AuthApi $github +// * +// */ +// public function testRouterAdd(\JustAuth\Request\AuthApi $github) +// { +// $github->authorization(); +// } + +} \ No newline at end of file diff --git a/test/Github/login.php b/test/Github/login.php deleted file mode 100644 index 1e5f5d0..0000000 --- a/test/Github/login.php +++ /dev/null @@ -1,14 +0,0 @@ -authorization(); -} catch (\Exception $e) { - echo $e->getMessage()."\n"; -} diff --git a/test/GithubTest.php b/test/GithubTest.php index f749d12..1488591 100644 --- a/test/GithubTest.php +++ b/test/GithubTest.php @@ -13,6 +13,4 @@ public function testInstance() $this->assertInstanceOf('JustAuth\Request\AuthApi', $github); return $github; } - - } \ No newline at end of file diff --git a/test/OSChina/login.php b/test/OSChina/login.php deleted file mode 100644 index fb83673..0000000 --- a/test/OSChina/login.php +++ /dev/null @@ -1,5 +0,0 @@ -assertInstanceOf('JustAuth\Request\AuthApi', $github); + return $github; + } +} \ No newline at end of file diff --git a/test/Weibo/login.php b/test/Weibo/login.php deleted file mode 100644 index 995b205..0000000 --- a/test/Weibo/login.php +++ /dev/null @@ -1,14 +0,0 @@ -authorization(); -} catch (\Exception $e) { - echo $e->getMessage()."\n"; -} diff --git a/test/common.php b/test/common.php deleted file mode 100644 index f38b224..0000000 --- a/test/common.php +++ /dev/null @@ -1,7 +0,0 @@ -