diff --git a/src/BlindPay.php b/src/BlindPay.php index accaad1..8f47185 100644 --- a/src/BlindPay.php +++ b/src/BlindPay.php @@ -21,6 +21,7 @@ use BlindPay\SDK\Resources\Quotes\Quotes; use BlindPay\SDK\Resources\Receivers\Receivers; use BlindPay\SDK\Resources\Receivers\ReceiversWrapper; +use BlindPay\SDK\Resources\TermsOfService\TermsOfService; use BlindPay\SDK\Resources\Transfers\Transfers; use BlindPay\SDK\Resources\Upload\Upload; use BlindPay\SDK\Resources\VirtualAccounts\VirtualAccounts; @@ -38,7 +39,7 @@ class BlindPay implements ApiClientInterface { private const BASE_URL = 'https://api.blindpay.com/v1/'; - private const VERSION = '2.1.0'; + private const VERSION = '2.2.0'; private Client $httpClient; @@ -114,10 +115,13 @@ private function initializeInstances(): void $apiKeysResource = new ApiKeys($this->instanceId, $this); $webhooksResource = new Webhooks($this->instanceId, $this); + $termsOfServiceResource = new TermsOfService($this->instanceId, $this); + $this->instances = new InstancesWrapper( $instancesResource, $apiKeysResource, - $webhooksResource + $webhooksResource, + $termsOfServiceResource ); } diff --git a/src/Resources/Instances/InstancesWrapper.php b/src/Resources/Instances/InstancesWrapper.php index b021a2b..a0daa5a 100644 --- a/src/Resources/Instances/InstancesWrapper.php +++ b/src/Resources/Instances/InstancesWrapper.php @@ -5,6 +5,7 @@ namespace BlindPay\SDK\Resources\Instances; use BlindPay\SDK\Resources\ApiKeys\ApiKeys; +use BlindPay\SDK\Resources\TermsOfService\TermsOfService; use BlindPay\SDK\Resources\Webhooks\Webhooks; use BlindPay\SDK\Types\BlindPayApiResponse; @@ -13,7 +14,8 @@ public function __construct( private Instances $base, public ApiKeys $apiKeys, - public Webhooks $webhookEndpoints + public Webhooks $webhookEndpoints, + public TermsOfService $tos ) {} /* diff --git a/src/Resources/TermsOfService/TermsOfService.php b/src/Resources/TermsOfService/TermsOfService.php new file mode 100644 index 0000000..62b8c16 --- /dev/null +++ b/src/Resources/TermsOfService/TermsOfService.php @@ -0,0 +1,84 @@ + $this->idempotencyKey, + ]; + + if ($this->receiverId !== null) { + $data['receiver_id'] = $this->receiverId; + } + + if ($this->redirectUrl !== null) { + $data['redirect_url'] = $this->redirectUrl; + } + + return $data; + } +} + +readonly class InitiateResponse +{ + public function __construct( + public string $url + ) {} + + public static function fromArray(array $data): self + { + return new self( + url: $data['url'] + ); + } +} + +class TermsOfService +{ + public function __construct( + private readonly string $instanceId, + private readonly ApiClientInterface $client + ) {} + + /* + * Initiate Terms of Service acceptance flow + * + * @param InitiateInput $input + * @return BlindPayApiResponse + */ + public function initiate(InitiateInput $input): BlindPayApiResponse + { + if (empty($input->idempotencyKey)) { + return BlindPayApiResponse::error( + new \BlindPay\SDK\Types\ErrorResponse('Idempotency key cannot be empty') + ); + } + + $response = $this->client->post( + "e/instances/{$this->instanceId}/tos", + $input->toArray() + ); + + if ($response->isSuccess() && is_array($response->data)) { + return BlindPayApiResponse::success( + InitiateResponse::fromArray($response->data) + ); + } + + return $response; + } +} diff --git a/tests/Resources/TermsOfService/TermsOfServiceTest.php b/tests/Resources/TermsOfService/TermsOfServiceTest.php new file mode 100644 index 0000000..ff57337 --- /dev/null +++ b/tests/Resources/TermsOfService/TermsOfServiceTest.php @@ -0,0 +1,77 @@ +mockHandler = new MockHandler; + $handlerStack = HandlerStack::create($this->mockHandler); + $httpClient = new Client(['handler' => $handlerStack]); + + $this->blindpay = new BlindPay( + apiKey: 'test-key', + instanceId: 'in_000000000000' + ); + + $this->injectHttpClient($httpClient); + } + + private function injectHttpClient(Client $client): void + { + $reflection = new ReflectionClass($this->blindpay); + $property = $reflection->getProperty('httpClient'); + $property->setAccessible(true); + $property->setValue($this->blindpay, $client); + } + + private function mockResponse(array $body, int $status = 200): void + { + $this->mockHandler->append( + new Response( + $status, + ['Content-Type' => 'application/json'], + json_encode($body) + ) + ); + } + + #[Test] + public function it_initiates_terms_of_service_with_all_parameters(): void + { + $mockedResponse = [ + 'url' => 'https://app.blindpay.com/e/terms-of-service?session_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', + ]; + + $this->mockResponse($mockedResponse); + + $input = new InitiateInput( + idempotencyKey: '123e4567-e89b-12d3-a456-426614174000', + receiverId: null, + redirectUrl: null + ); + + $response = $this->blindpay->instances->tos->initiate($input); + + $this->assertTrue($response->isSuccess()); + $this->assertNull($response->error); + $this->assertEquals($mockedResponse['url'], $response->data->url); + } +}