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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "blindpay"
version = "2.0.1"
version = "2.1.0"
description = "Official Python SDK for the Blindpay API — Global payments infrastructure"
readme = "README.md"
authors = [{ name = "Blindpay", email = "alves@blindpay.com" }]
Expand Down
2 changes: 1 addition & 1 deletion src/blindpay/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.0.1"
__version__ = "2.1.0"

from ._internal.exceptions import BlindPayError
from .client import BlindPay, BlindPaySync
Expand Down
28 changes: 28 additions & 0 deletions src/blindpay/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
from blindpay.resources.payouts.payouts import PayoutsResource, PayoutsResourceSync
from blindpay.resources.quotes.quotes import QuotesResource, QuotesResourceSync
from blindpay.resources.receivers.receivers import ReceiversResource, ReceiversResourceSync
from blindpay.resources.terms_of_service.terms_of_service import (
TermsOfServiceResource,
TermsOfServiceResourceSync,
)
from blindpay.resources.transfers.transfers import TransfersResource, TransfersResourceSync
from blindpay.resources.upload.upload import UploadResource, UploadResourceSync
from blindpay.resources.virtual_accounts.virtual_accounts import (
Expand Down Expand Up @@ -168,6 +172,12 @@ def webhook_endpoints(self) -> "WebhookEndpointsResource":

return create_webhook_endpoints_resource(self._instance_id, self._api)

@cached_property
def terms_of_service(self) -> "TermsOfServiceResource":
from blindpay.resources.terms_of_service import create_terms_of_service_resource

return create_terms_of_service_resource(self._instance_id, self._api)

def __getattr__(self, name: str) -> Any:
return getattr(self._base, name)

Expand Down Expand Up @@ -327,6 +337,12 @@ def upload(self) -> "UploadResource":

return create_upload_resource(self._api)

@cached_property
def terms_of_service(self) -> "TermsOfServiceResource":
from blindpay.resources.terms_of_service import create_terms_of_service_resource

return create_terms_of_service_resource(self._instance_id, self._api)

def verify_webhook_signature(
self, *, secret: str, id: str, timestamp: str, payload: str, svix_signature: str
) -> bool:
Expand Down Expand Up @@ -386,6 +402,12 @@ def webhook_endpoints(self) -> "WebhookEndpointsResourceSync":

return create_webhook_endpoints_resource_sync(self._instance_id, self._api)

@cached_property
def terms_of_service(self) -> "TermsOfServiceResourceSync":
from blindpay.resources.terms_of_service import create_terms_of_service_resource_sync

return create_terms_of_service_resource_sync(self._instance_id, self._api)

def __getattr__(self, name: str) -> Any:
return getattr(self._base, name)

Expand Down Expand Up @@ -545,6 +567,12 @@ def upload(self) -> "UploadResourceSync":

return create_upload_resource_sync(self._api)

@cached_property
def terms_of_service(self) -> "TermsOfServiceResourceSync":
from blindpay.resources.terms_of_service import create_terms_of_service_resource_sync

return create_terms_of_service_resource_sync(self._instance_id, self._api)

def verify_webhook_signature(
self, *, secret: str, id: str, timestamp: str, payload: str, svix_signature: str
) -> bool:
Expand Down
3 changes: 3 additions & 0 deletions src/blindpay/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .payouts import create_payouts_resource
from .quotes import create_quotes_resource
from .receivers import create_receivers_resource
from .terms_of_service import create_terms_of_service_resource, create_terms_of_service_resource_sync
from .transfers import create_transfers_resource
from .upload import create_upload_resource
from .virtual_accounts import create_virtual_accounts_resource
Expand All @@ -28,6 +29,8 @@
"create_payouts_resource",
"create_quotes_resource",
"create_receivers_resource",
"create_terms_of_service_resource",
"create_terms_of_service_resource_sync",
"create_transfers_resource",
"create_upload_resource",
"create_virtual_accounts_resource",
Expand Down
17 changes: 17 additions & 0 deletions src/blindpay/resources/terms_of_service/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from .terms_of_service import (
InitiateInput,
InitiateResponse,
TermsOfServiceResource,
TermsOfServiceResourceSync,
create_terms_of_service_resource,
create_terms_of_service_resource_sync,
)

__all__ = [
"create_terms_of_service_resource",
"create_terms_of_service_resource_sync",
"TermsOfServiceResource",
"TermsOfServiceResourceSync",
"InitiateInput",
"InitiateResponse",
]
42 changes: 42 additions & 0 deletions src/blindpay/resources/terms_of_service/terms_of_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing_extensions import Optional, TypedDict

from ..._internal.api_client import InternalApiClient, InternalApiClientSync
from ...types import BlindpayApiResponse


class InitiateInput(TypedDict):
idempotency_key: str
receiver_id: Optional[str]
redirect_url: Optional[str]


class InitiateResponse(TypedDict):
url: str


class TermsOfServiceResource:
def __init__(self, instance_id: str, client: InternalApiClient):
self._instance_id = instance_id
self._client = client

async def initiate(self, data: InitiateInput) -> BlindpayApiResponse[InitiateResponse]:
return await self._client.post(f"/e/instances/{self._instance_id}/tos", data)


class TermsOfServiceResourceSync:
def __init__(self, instance_id: str, client: InternalApiClientSync):
self._instance_id = instance_id
self._client = client

def initiate(self, data: InitiateInput) -> BlindpayApiResponse[InitiateResponse]:
return self._client.post(f"/e/instances/{self._instance_id}/tos", data)


def create_terms_of_service_resource(instance_id: str, client: InternalApiClient) -> TermsOfServiceResource:
return TermsOfServiceResource(instance_id, client)


def create_terms_of_service_resource_sync(
instance_id: str, client: InternalApiClientSync
) -> TermsOfServiceResourceSync:
return TermsOfServiceResourceSync(instance_id, client)
74 changes: 74 additions & 0 deletions tests/resources/test_terms_of_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from unittest.mock import patch

import pytest

from blindpay import BlindPay, BlindPaySync


class TestTermsOfService:
@pytest.fixture(autouse=True)
def setup(self):
self.blindpay = BlindPay(api_key="test-key", instance_id="in_000000000000")

@pytest.mark.asyncio
async def test_initiate_terms_of_service(self):
mocked_url = {
"url": "https://app.blindpay.com/e/terms-of-service?session_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
}

with patch.object(self.blindpay._api, "_request") as mock_request:
mock_request.return_value = {"data": mocked_url, "error": None}

response = await self.blindpay.instances.terms_of_service.initiate(
{
"idempotency_key": "123e4567-e89b-12d3-a456-426614174000",
"receiver_id": None,
"redirect_url": None,
}
)

assert response["error"] is None
assert response["data"] == mocked_url
mock_request.assert_called_once_with(
"POST",
"/e/instances/in_000000000000/tos",
{
"idempotency_key": "123e4567-e89b-12d3-a456-426614174000",
"receiver_id": None,
"redirect_url": None,
},
)


class TestTermsOfServiceSync:
@pytest.fixture(autouse=True)
def setup(self):
self.blindpay = BlindPaySync(api_key="test-key", instance_id="in_000000000000")

def test_initiate_terms_of_service(self):
mocked_url = {
"url": "https://app.blindpay.com/e/terms-of-service?session_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
}

with patch.object(self.blindpay._api, "_request") as mock_request:
mock_request.return_value = {"data": mocked_url, "error": None}

response = self.blindpay.instances.terms_of_service.initiate(
{
"idempotency_key": "123e4567-e89b-12d3-a456-426614174000",
"receiver_id": None,
"redirect_url": None,
}
)

assert response["error"] is None
assert response["data"] == mocked_url
mock_request.assert_called_once_with(
"POST",
"/e/instances/in_000000000000/tos",
{
"idempotency_key": "123e4567-e89b-12d3-a456-426614174000",
"receiver_id": None,
"redirect_url": None,
},
)
Loading