diff --git a/README.md b/README.md index 2eebab78..762c2754 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ Included service implementations - Mailchimp - Microsoft - Mondo + - MYOB - Nest - Netatmo - Parrot Flower Power diff --git a/examples/init.example.php b/examples/init.example.php index 6ab1cdb0..b81ca23b 100644 --- a/examples/init.example.php +++ b/examples/init.example.php @@ -123,6 +123,10 @@ 'key' => '', 'secret' => '', ), + 'myob' => array( + 'key' => '', + 'secret' => '', + ), 'nest' => array( 'key' => '', 'secret' => '', diff --git a/examples/myob.php b/examples/myob.php new file mode 100644 index 00000000..b753f3e3 --- /dev/null +++ b/examples/myob.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012 The authors + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use OAuth\Common\Storage\Session; +use OAuth\Common\Consumer\Credentials; + +/** + * Bootstrap the example + */ +require_once __DIR__ . '/bootstrap.php'; + +// Session storage +$storage = new Session(); + +// Setup the credentials for the requests +$credentials = new Credentials( + $servicesCredentials['myob']['key'], + $servicesCredentials['myob']['secret'], + $currentUri->getAbsoluteUri() +); + +// Instantiate MYOB service using the credentials, http client, storage mechanism for the token and profile scope +/** @var OAuth\OAuth2\Service\Myob $myobService */ +$myobService = $serviceFactory->createService('myob', $credentials, $storage, + array(\OAuth\OAuth2\Service\Myob::SCOPE_COMPANYFILE)); + +if (!empty($_GET['code'])) { + // This was a callback request from MYOB, get the token + $token = $myobService->requestAccessToken($_GET['code']); + +} elseif (!empty($_GET['go']) && $_GET['go'] === 'go') { + $url = $myobService->getAuthorizationUri(); + header('Location: ' . $url); +} else { + $url = $currentUri->getRelativeUri() . '?go=go'; + echo "Login with MYOB!"; +} diff --git a/src/OAuth/OAuth2/Service/Myob.php b/src/OAuth/OAuth2/Service/Myob.php new file mode 100644 index 00000000..521c5c2c --- /dev/null +++ b/src/OAuth/OAuth2/Service/Myob.php @@ -0,0 +1,97 @@ +setAccessToken($data['access_token']); + $token->setLifeTime($data['expires_in']); + + if (isset($data['refresh_token'])) { + $token->setRefreshToken($data['refresh_token']); + unset($data['refresh_token']); + } + + unset($data['access_token']); + unset($data['expires_in']); + + $token->setExtraParams($data); + + return $token; + } + + /** + * @inheritdoc + */ + public function requestAccessToken($code, $state = null) + { + if (null !== $state) { + $this->validateAuthorizationState($state); + } + + $bodyParams = array( + 'code' => $code, + 'client_id' => $this->credentials->getConsumerId(), + 'client_secret' => $this->credentials->getConsumerSecret(), + 'redirect_uri' => $this->credentials->getCallbackUrl(), + 'grant_type' => 'authorization_code', + 'scope' => implode(' ', $this->scopes), + ); + + $responseBody = $this->httpClient->retrieveResponse( + $this->getAccessTokenEndpoint(), + $bodyParams, + $this->getExtraOAuthHeaders() + ); + + $token = $this->parseAccessTokenResponse($responseBody); + $this->storage->storeAccessToken($this->service(), $token); + + return $token; + } +} \ No newline at end of file diff --git a/tests/Unit/OAuth2/Service/MyobTest.php b/tests/Unit/OAuth2/Service/MyobTest.php new file mode 100644 index 00000000..a5ad125e --- /dev/null +++ b/tests/Unit/OAuth2/Service/MyobTest.php @@ -0,0 +1,190 @@ +getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'), + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\ServiceInterface', $service); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + */ + public function testConstructCorrectInstanceWithoutCustomUri() + { + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'), + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + */ + public function testConstructCorrectInstanceWithCustomUri() + { + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'), + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface'), + array(), + $this->getMock('\\OAuth\\Common\\Http\\Uri\\UriInterface') + ); + + $this->assertInstanceOf('\\OAuth\\OAuth2\\Service\\AbstractService', $service); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::getAuthorizationEndpoint + */ + public function testGetAuthorizationEndpoint() + { + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'), + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->assertSame('https://secure.myob.com/oauth2/account/authorize', + $service->getAuthorizationEndpoint()->getAbsoluteUri()); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::getAccessTokenEndpoint + */ + public function testGetAccessTokenEndpoint() + { + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'), + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->assertSame('https://secure.myob.com/oauth2/v1/authorize', + $service->getAccessTokenEndpoint()->getAbsoluteUri()); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::getAuthorizationMethod + */ + public function testGetAuthorizationMethod() + { + $client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'); + $client->expects($this->once())->method('retrieveResponse')->will($this->returnArgument(2)); + + $token = $this->getMock('\\OAuth\\OAuth2\\Token\\TokenInterface'); + $token->expects($this->once())->method('getEndOfLife')->will($this->returnValue(TokenInterface::EOL_NEVER_EXPIRES)); + $token->expects($this->once())->method('getAccessToken')->will($this->returnValue('foo')); + + $storage = $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface'); + $storage->expects($this->once())->method('retrieveAccessToken')->will($this->returnValue($token)); + + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $client, + $storage + ); + + $headers = $service->request('https://pieterhordijk.com/my/awesome/path'); + + $this->assertTrue(array_key_exists('Authorization', $headers)); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::parseAccessTokenResponse + */ + public function testParseAccessTokenResponseThrowsExceptionOnNulledResponse() + { + $client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'); + $client->expects($this->once())->method('retrieveResponse')->will($this->returnValue(null)); + + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $client, + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException'); + + $service->requestAccessToken('foo'); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::parseAccessTokenResponse + */ + public function testParseAccessTokenResponseThrowsExceptionOnErrorDescription() + { + $client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'); + $client->expects($this->once())->method('retrieveResponse')->will($this->returnValue('error_description=some_error')); + + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $client, + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException'); + + $service->requestAccessToken('foo'); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::parseAccessTokenResponse + */ + public function testParseAccessTokenResponseThrowsExceptionOnError() + { + $client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'); + $client->expects($this->once())->method('retrieveResponse')->will($this->returnValue('error=some_error')); + + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $client, + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->setExpectedException('\\OAuth\\Common\\Http\\Exception\\TokenResponseException'); + + $service->requestAccessToken('foo'); + } + + /** + * @covers OAuth\OAuth2\Service\Myob::__construct + * @covers OAuth\OAuth2\Service\Myob::parseAccessTokenResponse + */ + public function testParseAccessTokenResponseValidWithoutRefreshToken() + { + $client = $this->getMock('\\OAuth\\Common\\Http\\Client\\ClientInterface'); + $client->expects($this->once())->method('retrieveResponse')->will($this->returnValue('{"access_token":"foo","expires_in":"bar"}')); + + $service = new Myob( + $this->getMock('\\OAuth\\Common\\Consumer\\CredentialsInterface'), + $client, + $this->getMock('\\OAuth\\Common\\Storage\\TokenStorageInterface') + ); + + $this->assertInstanceOf('\\OAuth\\OAuth2\\Token\\StdOAuth2Token', $service->requestAccessToken('foo')); + } +}