Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(enrollment): funding source from card token #14

Merged
merged 4 commits into from
Feb 6, 2024
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
3 changes: 2 additions & 1 deletion littlepay/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from littlepay.api.card_tokenization import CardTokenizationMixin
from littlepay.api.groups import GroupsMixin
from littlepay.api.products import ProductsMixin
from littlepay.api.funding_sources import FundingSourcesMixin
from littlepay.config import Config


Expand Down Expand Up @@ -63,7 +64,7 @@ def _json_post_credentials(client, method, uri, headers, body) -> tuple:
return uri, headers, json_data


class Client(CardTokenizationMixin, ProductsMixin, GroupsMixin, ClientProtocol):
class Client(CardTokenizationMixin, ProductsMixin, GroupsMixin, FundingSourcesMixin, ClientProtocol):
"""Represents an API connection to an environment."""

from_active_config = staticmethod(_client_from_active_config)
Expand Down
40 changes: 40 additions & 0 deletions littlepay/api/funding_sources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from dataclasses import dataclass
from typing import List, Optional

from littlepay.api import ClientProtocol


@dataclass
class FundingSourceResponse:
id: str
card_first_digits: str
card_last_digits: str
card_expiry_month: str
card_expiry_year: str
card_scheme: str
form_factor: str
participant_id: str
is_fpan: bool
related_funding_sources: List[dict]
thekaveman marked this conversation as resolved.
Show resolved Hide resolved
card_category: Optional[str] = None
issuer_country_code: Optional[str] = None
issuer_country_numeric_code: Optional[str] = None
replacement_funding_source: Optional[str] = None
token: Optional[str] = None
token_key_id: Optional[str] = None
icc_hash: Optional[str] = None


class FundingSourcesMixin(ClientProtocol):
"""Mixin implements APIs for funding sources."""

FUNDING_SOURCES = "fundingsources"

def funding_source_by_token_endpoint(self, card_token) -> str:
"""Endpoint for a funding source by card token."""
return self._make_endpoint(self.FUNDING_SOURCES, "bytoken", card_token)

def get_funding_source_by_token(self, card_token) -> FundingSourceResponse:
"""Return a FundingSourceResponse object from the funding source by token endpoint."""
endpoint = self.funding_source_by_token_endpoint(card_token)
return self._get(endpoint, FundingSourceResponse)
38 changes: 38 additions & 0 deletions tests/api/test_funding_sources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest

from littlepay.api.funding_sources import FundingSourceResponse, FundingSourcesMixin


@pytest.fixture
def mock_ClientProtocol_get_FundingResource(mocker):
funding_source = FundingSourceResponse(
id="0",
card_first_digits="0000",
card_last_digits="0000",
card_expiry_month="11",
card_expiry_year="24",
card_scheme="Visa",
form_factor="unknown",
participant_id="cst",
is_fpan=True,
related_funding_sources=[],
)
return mocker.patch("littlepay.api.ClientProtocol._get", return_value=funding_source)


def test_FundingSourcesMixin_concession_groups_fundingsources_endpoint(url):
client = FundingSourcesMixin()

assert client.funding_source_by_token_endpoint("abc_token") == f"{url}/fundingsources/bytoken/abc_token"


def test_FundingSourcesMixin_get_funding_source_by_token(mock_ClientProtocol_get_FundingResource):
client = FundingSourcesMixin()

card_token = "abc"
result = client.get_funding_source_by_token(card_token)

mock_ClientProtocol_get_FundingResource.assert_called_once_with(
client.funding_source_by_token_endpoint(card_token), FundingSourceResponse
thekaveman marked this conversation as resolved.
Show resolved Hide resolved
)
assert isinstance(result, FundingSourceResponse)
Loading