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
11 changes: 11 additions & 0 deletions checkout_sdk/accounts/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,17 @@ class InstrumentDetailsCardToken(InstrumentDetails):
token: str


class InstrumentAccountType(str, Enum):
SAVINGS = 'savings'
CHECKING = 'checking'


class InstrumentDetailsAch(InstrumentDetails):
account_number: str
routing_number: str
account_type: InstrumentAccountType


class BankDetails:
name: str
branch: str
Expand Down
8 changes: 0 additions & 8 deletions checkout_sdk/issuing/cardholders.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
from enum import Enum

from checkout_sdk.common.common import Phone, Address
from checkout_sdk.common.enums import DocumentType


class CardholderType(str, Enum):
INDIVIDUAL = 'individual'


class CardholderDocument:
type: DocumentType
front_document_id: str
back_document_id: str


class CardholderRequest:
type: CardholderType
reference: str
Expand All @@ -26,4 +19,3 @@ class CardholderRequest:
date_of_birth: str
billing_address: Address
residency_address: Address
document: CardholderDocument
7 changes: 3 additions & 4 deletions checkout_sdk/issuing/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class CardRequest:
activate_card: bool
metadata: CardMetadata
revocation_date: str
activation_date: str # ISO-8601 (IssuingActivationDate)

def __init__(self, type_p: CardType):
self.type = type_p
Expand Down Expand Up @@ -89,6 +90,8 @@ class UpdateCardRequest:
metadata: CardMetadata
expiry_month: int
expiry_year: int
activation_date: str # ISO-8601 (IssuingActivationDate)
revocation_date: str # yyyy-mm-dd (IssuingRevocationDate)


class RenewCardRequest:
Expand All @@ -105,10 +108,6 @@ class VirtualCardRenewRequest(RenewCardRequest):
pass


class ScheduleCardRevocationRequest:
revocation_date: str


class SecurityPair:
question: str
answer: str
Expand Down
42 changes: 42 additions & 0 deletions checkout_sdk/issuing/disputes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from enum import Enum


class DisputeEvidence:
name: str
content: str
Expand All @@ -9,12 +12,32 @@ class DisputeReasonChange:
justification: str


class IssuingDisputeFraudType(str, Enum):
CARD_LOST = 'card_lost'
CARD_STOLEN = 'card_stolen'
CARD_NEVER_RECEIVED = 'card_never_received'
FRAUDULENT_ACCOUNT = 'fraudulent_account'
COUNTERFEIT_CARD = 'counterfeit_card'
ACCOUNT_TAKEOVER = 'account_takeover'
CARD_NOT_PRESENT_FRAUD = 'card_not_present_fraud'
MERCHANT_MISREPRESENTATION = 'merchant_misrepresentation'
CARDHOLDER_MANIPULATION = 'cardholder_manipulation'
INCORRECT_PROCESSING = 'incorrect_processing'
OTHER = 'other'


class IssuingDisputeFraudDetails:
fraud_type: IssuingDisputeFraudType # required
description: str


class CreateDisputeRequest:
transaction_id: str
reason: str
evidence: list # DisputeEvidence
amount: int
presentment_message_id: str
fraud_details: IssuingDisputeFraudDetails
justification: str


Expand All @@ -23,3 +46,22 @@ class EscalateDisputeRequest:
additional_evidence: list # DisputeEvidence
amount: int
reason_change: DisputeReasonChange
fraud_details: IssuingDisputeFraudDetails


class AmendDisputeRequest:
reason: str
amount: int
evidence: list # DisputeEvidence
fraud_details: IssuingDisputeFraudDetails
reason_change_justification: str # max 13000
action_response: str # max 1000


