Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/BlindPay.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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
);
}

Expand Down
4 changes: 3 additions & 1 deletion src/Resources/Instances/InstancesWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -13,7 +14,8 @@
public function __construct(
private Instances $base,
public ApiKeys $apiKeys,
public Webhooks $webhookEndpoints
public Webhooks $webhookEndpoints,
public TermsOfService $tos
) {}

/*
Expand Down
84 changes: 84 additions & 0 deletions src/Resources/TermsOfService/TermsOfService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace BlindPay\SDK\Resources\TermsOfService;

use BlindPay\SDK\Internal\ApiClientInterface;
use BlindPay\SDK\Types\BlindPayApiResponse;

readonly class InitiateInput
{
public function __construct(
public string $idempotencyKey,
public ?string $receiverId = null,
public ?string $redirectUrl = null
) {}

public function toArray(): array
{
$data = [
'idempotency_key' => $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<InitiateResponse>
*/
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;
}
}
77 changes: 77 additions & 0 deletions tests/Resources/TermsOfService/TermsOfServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace BlindPay\SDK\Tests\Resources;

use BlindPay\SDK\BlindPay;
use BlindPay\SDK\Resources\TermsOfService\InitiateInput;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use ReflectionClass;

class TermsOfServiceTest extends TestCase
{
private BlindPay $blindpay;

private MockHandler $mockHandler;

protected function setUp(): void
{
$this->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);
}
}
Loading