From 7891e1d0858d0a936365eca2bae9d3e4dfa64bd1 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 21 Feb 2024 13:40:36 -0600 Subject: [PATCH 01/18] wip: add clover provider --- src/Clover/CloverExtendSocialite.php | 18 ++++++ src/Clover/Provider.php | 94 ++++++++++++++++++++++++++++ src/Clover/README.md | 43 +++++++++++++ src/Clover/composer.json | 21 +++++++ 4 files changed, 176 insertions(+) create mode 100644 src/Clover/CloverExtendSocialite.php create mode 100644 src/Clover/Provider.php create mode 100644 src/Clover/README.md create mode 100644 src/Clover/composer.json diff --git a/src/Clover/CloverExtendSocialite.php b/src/Clover/CloverExtendSocialite.php new file mode 100644 index 000000000..bd7ba45a7 --- /dev/null +++ b/src/Clover/CloverExtendSocialite.php @@ -0,0 +1,18 @@ +extendSocialite('clover', Provider::class); + } +} diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php new file mode 100644 index 000000000..097dc157d --- /dev/null +++ b/src/Clover/Provider.php @@ -0,0 +1,94 @@ +getConfig('environment') !== 'production'; + } + + /** + * {@inheritdoc} + */ + protected function getAuthUrl($state) + { + $domain = match ($this->useSandbox()) { + 'sandbox' => 'sandbox.dev.clover.com', + default => 'www.clover.com', + }; + + return $this->buildAuthUrlFromBase('https://'.$domain.'/oauth/v2/authorize', $state); + } + + /** + * {@inheritdoc} + */ + protected function getTokenUrl() + { + $domain = match ($this->useSandbox()) { + 'sandbox' => 'apisandbox.dev.clover.com', + default => 'api.clover.com', + }; + + return 'https://'.$domain.'/oauth/token'; + } + + /** + * {@inheritdoc} + */ + protected function getUserByToken($token) + { + $response = $this->getHttpClient()->get('', [ + 'headers' => [ + 'Authorization' => 'Bearer '.$token, + ], + ]); + + return json_decode($response->getBody(), true); + } + + /** + * {@inheritdoc} + */ + protected function mapUserToObject(array $user) + { + return (new User())->setRaw($user)->map([ + 'id' => $user['id'], + 'nickname' => $user['username'], + 'name' => $user['name'], + 'email' => $user['email'], + 'avatar' => $user['avatar'], + ]); + } + + /** + * {@inheritdoc} + */ + protected function getTokenFields($code) + { + return array_merge(parent::getTokenFields($code), [ + 'grant_type' => 'authorization_code' + ]); + } +} diff --git a/src/Clover/README.md b/src/Clover/README.md new file mode 100644 index 000000000..636f2afff --- /dev/null +++ b/src/Clover/README.md @@ -0,0 +1,43 @@ +# Clover + +```bash +composer require socialiteproviders/clover +``` + +## Installation & Basic Usage + +Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), then follow the provider specific instructions below. + +### Add configuration to `config/services.php` + +```php +'clover' => [ + 'client_id' => env('CLOVER_CLIENT_ID'), + 'client_secret' => env('CLOVER_CLIENT_SECRET'), + 'redirect' => env('CLOVER_REDIRECT_URI') + 'mode' => env('CLOVER_ENVIRONMENT', 'production'), +], +``` + +### Add provider event listener + +Configure the package's listener to listen for `SocialiteWasCalled` events. + +Add the event to your `listen[]` array in `app/Providers/EventServiceProvider`. See the [Base Installation Guide](https://socialiteproviders.com/usage/) for detailed instructions. + +```php +protected $listen = [ + \SocialiteProviders\Manager\SocialiteWasCalled::class => [ + // ... other providers + 'SocialiteProviders\\Clover\\CloverExtendSocialite@handle', + ], +]; +``` + +### Usage + +You should now be able to use the provider like you would regularly use Socialite (assuming you have the facade installed): + +```php +return Socialite::driver('clover')->redirect(); +``` diff --git a/src/Clover/composer.json b/src/Clover/composer.json new file mode 100644 index 000000000..0a1e4c0ca --- /dev/null +++ b/src/Clover/composer.json @@ -0,0 +1,21 @@ +{ + "name": "socialiteproviders/clover", + "description": "Clover OAuth2 Provider for Laravel Socialite", + "license": "MIT", + "authors": [ + { + "name": "macbookandrew", + "homepage": "https://andrewrminion.com" + } + ], + "require": { + "php": "^8.0", + "ext-json": "*", + "socialiteproviders/manager": "^4.0" + }, + "autoload": { + "psr-4": { + "SocialiteProviders\\Clover\\": "" + } + } +} From c26c0a39929dbaf7a2bebe16ae74fb7b2afa2bc6 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 21 Feb 2024 13:43:01 -0600 Subject: [PATCH 02/18] add clover to subtree split --- monorepo-builder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/monorepo-builder.yml b/monorepo-builder.yml index 364ff82c9..7eda13aa1 100644 --- a/monorepo-builder.yml +++ b/monorepo-builder.yml @@ -30,6 +30,7 @@ parameters: src/Cheddar: 'git@github.com:SocialiteProviders/Cheddar.git' src/ClaveUnica: 'git@github.com:SocialiteProviders/ClaveUnica.git' src/Clerk: 'git@github.com:SocialiteProviders/Clerk.git' + src/Clover: 'git@github.com:SocialiteProviders/Clover.git' src/Cognito: 'git@github.com:SocialiteProviders/Cognito.git' src/Coinbase: 'git@github.com:SocialiteProviders/Coinbase.git' src/ConstantContact: 'git@github.com:SocialiteProviders/ConstantContact.git' From 7d157f8d5274ce7f3bd212297fdf6a72ab2d6556 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:30:02 -0600 Subject: [PATCH 03/18] fix sandbox vs. production mode --- src/Clover/Provider.php | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 097dc157d..552fba2ae 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -18,14 +18,18 @@ class Provider extends AbstractProvider protected $scopes = ['']; /** - * Tests whether we are integrating to the Clover sandbox or production environments - * Change the value of CLOVER_ENVIRONMENT in your .env to switch. + * Indicates if the session state should be utilized. * - * @return bool + * @var bool */ - protected function useSandbox() + protected $stateless = true; + + protected function getApiDomain(): string { - return $this->getConfig('environment') !== 'production'; + return match (true) { + config('services.clover.sandbox-mode') => 'sandbox.dev.clover.com', + default => 'www.clover.com', + }; } /** @@ -33,12 +37,7 @@ protected function useSandbox() */ protected function getAuthUrl($state) { - $domain = match ($this->useSandbox()) { - 'sandbox' => 'sandbox.dev.clover.com', - default => 'www.clover.com', - }; - - return $this->buildAuthUrlFromBase('https://'.$domain.'/oauth/v2/authorize', $state); + return $this->buildAuthUrlFromBase('https://'.$this->getApiDomain().'/oauth/v2/authorize', $state); } /** @@ -46,12 +45,16 @@ protected function getAuthUrl($state) */ protected function getTokenUrl() { - $domain = match ($this->useSandbox()) { - 'sandbox' => 'apisandbox.dev.clover.com', + $domain = match (true) { + config('services.clover.sandbox-mode') => 'apisandbox.dev.clover.com', default => 'api.clover.com', }; - return 'https://'.$domain.'/oauth/token'; + return 'https://'.$domain.'/oauth/token?'.Arr::query([ + 'client_id' => config('services.clover.client_id'), + 'client_secret' => config('services.clover.client_secret'), + 'code' => $this->getCode(), + ]); } /** From 23dc185065631fb12a7de73158c912107a2e0b89 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:30:20 -0600 Subject: [PATCH 04/18] get employee ID data --- src/Clover/Provider.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 552fba2ae..ca4761105 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -2,6 +2,8 @@ namespace SocialiteProviders\Clover; +use GuzzleHttp\RequestOptions; +use Illuminate\Support\Arr; use SocialiteProviders\Manager\OAuth2\AbstractProvider; use SocialiteProviders\Manager\OAuth2\User; @@ -62,7 +64,12 @@ protected function getTokenUrl() */ protected function getUserByToken($token) { - $response = $this->getHttpClient()->get('', [ + $requestParams = str(request()->fullUrl()) + ->after('?') + ->explode('&') + ->mapWithKeys(fn (string $keyAndValue) => [str($keyAndValue)->before('=')->toString() => str($keyAndValue)->after('=')->toString()]); + + $response = $this->getHttpClient()->get('https://'.$this->getApiDomain().'/v3/merchants/'.$requestParams['merchant_id'].'/employees/'.$requestParams['employee_id'], [ 'headers' => [ 'Authorization' => 'Bearer '.$token, ], @@ -77,11 +84,11 @@ protected function getUserByToken($token) protected function mapUserToObject(array $user) { return (new User())->setRaw($user)->map([ - 'id' => $user['id'], - 'nickname' => $user['username'], - 'name' => $user['name'], - 'email' => $user['email'], - 'avatar' => $user['avatar'], + 'id' => $user['id'], + 'nickname' => $user['name'], + 'name' => $user['name'], + 'email' => $user['email'], + 'avatar' => null, ]); } From 50b5054c2e47e80ae66e1c900d597e8c9b8c15ea Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:30:32 -0600 Subject: [PATCH 05/18] retrieve the access token from the auth flow --- src/Clover/Provider.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index ca4761105..e97ac449d 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -93,12 +93,17 @@ protected function mapUserToObject(array $user) } /** - * {@inheritdoc} + * Get the access token response for the given code. + * + * @param string $code + * @return array */ - protected function getTokenFields($code) + public function getAccessTokenResponse($code) { - return array_merge(parent::getTokenFields($code), [ - 'grant_type' => 'authorization_code' + $response = $this->getHttpClient()->get($this->getTokenUrl(), [ + RequestOptions::HEADERS => $this->getTokenHeaders($code), ]); + + return json_decode($response->getBody(), true); } } From dc558984b9bd05de7fb7c4c1083eeecc85be00cc Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:31:25 -0600 Subject: [PATCH 06/18] update sandbox mode docs --- src/Clover/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clover/README.md b/src/Clover/README.md index 636f2afff..d809c806a 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -15,7 +15,7 @@ Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), 'client_id' => env('CLOVER_CLIENT_ID'), 'client_secret' => env('CLOVER_CLIENT_SECRET'), 'redirect' => env('CLOVER_REDIRECT_URI') - 'mode' => env('CLOVER_ENVIRONMENT', 'production'), + 'sandbox-mode' => env('CLOVER_SANDBOX_MODE', false), ], ``` From 53a23b86f0a52d8095aeafed69c4fbbac5de4ee3 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:31:53 -0600 Subject: [PATCH 07/18] add authorization doc --- src/Clover/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Clover/README.md b/src/Clover/README.md index d809c806a..69864d343 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -8,6 +8,8 @@ composer require socialiteproviders/clover Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), then follow the provider specific instructions below. +Ensure the app has permission to read employees. + ### Add configuration to `config/services.php` ```php From 4abf0c1dc21eeca125f30a9a3558f21c859c410a Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 27 Feb 2024 16:35:14 -0600 Subject: [PATCH 08/18] add docs about API token --- src/Clover/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Clover/README.md b/src/Clover/README.md index 69864d343..dc37eb7dd 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -43,3 +43,16 @@ You should now be able to use the provider like you would regularly use Socialit ```php return Socialite::driver('clover')->redirect(); ``` + +Presumably you are using this OAuth provider in order to retrieve an API token for calling other API endpoints. + +The user includes a `token` property that you can use to retrieve the API token like this: + +```php +Route::get('clover/auth/callback', function () { + $user = Socialite::driver('clover')->user(); + + // Save this token somewhere for other use. + $token = $user->token; +}); +``` From bb6a5be26746034ab13fd95a2380c12960afae1f Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 28 Feb 2024 11:01:57 -0600 Subject: [PATCH 09/18] use class constant --- src/Clover/CloverExtendSocialite.php | 7 +------ src/Clover/Provider.php | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Clover/CloverExtendSocialite.php b/src/Clover/CloverExtendSocialite.php index bd7ba45a7..32476227e 100644 --- a/src/Clover/CloverExtendSocialite.php +++ b/src/Clover/CloverExtendSocialite.php @@ -6,13 +6,8 @@ class CloverExtendSocialite { - /** - * Register the provider. - * - * @param \SocialiteProviders\Manager\SocialiteWasCalled $socialiteWasCalled - */ public function handle(SocialiteWasCalled $socialiteWasCalled) { - $socialiteWasCalled->extendSocialite('clover', Provider::class); + $socialiteWasCalled->extendSocialite(Provider::IDENTIFIER, Provider::class); } } diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index e97ac449d..02186e7da 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -12,7 +12,7 @@ class Provider extends AbstractProvider /** * Unique Provider Identifier. */ - const IDENTIFIER = 'CLOVER'; + const IDENTIFIER = 'clover'; /** * {@inheritdoc} From 89575dcb8dec41923c9d8dddd0fb6a71093103c8 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 28 Feb 2024 11:02:22 -0600 Subject: [PATCH 10/18] clean up code --- src/Clover/Provider.php | 66 +++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 02186e7da..548d5b467 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -2,8 +2,6 @@ namespace SocialiteProviders\Clover; -use GuzzleHttp\RequestOptions; -use Illuminate\Support\Arr; use SocialiteProviders\Manager\OAuth2\AbstractProvider; use SocialiteProviders\Manager\OAuth2\User; @@ -17,7 +15,7 @@ class Provider extends AbstractProvider /** * {@inheritdoc} */ - protected $scopes = ['']; + protected $scopes = []; /** * Indicates if the session state should be utilized. @@ -26,11 +24,18 @@ class Provider extends AbstractProvider */ protected $stateless = true; + public static function additionalConfigKeys() + { + return [ + 'environment', + ]; + } + protected function getApiDomain(): string { - return match (true) { - config('services.clover.sandbox-mode') => 'sandbox.dev.clover.com', - default => 'www.clover.com', + return match ($this->getConfig('environment')) { + 'sandbox' => 'sandbox.dev.clover.com', + default => 'www.clover.com', }; } @@ -39,7 +44,10 @@ protected function getApiDomain(): string */ protected function getAuthUrl($state) { - return $this->buildAuthUrlFromBase('https://'.$this->getApiDomain().'/oauth/v2/authorize', $state); + return $this->buildAuthUrlFromBase( + sprintf('https://%s/oauth/v2/authorize', $this->getApiDomain()), + $state + ); } /** @@ -47,16 +55,12 @@ protected function getAuthUrl($state) */ protected function getTokenUrl() { - $domain = match (true) { - config('services.clover.sandbox-mode') => 'apisandbox.dev.clover.com', - default => 'api.clover.com', + $domain = match ($this->getConfig('environment')) { + 'sandbox' => 'apisandbox.dev.clover.com', + default => 'api.clover.com', }; - return 'https://'.$domain.'/oauth/token?'.Arr::query([ - 'client_id' => config('services.clover.client_id'), - 'client_secret' => config('services.clover.client_secret'), - 'code' => $this->getCode(), - ]); + return sprintf('https://%s/oauth/token', $domain); } /** @@ -69,13 +73,18 @@ protected function getUserByToken($token) ->explode('&') ->mapWithKeys(fn (string $keyAndValue) => [str($keyAndValue)->before('=')->toString() => str($keyAndValue)->after('=')->toString()]); - $response = $this->getHttpClient()->get('https://'.$this->getApiDomain().'/v3/merchants/'.$requestParams['merchant_id'].'/employees/'.$requestParams['employee_id'], [ + $response = $this->getHttpClient()->get(sprintf( + 'https://%s/v3/merchants/%s/employees/%s', + $this->getApiDomain(), + $requestParams['merchant_id'], + $requestParams['employee_id'], + ), [ 'headers' => [ 'Authorization' => 'Bearer '.$token, ], ]); - return json_decode($response->getBody(), true); + return json_decode((string) $response->getBody(), true); } /** @@ -84,26 +93,11 @@ protected function getUserByToken($token) protected function mapUserToObject(array $user) { return (new User())->setRaw($user)->map([ - 'id' => $user['id'], + 'id' => $user['id'], 'nickname' => $user['name'], - 'name' => $user['name'], - 'email' => $user['email'], - 'avatar' => null, - ]); - } - - /** - * Get the access token response for the given code. - * - * @param string $code - * @return array - */ - public function getAccessTokenResponse($code) - { - $response = $this->getHttpClient()->get($this->getTokenUrl(), [ - RequestOptions::HEADERS => $this->getTokenHeaders($code), + 'name' => $user['name'], + 'email' => $user['email'], + 'avatar' => null, ]); - - return json_decode($response->getBody(), true); } } From c9a9ba1eeaa33800a0d43c3f608d229f44f8aa73 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 28 Feb 2024 11:03:05 -0600 Subject: [PATCH 11/18] update PHP dependency --- src/Clover/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clover/composer.json b/src/Clover/composer.json index 0a1e4c0ca..b64340f4c 100644 --- a/src/Clover/composer.json +++ b/src/Clover/composer.json @@ -9,7 +9,7 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "ext-json": "*", "socialiteproviders/manager": "^4.0" }, From 623d1dcf15bc6b9197a978b0333d30cd4c252514 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Wed, 28 Feb 2024 11:05:20 -0600 Subject: [PATCH 12/18] update docs --- src/Clover/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clover/README.md b/src/Clover/README.md index dc37eb7dd..299514d08 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -17,7 +17,7 @@ Ensure the app has permission to read employees. 'client_id' => env('CLOVER_CLIENT_ID'), 'client_secret' => env('CLOVER_CLIENT_SECRET'), 'redirect' => env('CLOVER_REDIRECT_URI') - 'sandbox-mode' => env('CLOVER_SANDBOX_MODE', false), + 'environment' => env('CLOVER_ENVIRONMENT', 'production'), ], ``` From f831461f027e3afd4d378fc4e3eb113be9d7020a Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:12:36 -0600 Subject: [PATCH 13/18] use correct token endpoint --- src/Clover/Provider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 548d5b467..9bd1dfa48 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -60,7 +60,7 @@ protected function getTokenUrl() default => 'api.clover.com', }; - return sprintf('https://%s/oauth/token', $domain); + return sprintf('https://%s/oauth/v2/token', $domain); } /** From 8b006bb7770b0524b725a9b8eb9fa9a51ea47039 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:12:51 -0600 Subject: [PATCH 14/18] fix code stye --- src/Clover/Provider.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 9bd1dfa48..5105f4928 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -35,7 +35,7 @@ protected function getApiDomain(): string { return match ($this->getConfig('environment')) { 'sandbox' => 'sandbox.dev.clover.com', - default => 'www.clover.com', + default => 'www.clover.com', }; } @@ -57,7 +57,7 @@ protected function getTokenUrl() { $domain = match ($this->getConfig('environment')) { 'sandbox' => 'apisandbox.dev.clover.com', - default => 'api.clover.com', + default => 'api.clover.com', }; return sprintf('https://%s/oauth/v2/token', $domain); @@ -93,11 +93,11 @@ protected function getUserByToken($token) protected function mapUserToObject(array $user) { return (new User())->setRaw($user)->map([ - 'id' => $user['id'], + 'id' => $user['id'], 'nickname' => $user['name'], - 'name' => $user['name'], - 'email' => $user['email'], - 'avatar' => null, + 'name' => $user['name'], + 'email' => $user['email'], + 'avatar' => null, ]); } } From 7ffadffe70c51aa77fc9255d304ab733d43b4996 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:13:22 -0600 Subject: [PATCH 15/18] get access token response using JSON instead of form params --- src/Clover/Provider.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 5105f4928..5f5789853 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -2,6 +2,7 @@ namespace SocialiteProviders\Clover; +use GuzzleHttp\RequestOptions; use SocialiteProviders\Manager\OAuth2\AbstractProvider; use SocialiteProviders\Manager\OAuth2\User; @@ -31,6 +32,22 @@ public static function additionalConfigKeys() ]; } + /** + * Get the access token response for the given code. + * + * @param string $code + * @return array + */ + public function getAccessTokenResponse($code) + { + $response = $this->getHttpClient()->post($this->getTokenUrl(), [ + RequestOptions::HEADERS => $this->getTokenHeaders($code), + RequestOptions::JSON => $this->getTokenFields($code), + ]); + + return json_decode($response->getBody(), true); + } + protected function getApiDomain(): string { return match ($this->getConfig('environment')) { From 4d27e6fb8f5b6786ace48993da9bb4041b56669d Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:13:37 -0600 Subject: [PATCH 16/18] =?UTF-8?q?parse=20expiration=20timestamp=20to=20Soc?= =?UTF-8?q?ialite=E2=80=99s=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Clover/Provider.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index 5f5789853..c71144aa1 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -3,6 +3,7 @@ namespace SocialiteProviders\Clover; use GuzzleHttp\RequestOptions; +use Illuminate\Support\Arr; use SocialiteProviders\Manager\OAuth2\AbstractProvider; use SocialiteProviders\Manager\OAuth2\User; @@ -117,4 +118,15 @@ protected function mapUserToObject(array $user) 'avatar' => null, ]); } + + /** + * Get the expires in from the token response body. + * + * @param array $body + * @return string + */ + protected function parseExpiresIn($body) + { + return (string) (Arr::get($body, 'access_token_expiration') - time()); + } } From 6f8a74759ccee20e4e018896b6f9be41f0dcf4ed Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:13:46 -0600 Subject: [PATCH 17/18] update docs --- src/Clover/README.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Clover/README.md b/src/Clover/README.md index 299514d08..e0a258cb3 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -52,7 +52,21 @@ The user includes a `token` property that you can use to retrieve the API token Route::get('clover/auth/callback', function () { $user = Socialite::driver('clover')->user(); - // Save this token somewhere for other use. - $token = $user->token; + // Save these tokens somewhere for use with the API. + $token = $user->accessTokenResponseBody; + + // Here’s what it looks like: + // [ + // 'access_token' => 'JWT', + // 'access_token_expiration' => 1709563149, + // 'refresh_token' => 'clvroar-6e49ffe9b5122f137aa39d8f7f930558', + // 'refresh_token_expiration' => 1741097349, + // ] + + // You may also want to store the merchant ID somewhere. + $merchantId = request()->input('merchant_id'); + + // Here’s what it looks like: + // 'ABC123DEF4567' }); ``` From 9bfa67e374df9eb7d30460d9afa1ad8d9c820ac4 Mon Sep 17 00:00:00 2001 From: Andrew Minion Date: Tue, 5 Mar 2024 14:20:55 -0600 Subject: [PATCH 18/18] add some suggested changes from #1162 --- src/Clover/CloverExtendSocialite.php | 2 +- src/Clover/Provider.php | 18 ++++++------------ src/Clover/README.md | 2 +- src/Clover/composer.json | 14 +++++++++++++- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Clover/CloverExtendSocialite.php b/src/Clover/CloverExtendSocialite.php index 32476227e..a740ab060 100644 --- a/src/Clover/CloverExtendSocialite.php +++ b/src/Clover/CloverExtendSocialite.php @@ -6,7 +6,7 @@ class CloverExtendSocialite { - public function handle(SocialiteWasCalled $socialiteWasCalled) + public function handle(SocialiteWasCalled $socialiteWasCalled): void { $socialiteWasCalled->extendSocialite(Provider::IDENTIFIER, Provider::class); } diff --git a/src/Clover/Provider.php b/src/Clover/Provider.php index c71144aa1..f1c7a93bc 100644 --- a/src/Clover/Provider.php +++ b/src/Clover/Provider.php @@ -26,7 +26,7 @@ class Provider extends AbstractProvider */ protected $stateless = true; - public static function additionalConfigKeys() + public static function additionalConfigKeys(): array { return [ 'environment', @@ -37,9 +37,8 @@ public static function additionalConfigKeys() * Get the access token response for the given code. * * @param string $code - * @return array */ - public function getAccessTokenResponse($code) + public function getAccessTokenResponse($code): array { $response = $this->getHttpClient()->post($this->getTokenUrl(), [ RequestOptions::HEADERS => $this->getTokenHeaders($code), @@ -60,7 +59,7 @@ protected function getApiDomain(): string /** * {@inheritdoc} */ - protected function getAuthUrl($state) + protected function getAuthUrl($state): string { return $this->buildAuthUrlFromBase( sprintf('https://%s/oauth/v2/authorize', $this->getApiDomain()), @@ -71,7 +70,7 @@ protected function getAuthUrl($state) /** * {@inheritdoc} */ - protected function getTokenUrl() + protected function getTokenUrl(): string { $domain = match ($this->getConfig('environment')) { 'sandbox' => 'apisandbox.dev.clover.com', @@ -86,16 +85,11 @@ protected function getTokenUrl() */ protected function getUserByToken($token) { - $requestParams = str(request()->fullUrl()) - ->after('?') - ->explode('&') - ->mapWithKeys(fn (string $keyAndValue) => [str($keyAndValue)->before('=')->toString() => str($keyAndValue)->after('=')->toString()]); - $response = $this->getHttpClient()->get(sprintf( 'https://%s/v3/merchants/%s/employees/%s', $this->getApiDomain(), - $requestParams['merchant_id'], - $requestParams['employee_id'], + $this->request->query('merchant_id'), + $this->request->query('employee_id'), ), [ 'headers' => [ 'Authorization' => 'Bearer '.$token, diff --git a/src/Clover/README.md b/src/Clover/README.md index e0a258cb3..34284703b 100644 --- a/src/Clover/README.md +++ b/src/Clover/README.md @@ -31,7 +31,7 @@ Add the event to your `listen[]` array in `app/Providers/EventServiceProvider`. protected $listen = [ \SocialiteProviders\Manager\SocialiteWasCalled::class => [ // ... other providers - 'SocialiteProviders\\Clover\\CloverExtendSocialite@handle', + \SocialiteProviders\Clover\CloverExtendSocialite::class.'@handle', ], ]; ``` diff --git a/src/Clover/composer.json b/src/Clover/composer.json index b64340f4c..ba5746806 100644 --- a/src/Clover/composer.json +++ b/src/Clover/composer.json @@ -2,16 +2,28 @@ "name": "socialiteproviders/clover", "description": "Clover OAuth2 Provider for Laravel Socialite", "license": "MIT", + "keywords": [ + "clover", + "laravel", + "oauth", + "provider", + "socialite" + ], "authors": [ { "name": "macbookandrew", "homepage": "https://andrewrminion.com" } ], + "support": { + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers", + "docs": "https://socialiteproviders.com/clover" + }, "require": { "php": "^8.1", "ext-json": "*", - "socialiteproviders/manager": "^4.0" + "socialiteproviders/manager": "^4.4" }, "autoload": { "psr-4": {