class SubmitDisputeRequest:
# Deprecated: the submit endpoint is deprecated in the API swagger. Use CreateDisputeRequest to
# create and submit in one step, or AmendDisputeRequest when the dispute status is
# 'action_required'.
reason: str
evidence: list # DisputeEvidence
amount: int
36 changes: 21 additions & 15 deletions checkout_sdk/issuing/issuing_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from checkout_sdk.client import Client
from checkout_sdk.issuing.cardholders import CardholderRequest
from checkout_sdk.issuing.cards import CardRequest, ThreeDsEnrollmentRequest, UpdateThreeDsEnrollmentRequest, \
CardCredentialsQuery, RevokeRequest, SuspendRequest, UpdateCardRequest, RenewCardRequest, \
ScheduleCardRevocationRequest
CardCredentialsQuery, RevokeRequest, SuspendRequest, UpdateCardRequest, RenewCardRequest
from checkout_sdk.issuing.controls import CardControlRequest, CardControlsQuery, UpdateCardControlRequest, \
CreateControlGroupRequest, ControlGroupQueryTarget, ControlProfileRequest
from checkout_sdk.issuing.disputes import CreateDisputeRequest, EscalateDisputeRequest
from checkout_sdk.issuing.disputes import CreateDisputeRequest, EscalateDisputeRequest, AmendDisputeRequest, \
SubmitDisputeRequest
from checkout_sdk.issuing.testing import CardAuthorizationRequest, SimulationRequest, \
CardRefundAuthorizationRequest, SimulateOobAuthenticationRequest
from checkout_sdk.issuing.transactions import TransactionsQueryFilter
Expand All @@ -25,7 +25,6 @@ class IssuingClient(Client):
__CREDENTIALS = 'credentials'
__RENEW = 'renew'
__REVOKE = 'revoke'
__SCHEDULE_REVOCATION = 'schedule-revocation'
__SUSPEND = 'suspend'
__CONTROLS = 'controls'
__CONTROL_GROUPS = 'control-groups'
Expand All @@ -37,6 +36,8 @@ class IssuingClient(Client):
__DISPUTES = 'disputes'
__CANCEL = 'cancel'
__ESCALATE = 'escalate'
__AMEND = 'amend'
__SUBMIT = 'submit'
__SIMULATE = 'simulate'
__AUTHORIZATIONS = 'authorizations'
__PRESENTMENTS = 'presentments'
Expand Down Expand Up @@ -115,17 +116,6 @@ def revoke_card(self, card_id: str, revoke_request: RevokeRequest):
self._sdk_authorization(),
revoke_request)

def schedule_card_revocation(self, card_id: str, schedule_request: ScheduleCardRevocationRequest):
return self._api_client.post(
self.build_path(self.__ISSUING, self.__CARDS, card_id, self.__SCHEDULE_REVOCATION),
self._sdk_authorization(),
schedule_request)

def delete_card_revocation(self, card_id: str):
return self._api_client.delete(
self.build_path(self.__ISSUING, self.__CARDS, card_id, self.__SCHEDULE_REVOCATION),
self._sdk_authorization())

