Skip to content

Commit

Permalink
initialize commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pooryasadidi6868 committed Nov 22, 2020
0 parents commit 7d22e2e
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 0 deletions.
141 changes: 141 additions & 0 deletions Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace PooryaSadidi\ZarinPal;

use Illuminate\Support\Arr;
use Predis\ClientException;
use SocialiteProviders\Manager\OAuth2\AbstractProvider;
use SocialiteProviders\Manager\OAuth2\User;

class Provider extends AbstractProvider
{
/**
* Unique Provider Identifier.
*/
public const IDENTIFIER = 'ZARINPAL';

/**
* {@inheritdoc}
*/
protected $scopes = ['user.read'];

/**
* {@inherticdoc}.
*/
protected $scopeSeparator = ' ';


/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://next.zarinpal.com/api/oauth/authorizeInit', $state);
}


// protected function buildAuthUrlFromBase($url, $state)
// {
// return $url.'?'.http_build_query($this->getCodeFields($state));
// }

protected function getCodeFields($state = null)
{
$fields = [
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUrl,
'scope' => $this->formatScopes($this->getScopes(), $this->scopeSeparator),
'response_type' => 'code',
];

if ($this->usesState()) {
$fields['state'] = $state;
}
$verifier = ($this->isStateless()) ? \Illuminate\Support\Str::random(128) : $this->request->session()->pull('code_verifier');
$fields['code_challenge'] = $this->getCodeChallenge($verifier);
$fields['code_challenge_method'] = $this->getCodeChallengeMethod();
$fields['state'] = $verifier;

return array_merge($fields, $this->parameters);
}


protected function getCodeChallenge($verifier)
{

$hashed = hash('sha256', $verifier, true);
return rtrim(strtr(base64_encode($hashed), '+/', '-_'), '='); // base64-URL-encoding
}

protected function getCodeChallengeMethod()
{
return 'S256';
}

/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return 'https://next.zarinpal.com/api/oauth/token';
}

/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$graphQLquery = include('Query.php');
$response = $this->getHttpClient()->post('https://next.zarinpal.com/api/v4/graphql',
[
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $token,
],
'form_params' => $graphQLquery
]);



return json_decode($response->getBody(), true);
}

/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
$user = $user['data']['Me'];
return (new User)->setRaw($user)->map([
'id' => $user['id'],
'full_name' => $user['full_name'],
'phone' => $user['cell_number'],
'avatar' => $user['avatar'],
]);
}

/**
* {@inheritdoc}
*/
protected function getTokenFields($code)
{
return [
'grant_type' => 'authorization_code',
'client_id' => $this->clientId,
'code_verifier' => request()->input('state'),
'code' => $code,
'redirect_uri' => $this->redirectUrl,
];
}

public function getAccessTokenResponse($code)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
'form_params' => $this->getTokenFields($code),
]);

return json_decode($response->getBody(), true);
}

}
14 changes: 14 additions & 0 deletions Query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
return [
'operationName' => null,
'query' => '{ Me {
id
avatar
full_name
cell_number
}
}',
'variables' => null
];


51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# ZarinPal

```bash
composer require pooryasadidi/socialite-zarinpal
```

## 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
'zarinpal' => [
'client_id' => env('ZARINPAL_CLIENT_ID'),
'client_secret' => env('ZARINPAL_CLIENT_SECRET'),
'redirect' => env('ZARINPAL_REDIRECT_URI')
],
```

### 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
'PooryaSadidi\\ZarinPal\\ZarinPalExtendSocialite@handle',
],
];
```

### Usage

this package just test in stateless 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('zarinpal')->stateless()->redirect();
return Socialite::driver('zarinpal')->stateless()->user();
```

### Returned User fields

- ``id``
- ``fullname``
- ``phone``
- ``avatar``
18 changes: 18 additions & 0 deletions ZarinPalExtendSocialite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace PooryaSadidi\ZarinPal;

use SocialiteProviders\Manager\SocialiteWasCalled;

class ZarinPalExtendSocialite
{
/**
* Register the provider.
*
* @param \SocialiteProviders\Manager\SocialiteWasCalled $socialiteWasCalled
*/
public function handle(SocialiteWasCalled $socialiteWasCalled)
{
$socialiteWasCalled->extendSocialite('zarinpal', Provider::class);
}
}
21 changes: 21 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "pooryasadidi/socialite-zarinpal",
"description": "ZarinPal OAuth2 Provider for Laravel Socialite",
"license": "MIT",
"authors": [
{
"name": "Poorya Sadidi",
"email": "pooryasadidi6868@gmail.com"
}
],
"require": {
"php": "^7.2",
"ext-json": "*",
"socialiteproviders/manager": "~4.0"
},
"autoload": {
"psr-4": {
"PooryaSadidi\\ZarinPal\\": ""
}
}
}

0 comments on commit 7d22e2e

Please sign in to comment.