1f991/patreon-php

View on GitHub
src/Patreon/OAuth.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php declare(strict_types=1);

namespace Squid\Patreon;

use Http\Client\HttpClient;
use Http\Discovery\HttpClientDiscovery;
use Http\Discovery\MessageFactoryDiscovery;
use Psr\Http\Message\RequestInterface;
use Squid\Patreon\Exceptions\OAuthReturnedError;
use Squid\Patreon\Exceptions\OAuthScopesAreInvalid;

class OAuth
{
    /**
    * Valid OAuth scopes supported by Patreon.
    *
    * @var array
    */
    const OAUTH_SCOPES = [
        'users',
        'pledges-to-me',
        'my-campaign'
    ];

    /**
     * Constructs a new OAuth client.
     *
     * @param string     $clientId     Patreon Platform Client ID
     * @param string     $clientSecret Patreon Platform Client Secret
     * @param string     $redirectUri  Whitelisted Client Redirect URI
     * @param HttpClient $httpClient   Http Client
     *
     * @return void
     */
    public function __construct(
        string $clientId,
        string $clientSecret,
        string $redirectUri,
        ?HttpClient $httpClient = null
    ) {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
        $this->redirectUri = $redirectUri;
        $this->httpClient = $httpClient ?: HttpClientDiscovery::find();
    }

    /**
     * Get an Authorization URL to redirect the user to.
     *
     * @param array $scope Array of valid scopes
     *
     * @return string
     */
    public function getAuthorizationUrl(
        array $scope = ['users', 'pledges-to-me', 'my-campaign']
    ): string {
        if ($invalid = array_diff($scope, self::OAUTH_SCOPES)) {
            throw OAuthScopesAreInvalid::scopes($invalid, self::OAUTH_SCOPES);
        }

        $query = http_build_query(
            [
            'response_type' => 'code',
            'client_id' => $this->clientId,
            'redirect_uri' => $this->redirectUri,
            'scope' => implode(' ', $scope),
            ]
        );

        return 'https://www.patreon.com/oauth2/authorize?' . $query;
    }

    /**
     * Get an Access Token from the user's OAuth code.
     *
     * @param string $code OAuth authorized_code
     *
     * @return array
     */
    public function getAccessToken(string $code): array
    {
        return $this->sendTokenRequest(
            [
            'code' => $code,
            'grant_type' => 'authorization_code',
            'redirect_uri' => $this->redirectUri,
            ]
        );
    }

    /**
     * Get a new Access Token using the user's Refresh Token.
     *
     * @param string $refreshToken User's Refresh Token
     *
     * @return array
     */
    public function getNewToken(string $refreshToken)
    {
        return $this->sendTokenRequest(
            [
            'grant_type' => 'refresh_token',
            'refresh_token' => $refreshToken,
            ]
        );
    }

    /**
     * Send a request to the Patreon OAuth token endpoint.
     *
     * @param array $parameters Parameters to include in the request.
     *
     * @return array
     */
    protected function sendTokenRequest(array $parameters): array
    {
        $parameters = array_merge(
            $parameters,
            [
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            ]
        );

        $response = $this->httpClient->sendRequest(
            $this->createTokenRequest($parameters)
        );

        $result = json_decode((string) $response->getBody());

        if ($result->error ?? false) {
            throw OAuthReturnedError::error($result->error);
        }

        return [
            'access_token' => $result->access_token,
            'refresh_token' => $result->refresh_token,
            'expires_in' => $result->expires_in,
            'scope' => $result->scope,
            'token_type' => $result->token_type
        ];
    }

    /**
     * Creates a Token Request.
     *
     * @param array $parameters Token request parameters.
     *
     * @return \Psr\Http\Message\RequestInterface
     */
    protected function createTokenRequest($parameters): RequestInterface
    {
        return MessageFactoryDiscovery::find()->createRequest(
            'POST',
            'https://api.patreon.com/oauth2/token',
            [
                'Content-Type'  => 'application/x-www-form-urlencoded',
                'Accept'        => 'application/json',
                'User-Agent'    => '1f991/patreon-php'
            ],
            http_build_query($parameters)
        );
    }
}