def suspend_card(self, card_id: str, suspend_request: SuspendRequest):
return self._api_client.post(self.build_path(self.__ISSUING, self.__CARDS, card_id, self.__SUSPEND),
self._sdk_authorization(),
Expand Down Expand Up @@ -248,6 +238,22 @@ def escalate_dispute(self, dispute_id: str, escalate_dispute_request: EscalateDi
escalate_dispute_request,
idempotency_key)

def amend_dispute(self, dispute_id: str, amend_dispute_request: AmendDisputeRequest = None,
idempotency_key: str = None):
return self._api_client.post(self.build_path(self.__ISSUING, self.__DISPUTES, dispute_id, self.__AMEND),
self._sdk_authorization(),
amend_dispute_request,
idempotency_key)

def submit_dispute(self, dispute_id: str, submit_dispute_request: SubmitDisputeRequest = None,
idempotency_key: str = None):
# Deprecated: use create_dispute to create and submit in one step, or amend_dispute when the
# dispute status is 'action_required'. The submit endpoint is deprecated in the API swagger.
return self._api_client.post(self.build_path(self.__ISSUING, self.__DISPUTES, dispute_id, self.__SUBMIT),
self._sdk_authorization(),
submit_dispute_request,
idempotency_key)

def simulate_authorization(self, authorization_request: CardAuthorizationRequest):
return self._api_client.post(self.build_path(self.__ISSUING, self.__SIMULATE, self.__AUTHORIZATIONS),
self._sdk_authorization(),
Expand Down
109 changes: 108 additions & 1 deletion checkout_sdk/payments/setups/setups.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ class PaymentMethodBase:

# Klarna entities
class KlarnaAccountHolder:
billing_address: Address
# readOnly: the account holder details returned by Klarna after the shopper completes
# verification (swagger KlarnaAccountHolder).
name: str


class Klarna(PaymentMethodBase):
Expand Down Expand Up @@ -402,6 +404,73 @@ class ApplePay(PaymentSetupPaymentMethod):
account_holder: PaymentSetupAccountHolder


# Bacs entities
class BacsAccountHolderType(str, Enum):
INDIVIDUAL = 'individual'
CORPORATE = 'corporate'


class BacsAccountHolder:
type: BacsAccountHolderType
first_name: str
last_name: str
company_name: str
email: str


class Bacs(PaymentMethodBase):
instrument_id: str
account_holder: BacsAccountHolder
account_number: str
bank_code: str
country: str
currency: Currency
allow_partial_match: bool


# Card Present entities
class CardPresentPin:
key_set_id: str
block: str
block_format: str


class CardPresent(PaymentSetupPaymentMethod):
track2: str
emv: str
entry_mode: str
pin: CardPresentPin
store_for_future_use: bool
name: str


# Pay by Bank entities
class PayByBankBank:
bank_id: str
display_name: str
logo_url: str
available: bool


class PayByBankActionType(str, Enum):
SELECT_BANK = 'select_bank'


class PayByBankAction:
type: PayByBankActionType
banks: list # list of PayByBankBank


class PayByBank(PaymentSetupPaymentMethod):
bank_id: str
action: PayByBankAction


# Stablecoin entities
class Stablecoin(PaymentSetupPaymentMethod):
pass


# Card entities
class Card(PaymentSetupPaymentMethod):
number: str
Expand Down Expand Up @@ -459,6 +528,10 @@ class PaymentMethods:
googlepay: GooglePay
applepay: ApplePay
card: Card
bacs: Bacs
card_present: CardPresent
pay_by_bank: PayByBank
stablecoin: Stablecoin


# Settings entity
Expand All @@ -477,6 +550,18 @@ class OrderSubMerchant:
registration_date: datetime


class AmountAllocationCommission:
amount: int
percentage: float


class PaymentSetupAmountAllocation:
id: str # required
amount: int # required
reference: str
commission: AmountAllocationCommission


class Order:
items: list # list of PaymentContextsItems
shipping: ShippingDetails
Expand All @@ -485,6 +570,9 @@ class Order:
invoice_id: str
shipping_amount: int
tax_amount: int
tipping_amount: int
surcharge_amount: int
amount_allocations: list # list of PaymentSetupAmountAllocation


# Industry entities
Expand All @@ -504,6 +592,22 @@ class PaymentSetupBilling:
address: Address


class PaymentSetupBillingDescriptor:
name: str
city: str
reference: str


class PaymentSetupPresentmentDetails:
amount: int
currency: str


class PaymentSetupTerminal:
id: str
local_date_time: str


class AccountFundingTransactionIdentificationType(str, Enum):
PASSPORT = 'passport'
DRIVING_LICENSE = 'driving_license'
Expand Down Expand Up @@ -573,4 +677,7 @@ class PaymentSetupsRequest:
order: Order
industry: Industry
billing: PaymentSetupBilling
billing_descriptor: PaymentSetupBillingDescriptor
presentment_details: PaymentSetupPresentmentDetails
terminal: PaymentSetupTerminal
account_funding_transaction: PaymentSetupAccountFundingTransaction
28 changes: 28 additions & 0 deletions tests/accounts/instrument_details_ach_serialization_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import json

from checkout_sdk.json_serializer import JsonSerializer
from checkout_sdk.accounts.accounts import (
InstrumentDetails, InstrumentDetailsAch, InstrumentAccountType,
)


def _serialize(obj):
return json.loads(json.dumps(obj, cls=JsonSerializer))


class TestInstrumentDetailsAchSerialization:

def test_is_instrument_details(self):
assert isinstance(InstrumentDetailsAch(), InstrumentDetails)

def test_serializes_all_three_fields(self):
details = InstrumentDetailsAch()
details.account_number = '12345100'
details.routing_number = '026009593'
details.account_type = InstrumentAccountType.SAVINGS

assert _serialize(details) == {
'account_number': '12345100',
'routing_number': '026009593',
'account_type': 'savings',
}
Loading
Loading