From 8b7f957fd30ea883248d6897215f945e17defaf8 Mon Sep 17 00:00:00 2001 From: James Seconde Date: Wed, 22 May 2024 16:09:24 +0100 Subject: [PATCH] Finished GNP Auth and SimSwap MVP implementation --- phpunit.xml.dist | 6 + src/Account/ClientFactory.php | 2 +- src/Application/ClientFactory.php | 2 +- src/Client.php | 4 + src/Client/APIResource.php | 29 ++-- src/Client/Credentials/Gnp.php | 25 +++ .../Credentials/Handler/AbstractHandler.php | 2 +- src/Client/Credentials/Handler/GnpHandler.php | 60 +++++++ src/Client/Credentials/Keypair.php | 7 - src/Client/ScopeAwareTrait.php | 25 +++ src/Conversion/ClientFactory.php | 2 +- src/Entity/IterableAPICollection.php | 2 +- src/Insights/ClientFactory.php | 2 +- src/Meetings/ClientFactory.php | 2 +- src/Messages/Client.php | 2 +- src/Messages/ClientFactory.php | 2 +- src/Numbers/ClientFactory.php | 2 +- src/Redact/ClientFactory.php | 2 +- src/SMS/ClientFactory.php | 2 +- src/SimSwap/Client.php | 62 +++++++ src/SimSwap/ClientFactory.php | 27 +++ src/Verify/ClientFactory.php | 2 +- src/Voice/ClientFactory.php | 2 +- test/Account/ClientTest.php | 20 +-- test/Application/ClientTest.php | 2 +- test/Client/APIResourceTest.php | 8 +- .../Fixtures/Responses/gnp-be-success.json | 5 + .../Fixtures/Responses/gnp-token-success.json | 5 + .../Credentials/Handler/GnpHandlerTest.php | 164 ++++++++++++++++++ test/Conversion/ClientTest.php | 2 +- test/Insights/AdvancedTest.php | 2 +- test/Insights/ClientTest.php | 6 +- test/Meetings/ClientTest.php | 26 +-- test/Messages/ClientTest.php | 2 +- test/Numbers/ClientTest.php | 16 +- test/ProactiveConnect/ClientTest.php | 10 +- test/Secrets/ClientTest.php | 2 +- test/SimSwap/ClientIntegrationTest.php | 41 +++++ test/SimSwap/ClientTest.php | 130 ++++++++++++++ .../Responses/simswap-check-success.json | 3 + .../Responses/simswap-date-success.json | 3 + test/Users/ClientTest.php | 8 +- test/Verify/ClientTest.php | 2 +- test/Verify2/ClientTest.php | 2 +- test/Voice/ClientTest.php | 2 +- 45 files changed, 644 insertions(+), 90 deletions(-) create mode 100644 src/Client/Credentials/Gnp.php create mode 100644 src/Client/Credentials/Handler/GnpHandler.php create mode 100644 src/Client/ScopeAwareTrait.php create mode 100644 src/SimSwap/Client.php create mode 100644 src/SimSwap/ClientFactory.php create mode 100644 test/Client/Credentials/Handler/Fixtures/Responses/gnp-be-success.json create mode 100644 test/Client/Credentials/Handler/Fixtures/Responses/gnp-token-success.json create mode 100644 test/Client/Credentials/Handler/GnpHandlerTest.php create mode 100644 test/SimSwap/ClientIntegrationTest.php create mode 100644 test/SimSwap/ClientTest.php create mode 100644 test/SimSwap/Fixtures/Responses/simswap-check-success.json create mode 100644 test/SimSwap/Fixtures/Responses/simswap-date-success.json diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 003e004b..f3404d21 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -23,6 +23,9 @@ test/Verify2 + + test/Client + test/ProactiveConnect @@ -38,6 +41,9 @@ test/SMS + + test/SimSwap + test/Subaccount diff --git a/src/Account/ClientFactory.php b/src/Account/ClientFactory.php index 77721af6..7446d220 100644 --- a/src/Account/ClientFactory.php +++ b/src/Account/ClientFactory.php @@ -19,7 +19,7 @@ public function __invoke(ContainerInterface $container): Client ->setBaseUrl($accountApi->getClient()->getRestUrl()) ->setIsHAL(false) ->setBaseUri('/account') - ->setAuthHandler(new BasicQueryHandler()) + ->setAuthHandlers(new BasicQueryHandler()) ; return new Client($accountApi); diff --git a/src/Application/ClientFactory.php b/src/Application/ClientFactory.php index ebc3ca88..1593fe6f 100644 --- a/src/Application/ClientFactory.php +++ b/src/Application/ClientFactory.php @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client $api ->setBaseUri('/v2/applications') ->setCollectionName('applications') - ->setAuthHandler(new BasicHandler()); + ->setAuthHandlers(new BasicHandler()); return new Client($api, new Hydrator()); } diff --git a/src/Client.php b/src/Client.php index 3c425ed0..a6ac029e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -43,6 +43,7 @@ use Vonage\Numbers\ClientFactory as NumbersClientFactory; use Vonage\Redact\ClientFactory as RedactClientFactory; use Vonage\Secrets\ClientFactory as SecretsClientFactory; +use Vonage\SimSwap\ClientFactory as SimSwapClientFactory; use Vonage\SMS\ClientFactory as SMSClientFactory; use Vonage\Subaccount\ClientFactory as SubaccountClientFactory; use Vonage\Messages\ClientFactory as MessagesClientFactory; @@ -77,6 +78,7 @@ * @method Numbers\Client numbers() * @method Redact\Client redact() * @method Secrets\Client secrets() + * @method SimSwap\Client simswap() * @method SMS\Client sms() * @method Subaccount\Client subaccount() * @method Users\Client users() @@ -216,6 +218,7 @@ public function __construct( 'messages' => MessagesClientFactory::class, 'redact' => RedactClientFactory::class, 'secrets' => SecretsClientFactory::class, + 'simswap' => SimSwapClientFactory::class, 'sms' => SMSClientFactory::class, 'subaccount' => SubaccountClientFactory::class, 'users' => UsersClientFactory::class, @@ -225,6 +228,7 @@ public function __construct( // Additional utility classes APIResource::class => APIResource::class, + Client::class => function() { return $this; } ]; if (class_exists('Vonage\Video\ClientFactory')) { diff --git a/src/Client/APIResource.php b/src/Client/APIResource.php index 07289c33..4125a332 100644 --- a/src/Client/APIResource.php +++ b/src/Client/APIResource.php @@ -1,4 +1,5 @@ getClient()->getCredentials(); - if (is_array($this->getAuthHandler())) { - foreach ($this->getAuthHandler() as $handler) { + if (is_array($this->getAuthHandlers())) { + foreach ($this->getAuthHandlers() as $handler) { try { $request = $handler($request, $credentials); break; @@ -84,7 +85,7 @@ public function addAuth(RequestInterface $request): RequestInterface return $request; } - return $this->getAuthHandler()($request, $credentials); + return $this->getAuthHandlers()($request, $credentials); } /** @@ -106,7 +107,7 @@ public function create(array $body, string $uri = '', array $headers = []): ?arr $request->getBody()->write(json_encode($body)); - if ($this->getAuthHandler()) { + if ($this->getAuthHandlers()) { $request = $this->addAuth($request); } @@ -154,7 +155,7 @@ public function delete(string $id, array $headers = []): ?array $headers ); - if ($this->getAuthHandler()) { + if ($this->getAuthHandlers()) { $request = $this->addAuth($request); } @@ -207,7 +208,7 @@ public function get($id, array $query = [], array $headers = [], bool $jsonRespo $headers ); - if ($this->getAuthHandler()) { + if ($this->getAuthHandlers()) { $request = $this->addAuth($request); } @@ -231,10 +232,10 @@ public function get($id, array $query = [], array $headers = [], bool $jsonRespo return json_decode($response->getBody()->getContents(), true); } - public function getAuthHandler() + public function getAuthHandlers() { // If we have not set a handler, default to Basic and issue warning. - if (!$this->authHandler) { + if (!$this->authHandlers) { $this->log( LogLevel::WARNING, 'Warning: no authorisation handler set for this Client. Defaulting to Basic which might not be @@ -244,7 +245,7 @@ public function getAuthHandler() return new BasicHandler(); } - return $this->authHandler; + return $this->authHandlers; } public function getBaseUrl(): ?string @@ -352,12 +353,12 @@ public function search(?FilterInterface $filter = null, string $uri = ''): Itera * * @return $this */ - public function setAuthHandler($handler): self + public function setAuthHandlers($handler): self { if (!is_array($handler)) { $handler = [$handler]; } - $this->authHandler = $handler; + $this->authHandlers = $handler; return $this; } @@ -430,7 +431,7 @@ public function submit(array $formData = [], string $uri = '', array $headers = $headers ); - if ($this->getAuthHandler()) { + if ($this->getAuthHandlers()) { $request = $this->addAuth($request); } @@ -473,7 +474,7 @@ protected function updateEntity(string $method, string $id, array $body, array $ $headers ); - if ($this->getAuthHandler()) { + if ($this->getAuthHandlers()) { $request = $this->addAuth($request); } diff --git a/src/Client/Credentials/Gnp.php b/src/Client/Credentials/Gnp.php new file mode 100644 index 00000000..33a11d05 --- /dev/null +++ b/src/Client/Credentials/Gnp.php @@ -0,0 +1,25 @@ +msisdn; + } + + public function setMsisdn(string $msisdn): Gnp + { + $this->msisdn = $msisdn; + + return $this; + } +} diff --git a/src/Client/Credentials/Handler/AbstractHandler.php b/src/Client/Credentials/Handler/AbstractHandler.php index fed34229..d4a6b4b8 100644 --- a/src/Client/Credentials/Handler/AbstractHandler.php +++ b/src/Client/Credentials/Handler/AbstractHandler.php @@ -8,7 +8,7 @@ abstract class AbstractHandler implements HandlerInterface { - abstract function __invoke(RequestInterface $request, CredentialsInterface $credentials): RequestInterface; + abstract public function __invoke(RequestInterface $request, CredentialsInterface $credentials): RequestInterface; protected function extract(string $class, CredentialsInterface $credentials): CredentialsInterface { diff --git a/src/Client/Credentials/Handler/GnpHandler.php b/src/Client/Credentials/Handler/GnpHandler.php new file mode 100644 index 00000000..0149ec6e --- /dev/null +++ b/src/Client/Credentials/Handler/GnpHandler.php @@ -0,0 +1,60 @@ +extract(Gnp::class, $credentials); + $msisdn = $credentials->getMsisdn(); + + // Request OIDC, returns Auth Request ID + // Reconfigure new client for GNP Auth + $api = new APIResource(); + $api->setAuthHandlers(new KeypairHandler()); + $api->setClient($this->getClient()); + $api->setBaseUrl(self::VONAGE_GNP_AUTH_BACKEND_URL); + + // This handler requires an injected client configured with a Gnp credentials object and a configured scope + $response = $api->submit([ + 'login_hint' => $msisdn, + 'scope' => $this->getScope() + ]); + + $decoded = json_decode($response, true, 512, JSON_THROW_ON_ERROR); + + $authReqId = $decoded['auth_req_id']; + + // CAMARA Access Token + $api->setBaseUrl(self::VONAGE_GNP_AUTH_TOKEN_URL); + $response = $api->submit([ + 'grant_type' => self::VONAGE_GNP_AUTH_TOKEN_GRANT_TYPE, + 'auth_req_id' => $authReqId + ]); + + $decoded = json_decode($response, true, 512, JSON_THROW_ON_ERROR); + + $token = $decoded['access_token']; + + // Add CAMARA Access Token to request and return to make API call + return $request->withHeader('Authorization', 'Bearer ' . $token); + } +} diff --git a/src/Client/Credentials/Keypair.php b/src/Client/Credentials/Keypair.php index 91222450..a9be1a1c 100644 --- a/src/Client/Credentials/Keypair.php +++ b/src/Client/Credentials/Keypair.php @@ -4,20 +4,13 @@ namespace Vonage\Client\Credentials; -use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Encoding\JoseEncoder; use Lcobucci\JWT\Signer\Key; use Lcobucci\JWT\Signer\Key\InMemory; -use Lcobucci\JWT\Signer\Rsa\Sha256; use Lcobucci\JWT\Token; use Vonage\Application\Application; -use Vonage\Client\Exception\Validation; use Vonage\JWT\TokenGenerator; -use function base64_encode; -use function mt_rand; -use function time; - /** * @property mixed application */ diff --git a/src/Client/ScopeAwareTrait.php b/src/Client/ScopeAwareTrait.php new file mode 100644 index 00000000..7c48965a --- /dev/null +++ b/src/Client/ScopeAwareTrait.php @@ -0,0 +1,25 @@ +scope = $scope; + + return $this; + } + + public function getScope(): ?string + { + return $this->scope; + } +} diff --git a/src/Conversion/ClientFactory.php b/src/Conversion/ClientFactory.php index 706ab1a8..291f828c 100644 --- a/src/Conversion/ClientFactory.php +++ b/src/Conversion/ClientFactory.php @@ -19,7 +19,7 @@ public function __invoke(ContainerInterface $container): Client /** @var APIResource $api */ $api = $container->make(APIResource::class); $api->setBaseUri('/conversions/'); - $api->setAuthHandler(new BasicHandler()); + $api->setAuthHandlers(new BasicHandler()); return new Client($api); } diff --git a/src/Entity/IterableAPICollection.php b/src/Entity/IterableAPICollection.php index 878ccb0c..aa8157eb 100644 --- a/src/Entity/IterableAPICollection.php +++ b/src/Entity/IterableAPICollection.php @@ -526,7 +526,7 @@ protected function fetchPage($absoluteUri): void $request = new Request($requestUri, 'GET'); - if ($this->getApiResource()->getAuthHandler()) { + if ($this->getApiResource()->getAuthHandlers()) { $request = $this->getApiResource()->addAuth($request); } diff --git a/src/Insights/ClientFactory.php b/src/Insights/ClientFactory.php index b1a21ae7..aa3d0f26 100644 --- a/src/Insights/ClientFactory.php +++ b/src/Insights/ClientFactory.php @@ -15,7 +15,7 @@ public function __invoke(ContainerInterface $container): Client /** @var APIResource $api */ $api = $container->make(APIResource::class); $api->setIsHAL(false); - $api->setAuthHandler(new BasicQueryHandler()); + $api->setAuthHandlers(new BasicQueryHandler()); return new Client($api); } diff --git a/src/Meetings/ClientFactory.php b/src/Meetings/ClientFactory.php index eca8e738..d44384e8 100644 --- a/src/Meetings/ClientFactory.php +++ b/src/Meetings/ClientFactory.php @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client $api ->setBaseUrl('https://api-eu.vonage.com/v1/meetings/') ->setExceptionErrorHandler(new ExceptionErrorHandler()) - ->setAuthHandler(new KeypairHandler()); + ->setAuthHandlers(new KeypairHandler()); return new Client($api); } diff --git a/src/Messages/Client.php b/src/Messages/Client.php index d775399e..3a0d6bac 100644 --- a/src/Messages/Client.php +++ b/src/Messages/Client.php @@ -21,6 +21,6 @@ public function getAPIResource(): APIResource public function send(BaseMessage $message): ?array { - return $this->api->create($message->toArray()); + return $this->getAPIResource()->create($message->toArray()); } } diff --git a/src/Messages/ClientFactory.php b/src/Messages/ClientFactory.php index 7ef55fc9..e72ca2ee 100644 --- a/src/Messages/ClientFactory.php +++ b/src/Messages/ClientFactory.php @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client ->setBaseUrl($api->getClient()->getApiUrl() . '/v1/messages') ->setIsHAL(false) ->setErrorsOn200(false) - ->setAuthHandler([new KeypairHandler(), new BasicHandler()]) + ->setAuthHandlers([new KeypairHandler(), new BasicHandler()]) ->setExceptionErrorHandler(new ExceptionErrorHandler()); return new Client($api); diff --git a/src/Numbers/ClientFactory.php b/src/Numbers/ClientFactory.php index 2b5a6468..2f011dc3 100644 --- a/src/Numbers/ClientFactory.php +++ b/src/Numbers/ClientFactory.php @@ -17,7 +17,7 @@ public function __invoke(ContainerInterface $container): Client $api ->setBaseUrl($api->getClient()->getRestUrl()) ->setIsHAL(false) - ->setAuthHandler(new BasicHandler()); + ->setAuthHandlers(new BasicHandler()); return new Client($api); } diff --git a/src/Redact/ClientFactory.php b/src/Redact/ClientFactory.php index 5e912ca4..0a78ab0b 100644 --- a/src/Redact/ClientFactory.php +++ b/src/Redact/ClientFactory.php @@ -20,7 +20,7 @@ public function __invoke(ContainerInterface $container): Client $api = $container->make(APIResource::class); $api ->setBaseUri('/v1/redact/transaction') - ->setAuthHandler(new BasicHandler()) + ->setAuthHandlers(new BasicHandler()) ->setCollectionName(''); // This API has a slightly different format for the error message, so override diff --git a/src/SMS/ClientFactory.php b/src/SMS/ClientFactory.php index 59af2e0f..81656765 100644 --- a/src/SMS/ClientFactory.php +++ b/src/SMS/ClientFactory.php @@ -21,7 +21,7 @@ public function __invoke(ContainerInterface $container): Client ->setIsHAL(false) ->setErrorsOn200(true) ->setExceptionErrorHandler(new ExceptionErrorHandler()) - ->setAuthHandler([new BasicHandler(), new SignatureBodyHandler()]); + ->setAuthHandlers([new BasicHandler(), new SignatureBodyHandler()]); return new Client($api); } diff --git a/src/SimSwap/Client.php b/src/SimSwap/Client.php new file mode 100644 index 00000000..b198bfe3 --- /dev/null +++ b/src/SimSwap/Client.php @@ -0,0 +1,62 @@ +api; + } + + + public function checkSimSwap(string $number, ?int $maxAge = null) + { + /** @var GnpHandler $handler */ + $handler = $this->getAPIResource()->getAuthHandlers()[0]; + + if (!$handler instanceof GnpHandler) { + throw new \RuntimeException('SimSwap Client has been misconfigured. Only a GNP Handler can be used'); + } + + $handler->setScope('dpv:FraudPreventionAndDetection#check-sim-swap'); + + $payload = [ + 'phoneNumber' => $number + ]; + + if (!is_null($maxAge)) { + $payload['maxAge'] = $maxAge; + } + + $response = $this->getAPIResource()->create($payload, 'check'); + + return $response['swapped']; + } + + public function checkSimSwapDate(string $number): string + { + /** @var GnpHandler $handler */ + $handler = $this->getAPIResource()->getAuthHandlers()[0]; + + if (!$handler instanceof GnpHandler) { + throw new \RuntimeException('SimSwap Client has been misconfigured. Only a GNP Handler can be used'); + } + + $handler->setScope('dpv:FraudPreventionAndDetection#retrieve-sim-swap'); + + $response = $this->getAPIResource()->create(['phoneNumber' => $number], 'retrieve-date'); + + return $response['latestSimChange']; + } +} diff --git a/src/SimSwap/ClientFactory.php b/src/SimSwap/ClientFactory.php new file mode 100644 index 00000000..92432137 --- /dev/null +++ b/src/SimSwap/ClientFactory.php @@ -0,0 +1,27 @@ +get(\Vonage\Client::class); + $handler->setClient($client); + + /** @var APIResource $api */ + $api = $container->make(APIResource::class); + $api + ->setBaseUrl('https://api-eu.vonage.com/camara/sim-swap/v040') + ->setIsHAL(false) + ->setErrorsOn200(false) + ->setAuthHandlers($handler); + + return new Client($api); + } +} \ No newline at end of file diff --git a/src/Verify/ClientFactory.php b/src/Verify/ClientFactory.php index 8d8dbfe1..35f2d982 100644 --- a/src/Verify/ClientFactory.php +++ b/src/Verify/ClientFactory.php @@ -21,7 +21,7 @@ public function __invoke(ContainerInterface $container): Client ->setIsHAL(false) ->setBaseUri('/verify') ->setErrorsOn200(true) - ->setAuthHandler(new TokenBodyHandler()) + ->setAuthHandlers(new TokenBodyHandler()) ->setExceptionErrorHandler(new ExceptionErrorHandler()); return new Client($api); diff --git a/src/Voice/ClientFactory.php b/src/Voice/ClientFactory.php index 11cfc887..03069e3a 100644 --- a/src/Voice/ClientFactory.php +++ b/src/Voice/ClientFactory.php @@ -16,7 +16,7 @@ public function __invoke(ContainerInterface $container): Client $api = $container->make(APIResource::class); $api ->setBaseUri('/v1/calls') - ->setAuthHandler(new KeypairHandler()) + ->setAuthHandlers(new KeypairHandler()) ->setCollectionName('calls'); return new Client($api); diff --git a/test/Account/ClientTest.php b/test/Account/ClientTest.php index f83a63d3..7d120a9d 100644 --- a/test/Account/ClientTest.php +++ b/test/Account/ClientTest.php @@ -49,7 +49,7 @@ public function setUp(): void $this->api = new APIResource(); $this->api->setBaseUrl('https://rest.nexmo.com') ->setIsHAL(false) - ->setAuthHandler(new Client\Credentials\Handler\BasicQueryHandler()) + ->setAuthHandlers(new Client\Credentials\Handler\BasicQueryHandler()) ->setBaseUri('/account'); $this->api->setClient($this->vonageClient->reveal()); @@ -155,7 +155,7 @@ public function testGetBalance(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-balance', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -185,7 +185,7 @@ public function testGetBalanceWithNoResults(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-balance', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->shouldBeCalledTimes(1)->willReturn($this->getResponse('empty')); @@ -314,7 +314,7 @@ public function testGetSmsPricing(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-pricing/outbound/sms', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('country', 'US', $request); return true; @@ -339,7 +339,7 @@ public function testGetSmsPricingReturnsEmptySet(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-pricing/outbound/sms', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('country', 'XX', $request); return true; @@ -359,7 +359,7 @@ public function testGetVoicePricing(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-pricing/outbound/voice', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('country', 'US', $request); return true; @@ -380,7 +380,7 @@ public function testGetPrefixPricing(): void $this->assertEquals('/account/get-prefix-pricing/outbound', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('prefix', '263', $request); if ($hasRun) { @@ -402,7 +402,7 @@ public function testGetPrefixPricingNoResults(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-prefix-pricing/outbound', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('prefix', '263', $request); return true; @@ -420,7 +420,7 @@ public function testGetPrefixPricingGenerates4xxError(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-prefix-pricing/outbound', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('prefix', '263', $request); return true; @@ -437,7 +437,7 @@ public function testGetPrefixPricingGenerates5xxError(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/get-prefix-pricing/outbound', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('prefix', '263', $request); return true; diff --git a/test/Application/ClientTest.php b/test/Application/ClientTest.php index ade1efd6..548199fc 100644 --- a/test/Application/ClientTest.php +++ b/test/Application/ClientTest.php @@ -89,7 +89,7 @@ public function testGetApplication($payload, $id, $expectsError): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) use ($id) { $this->assertEquals('/v2/applications/' . $id, $request->getUri()->getPath()); $this->assertEquals('api.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse()); diff --git a/test/Client/APIResourceTest.php b/test/Client/APIResourceTest.php index 99bf020a..29c1b5d2 100644 --- a/test/Client/APIResourceTest.php +++ b/test/Client/APIResourceTest.php @@ -41,16 +41,16 @@ public function testNotOverridingBaseURLReturnsBlank(): void public function testCanSetMultipleAuthHandlers(): void { $resource = new APIResource(); - $resource->setAuthHandler([new BasicHandler(), new SignatureBodyHandler()]); + $resource->setAuthHandlers([new BasicHandler(), new SignatureBodyHandler()]); - $this->assertIsArray($resource->getAuthHandler()); + $this->assertIsArray($resource->getAuthHandlers()); } public function testSingleAuthHanlderConvertedToArray(): void { $resource = new APIResource(); - $resource->setAuthHandler(new BasicHandler()); + $resource->setAuthHandlers(new BasicHandler()); - $this->assertIsArray($resource->getAuthHandler()); + $this->assertIsArray($resource->getAuthHandlers()); } } diff --git a/test/Client/Credentials/Handler/Fixtures/Responses/gnp-be-success.json b/test/Client/Credentials/Handler/Fixtures/Responses/gnp-be-success.json new file mode 100644 index 00000000..ccdaa415 --- /dev/null +++ b/test/Client/Credentials/Handler/Fixtures/Responses/gnp-be-success.json @@ -0,0 +1,5 @@ +{ + "auth_req_id": "0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537", + "expires_in": "120", + "interval": "2" +} \ No newline at end of file diff --git a/test/Client/Credentials/Handler/Fixtures/Responses/gnp-token-success.json b/test/Client/Credentials/Handler/Fixtures/Responses/gnp-token-success.json new file mode 100644 index 00000000..d9ef8e63 --- /dev/null +++ b/test/Client/Credentials/Handler/Fixtures/Responses/gnp-token-success.json @@ -0,0 +1,5 @@ +{ + "access_token": "5d0358cd-8861-4c9f-9702-6164b6e483f4", + "token_type": "string", + "refresh_token": "586c7bea-96f6-4388-bd6d-36a759dc5a0a" +} \ No newline at end of file diff --git a/test/Client/Credentials/Handler/GnpHandlerTest.php b/test/Client/Credentials/Handler/GnpHandlerTest.php new file mode 100644 index 00000000..a1fd3463 --- /dev/null +++ b/test/Client/Credentials/Handler/GnpHandlerTest.php @@ -0,0 +1,164 @@ +key = file_get_contents(__DIR__ . '/../test.key'); + + $this->handlerClient = $this->prophesize(Client::class); + $this->handlerClient->getCredentials()->willReturn( + new Client\Credentials\Container(new Client\Credentials\Gnp( + 'tel:+447700900000', + $this->key, + $this->application + )) + ); + } + + public function time(): int + { + return 1697209080; + } + + public function testWillReturnSimSwapCheckWithValidCredentials(): void + { + $this->handlerClient->send(Argument::that(function (Request $request) { + $this->requestCount++; + + if ($this->requestCount === 1) { + $this->assertRequestMethod('POST', $request); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/oauth2/bc-authorize', + $uriString + ); + + $this->assertRequestFormBodyContains('login_hint', 'tel:+447700900000', $request); + $this->assertRequestFormBodyContains('scope', 'dpv:FraudPreventionAndDetection#check-sim-swap', $request); + + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + + return true; + } + + if ($this->requestCount === 2) { + $this->assertEquals('POST', $request->getMethod()); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/oauth2/token', + $uriString + ); + + $this->assertRequestFormBodyContains('grant_type', 'urn:openid:params:grant-type:ciba', $request); + $this->assertRequestFormBodyContains('auth_req_id', '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537', $request); + + return true; + } + }))->willReturn($this->getResponse('gnp-be-success'), $this->getResponse('gnp-token-success')); + + $credentials = new Gnp($this->msisdn, $this->key, $this->application); + $handler = new GnpHandler(); + $handler->setClient($this->handlerClient->reveal()); + $handler->setScope('dpv:FraudPreventionAndDetection#check-sim-swap'); + + $request = new Request(); + + $request = $handler($request, $credentials); + $authHeader = $request->getHeader('Authorization'); + $this->assertEquals('Bearer 5d0358cd-8861-4c9f-9702-6164b6e483f4', $authHeader[0]); + + $this->assertInstanceOf(Request::class, $request); + } + + public function testWillReturnSimSwapDateWithValidCredentials(): void + { + $this->handlerClient->send(Argument::that(function (Request $request) { + $this->requestCount++; + + if ($this->requestCount === 1) { + $this->assertRequestMethod('POST', $request); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/oauth2/bc-authorize', + $uriString + ); + + $this->assertRequestFormBodyContains('login_hint', 'tel:+447700900000', $request); + $this->assertRequestFormBodyContains('scope', 'dpv:FraudPreventionAndDetection#check-sim-swap', $request); + + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + + return true; + } + + if ($this->requestCount === 2) { + $this->assertEquals('POST', $request->getMethod()); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/oauth2/token', + $uriString + ); + + $this->assertRequestFormBodyContains('grant_type', 'urn:openid:params:grant-type:ciba', $request); + $this->assertRequestFormBodyContains('auth_req_id', '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537', $request); + + return true; + } + }))->willReturn($this->getResponse('gnp-be-success'), $this->getResponse('gnp-token-success')); + + $credentials = new Gnp($this->msisdn, $this->key, $this->application); + $handler = new GnpHandler(); + $handler->setClient($this->handlerClient->reveal()); + $handler->setScope('dpv:FraudPreventionAndDetection#check-sim-swap'); + + $request = new Request(); + + $request = $handler($request, $credentials); + $this->assertInstanceOf(Request::class, $request); + } + protected function getResponse(string $identifier, int $status = 200): Response + { + return new Response(fopen(__DIR__ . '/Fixtures/Responses/' . $identifier . '.json', 'rb'), $status); + } +} diff --git a/test/Conversion/ClientTest.php b/test/Conversion/ClientTest.php index dcfb8b78..62b7ff4a 100644 --- a/test/Conversion/ClientTest.php +++ b/test/Conversion/ClientTest.php @@ -55,7 +55,7 @@ public function setUp(): void $this->apiResource = new APIResource(); $this->apiResource ->setBaseUri('/conversions/') - ->setAuthHandler(new Client\Credentials\Handler\BasicHandler()) + ->setAuthHandlers(new Client\Credentials\Handler\BasicHandler()) ->setClient($this->vonageClient->reveal()); $this->conversionClient = new ConversionClient($this->apiResource); diff --git a/test/Insights/AdvancedTest.php b/test/Insights/AdvancedTest.php index 7d3d7493..5d850849 100644 --- a/test/Insights/AdvancedTest.php +++ b/test/Insights/AdvancedTest.php @@ -34,7 +34,7 @@ public function setUp(): void $this->api = (new APIResource()) ->setClient($this->vonageClient->reveal()) ->setIsHAL(false) - ->setAuthHandler(new BasicQueryHandler()) + ->setAuthHandlers(new BasicQueryHandler()) ->setBaseUrl('https://api.nexmo.com/ni/advanced'); $this->insightClient = new InsightClient($this->api); diff --git a/test/Insights/ClientTest.php b/test/Insights/ClientTest.php index e7d60072..fa5f7b20 100644 --- a/test/Insights/ClientTest.php +++ b/test/Insights/ClientTest.php @@ -76,7 +76,7 @@ public function testAdvancedAsync(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/ni/advanced/async/json', $request->getUri()->getPath()); $this->assertEquals('api.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains("number", "14155550100", $request); $this->assertRequestQueryContains("callback", "example.com/hook", $request); @@ -157,7 +157,7 @@ protected function checkInsightsRequest($methodToCall, $expectedPath, $expectedC $this->vonageClient->send(Argument::that(function (RequestInterface $request) use ($expectedPath) { $this->assertEquals($expectedPath, $request->getUri()->getPath()); $this->assertEquals('api.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains("number", "14155550100", $request); return true; @@ -173,7 +173,7 @@ protected function checkInsightsRequestCnam($methodToCall, $expectedPath, $expec $this->vonageClient->send(Argument::that(function (RequestInterface $request) use ($expectedPath) { $this->assertEquals($expectedPath, $request->getUri()->getPath()); $this->assertEquals('api.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains("number", "14155550100", $request); $this->assertRequestQueryContains("cnam", "true", $request); diff --git a/test/Meetings/ClientTest.php b/test/Meetings/ClientTest.php index fa030a72..32a000b7 100644 --- a/test/Meetings/ClientTest.php +++ b/test/Meetings/ClientTest.php @@ -51,7 +51,7 @@ public function setUp(): void ->setIsHAL(true) ->setExceptionErrorHandler(new ExceptionErrorHandler()) ->setClient($this->vonageClient->reveal()) - ->setAuthHandler(new KeypairHandler()) + ->setAuthHandlers(new KeypairHandler()) ->setBaseUrl('https://api-eu.vonage.com/v1/meetings'); $this->meetingsClient = new MeetingsClient($this->api); } @@ -67,7 +67,7 @@ public function testBaseUrlIsSet(): void public function testWillGetAvailableRooms(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -87,7 +87,7 @@ public function testWillGetAvailableRooms(): void public function testWillGetAvailableRoomsWithFilter(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -179,7 +179,7 @@ public function testClientWillHandleUnauthorizedRequests(): void public function testClientWillHandleNotFoundResponse(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); $this->assertEquals( @@ -217,7 +217,7 @@ public function testClientWillHandleValidationError(): void public function testWillGetRoomDetails(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); $this->assertEquals( @@ -269,7 +269,7 @@ public function testWillUpdateExistingRoom(): void public function testWillGetRecording(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -308,7 +308,7 @@ public function testWillDeleteRecording(): void public function testWillGetRecordingsFromSession(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -330,7 +330,7 @@ public function testWillGetRecordingsFromSession(): void public function testWillGetMeetingDialNumbers(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -352,7 +352,7 @@ public function testWillGetMeetingDialNumbers(): void public function testWillGetApplicationThemes(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -413,7 +413,7 @@ public function testWillHandleConflictErrorOnThemeCreation(): void public function testWillGetThemeById(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -562,7 +562,7 @@ public function testWillUploadImageToAws(): void public function testCanGetUploadUrlsForThemeLogo(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -578,7 +578,7 @@ public function testCanGetUploadUrlsForThemeLogo(): void public function testWillGetRoomsAssociatedWithTheme(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -597,7 +597,7 @@ public function testWillGetRoomsAssociatedWithTheme(): void public function testWillGetRoomsAssociatedWithThemeUsingFilter(): void { $this->vonageClient->send(Argument::that(function (RequestInterface $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); diff --git a/test/Messages/ClientTest.php b/test/Messages/ClientTest.php index c93fe738..6e6e3611 100644 --- a/test/Messages/ClientTest.php +++ b/test/Messages/ClientTest.php @@ -74,7 +74,7 @@ public function setUp(): void ->setIsHAL(false) ->setErrorsOn200(false) ->setClient($this->vonageClient->reveal()) - ->setAuthHandler([new Client\Credentials\Handler\KeypairHandler(), new Client\Credentials\Handler\BasicHandler()]) + ->setAuthHandlers([new Client\Credentials\Handler\KeypairHandler(), new Client\Credentials\Handler\BasicHandler()]) ->setExceptionErrorHandler(new ExceptionErrorHandler()) ->setBaseUrl('https://rest.nexmo.com'); diff --git a/test/Numbers/ClientTest.php b/test/Numbers/ClientTest.php index 25e57564..754b96e6 100644 --- a/test/Numbers/ClientTest.php +++ b/test/Numbers/ClientTest.php @@ -166,7 +166,7 @@ public function testGetNumber($payload, $id): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) use ($id) { $this->assertEquals('/account/numbers', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('pattern', $id, $request); return true; }))->willReturn($this->getResponse('single')); @@ -198,7 +198,7 @@ public function testListNumbers(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/numbers', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('list')); @@ -230,7 +230,7 @@ public function testSearchAvailablePassesThroughWhitelistedOptions(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) use ($options) { $this->assertEquals('/number/search', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); // Things that are whitelisted should be shown foreach ($options as $name => $value) { @@ -262,7 +262,7 @@ public function testSearchAvailableAcceptsFilterInterfaceOptions(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/number/search', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('available-numbers')); @@ -297,7 +297,7 @@ public function testSearchAvailableReturnsNumberList(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/number/search', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('available-numbers')); @@ -324,7 +324,7 @@ public function testSearchAvailableReturnsEmptyNumberList(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/number/search', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('empty')); @@ -360,7 +360,7 @@ public function testSearchOwnedPassesInAllowedAdditionalParameters(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/numbers', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $this->assertRequestQueryContains('index', '1', $request); $this->assertRequestQueryContains('size', '100', $request); $this->assertRequestQueryContains('search_pattern', '0', $request); @@ -393,7 +393,7 @@ public function testSearchOwnedReturnsSingleNumber(): void $this->vonageClient->send(Argument::that(function (RequestInterface $request) { $this->assertEquals('/account/numbers', $request->getUri()->getPath()); $this->assertEquals('rest.nexmo.com', $request->getUri()->getHost()); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('single')); diff --git a/test/ProactiveConnect/ClientTest.php b/test/ProactiveConnect/ClientTest.php index 007568f6..c7d5dd3a 100644 --- a/test/ProactiveConnect/ClientTest.php +++ b/test/ProactiveConnect/ClientTest.php @@ -45,7 +45,7 @@ public function setUp(): void ->setIsHAL(true) ->setErrorsOn200(false) ->setClient($this->vonageClient->reveal()) - ->setAuthHandler(new Client\Credentials\Handler\KeypairHandler()) + ->setAuthHandlers(new Client\Credentials\Handler\KeypairHandler()) ->setBaseUrl('https://api-eu.vonage.com/v0.1/bulk'); $this->proactiveConnectClient = new ProactiveConnectClient($this->api); @@ -322,7 +322,7 @@ public function testCanGetListById(): void $uriString ); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('list-get-success')); @@ -479,7 +479,7 @@ public function testWillReplaceFetchItemsFromDataSource() public function testWillGetListItems(): void { $this->vonageClient->send(Argument::that(function (Request $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -545,7 +545,7 @@ public function testWillCreateListItem(): void public function testWillDownloadItemCsv(): void { $this->vonageClient->send(Argument::that(function (Request $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); @@ -593,7 +593,7 @@ public function testWillGetItemById(): void $itemId = '4cb98f71-a879-49f7-b5cf-2314353eb52c'; $this->vonageClient->send(Argument::that(function (Request $request) { - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); $uri = $request->getUri(); $uriString = $uri->__toString(); $this->assertEquals( diff --git a/test/Secrets/ClientTest.php b/test/Secrets/ClientTest.php index 434a9d3d..f5966050 100644 --- a/test/Secrets/ClientTest.php +++ b/test/Secrets/ClientTest.php @@ -37,7 +37,7 @@ public function setUp(): void $api = new APIResource(); $api->setClient($this->vonage->reveal()) ->setBaseUri('/accounts') - ->setAuthHandler(new VonageClient\Credentials\Handler\BasicHandler()) + ->setAuthHandlers(new VonageClient\Credentials\Handler\BasicHandler()) ->setCollectionName('secrets'); $this->client = new Client($api); diff --git a/test/SimSwap/ClientIntegrationTest.php b/test/SimSwap/ClientIntegrationTest.php new file mode 100644 index 00000000..1b789d4a --- /dev/null +++ b/test/SimSwap/ClientIntegrationTest.php @@ -0,0 +1,41 @@ +key = file_get_contents(__DIR__ . '/../Client/Credentials/test.key'); + + parent::setUp(); // TODO: Change the autogenerated stub + } + + public function testWillConfigureClientCorrectly(): void + { + $vonageClient = new Client(new Client\Credentials\Gnp('999', $this->key, 'XXX')); + $simSwapClient = $vonageClient->simswap(); + $authHandlers = $simSwapClient->getAPIResource()->getAuthHandlers(); + $this->assertInstanceOf(\Vonage\SimSwap\Client::class, $simSwapClient); + + // Assert that Auth handler is Gnp + $this->assertInstanceOf(Client\Credentials\Handler\GnpHandler::class, $authHandlers[0]); + + // Assert that Auth handler has a configured client with Gnp credentials + /** @var Client $handlerClient */ + $handlerClient = $authHandlers[0]->getClient(); + $this->assertInstanceOf(Client\Credentials\Gnp::class, $handlerClient->getCredentials()); + + $this->assertTrue(true); + } +} diff --git a/test/SimSwap/ClientTest.php b/test/SimSwap/ClientTest.php new file mode 100644 index 00000000..45d15eed --- /dev/null +++ b/test/SimSwap/ClientTest.php @@ -0,0 +1,130 @@ +vonageClient = $this->prophesize(Client::class); + $this->vonageClient->getCredentials()->willReturn( + new Client\Credentials\Container(new Client\Credentials\Gnp( + 'tel:+447700900000', + file_get_contents(__DIR__ . '/../Client/Credentials/test.key'), + 'def', + )) + ); + + $this->handlerClient = $this->prophesize(Client::class); + $this->handlerClient->getCredentials()->willReturn( + new Client\Credentials\Container(new Client\Credentials\Gnp( + 'tel:+447700900000', + file_get_contents(__DIR__ . '/../Client/Credentials/test.key'), + 'def', + )) + ); + + $handler = new Client\Credentials\Handler\GnpHandler(); + $handler->setClient($this->handlerClient->reveal()); + + /** @noinspection PhpParamsInspection */ + $this->api = (new APIResource()) + ->setClient($this->vonageClient->reveal()) + ->setAuthHandlers($handler) + ->setBaseUrl('https://api-eu.vonage.com/camara/sim-swap/v040/'); + + $this->simSwapClient = new SimSwapClient($this->api); + } + + public function testHasSetupClientCorrectly(): void + { + $this->assertInstanceOf(SimSwapClient::class, $this->simSwapClient); + } + + public function testWillCheckSimSwap(): void + { + $this->handlerClient->send(Argument::that(function (Request $request) { + }))->willReturn( + $this->getResponse('../../../Client/Credentials/Handler/Fixtures/Responses/gnp-be-success'), + $this->getResponse('../../../Client/Credentials/Handler/Fixtures/Responses/gnp-token-success') + ); + + $this->vonageClient->send(Argument::that(function (Request $request) { + $this->assertEquals('POST', $request->getMethod()); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/camara/sim-swap/v040/check', + $uriString + ); + + $this->assertRequestJsonBodyContains('phoneNumber', '+346661113334', $request); + $this->assertRequestJsonBodyContains('maxAge', 240, $request); + + return true; + }))->willReturn($this->getResponse('simswap-check-success')); + + $response = $this->simSwapClient->checkSimSwap('+346661113334', 240); + + $this->assertTrue($response); + } + + public function testWillRetrieveSimSwapDate(): void + { + $this->handlerClient->send(Argument::that(function (Request $request) { + }))->willReturn( + $this->getResponse('../../../Client/Credentials/Handler/Fixtures/Responses/gnp-be-success'), + $this->getResponse('../../../Client/Credentials/Handler/Fixtures/Responses/gnp-token-success') + ); + + $this->vonageClient->send(Argument::that(function (Request $request) { + $this->assertEquals('POST', $request->getMethod()); + + $uri = $request->getUri(); + $uriString = $uri->__toString(); + $this->assertEquals( + 'https://api-eu.vonage.com/camara/sim-swap/v040/retrieve-date', + $uriString + ); + + $this->assertRequestJsonBodyContains('phoneNumber', '+346661113334', $request); + + return true; + }))->willReturn($this->getResponse('simswap-date-success')); + + $response = $this->simSwapClient->checkSimSwapDate('+346661113334'); + + $this->assertEquals('2019-08-24T14:15:22Z', $response); + } + + /** + * This method gets the fixtures and wraps them in a Response object to mock the API + */ + protected function getResponse(string $identifier, int $status = 200): Response + { + return new Response(fopen(__DIR__ . '/Fixtures/Responses/' . $identifier . '.json', 'rb'), $status); + } +} diff --git a/test/SimSwap/Fixtures/Responses/simswap-check-success.json b/test/SimSwap/Fixtures/Responses/simswap-check-success.json new file mode 100644 index 00000000..b0e73411 --- /dev/null +++ b/test/SimSwap/Fixtures/Responses/simswap-check-success.json @@ -0,0 +1,3 @@ +{ + "swapped": true +} \ No newline at end of file diff --git a/test/SimSwap/Fixtures/Responses/simswap-date-success.json b/test/SimSwap/Fixtures/Responses/simswap-date-success.json new file mode 100644 index 00000000..1dddfe85 --- /dev/null +++ b/test/SimSwap/Fixtures/Responses/simswap-date-success.json @@ -0,0 +1,3 @@ +{ + "latestSimChange": "2019-08-24T14:15:22Z" +} \ No newline at end of file diff --git a/test/Users/ClientTest.php b/test/Users/ClientTest.php index 3a6d0482..82a52c7e 100644 --- a/test/Users/ClientTest.php +++ b/test/Users/ClientTest.php @@ -46,7 +46,7 @@ public function setUp(): void $apiResource->setClient($this->vonageClient->reveal()) ->setBaseUri('/v1/users') ->setCollectionName('users') - ->setAuthHandler(new Client\Credentials\Handler\KeypairHandler()); + ->setAuthHandlers(new Client\Credentials\Handler\KeypairHandler()); $hydrator = new ArrayHydrator(); $hydrator->setPrototype(new User()); @@ -65,7 +65,7 @@ public function testClientWillUseJwtAuth(): void mb_substr($request->getHeaders()['Authorization'][0], 0, 7) ); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('list-user-success')); @@ -83,7 +83,7 @@ public function testWillListUsers(): void $uriString ); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('list-user-success')); @@ -200,7 +200,7 @@ public function testWillGetUser(): void $uriString ); - $this->assertEquals('GET', $request->getMethod()); + $this->assertRequestMethod('GET', $request); return true; }))->willReturn($this->getResponse('get-user-success')); diff --git a/test/Verify/ClientTest.php b/test/Verify/ClientTest.php index a81c3411..ad1c0b63 100644 --- a/test/Verify/ClientTest.php +++ b/test/Verify/ClientTest.php @@ -51,7 +51,7 @@ public function setUp(): void ->setIsHAL(false) ->setBaseUri('/verify') ->setErrorsOn200(true) - ->setAuthHandler(new Client\Credentials\Handler\TokenBodyHandler()) + ->setAuthHandlers(new Client\Credentials\Handler\TokenBodyHandler()) ->setClient($this->vonageClient->reveal()) ->setExceptionErrorHandler(new ExceptionErrorHandler()); diff --git a/test/Verify2/ClientTest.php b/test/Verify2/ClientTest.php index fe77d040..ed14397a 100644 --- a/test/Verify2/ClientTest.php +++ b/test/Verify2/ClientTest.php @@ -45,7 +45,7 @@ public function setUp(): void ->setIsHAL(false) ->setErrorsOn200(false) ->setClient($this->vonageClient->reveal()) - ->setAuthHandler([new Client\Credentials\Handler\BasicHandler(), new Client\Credentials\Handler\KeypairHandler()]) + ->setAuthHandlers([new Client\Credentials\Handler\BasicHandler(), new Client\Credentials\Handler\KeypairHandler()]) ->setBaseUrl('https://api.nexmo.com/v2/verify'); $this->verify2Client = new Verify2Client($this->api); diff --git a/test/Voice/ClientTest.php b/test/Voice/ClientTest.php index 39a4bcfd..e078c04d 100644 --- a/test/Voice/ClientTest.php +++ b/test/Voice/ClientTest.php @@ -58,7 +58,7 @@ public function setUp(): void $this->api = (new APIResource()) ->setBaseUri('/v1/calls') ->setCollectionName('calls') - ->setAuthHandler(new Client\Credentials\Handler\KeypairHandler()) + ->setAuthHandlers(new Client\Credentials\Handler\KeypairHandler()) ->setClient($this->vonageClient->reveal()); $this->voiceClient = new VoiceClient($this->api);