From bd6c2ae93496482d5e37d3d86cb9509498129428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:29:19 +0200 Subject: [PATCH] Accounts, Payment Sessions and Account Holder APM updates (#172) --- checkout_sdk/accounts/accounts.py | 99 +++++++++++++- checkout_sdk/checkout_api.py | 2 +- checkout_sdk/common/common.py | 27 +++- checkout_sdk/common/enums.py | 34 +++++ .../payments/hosted/hosted_payments.py | 12 +- checkout_sdk/payments/links/payments_links.py | 14 +- checkout_sdk/payments/payment_apm.py | 41 +++++- checkout_sdk/payments/payments.py | 14 ++ checkout_sdk/payments/sessions/sessions.py | 1 + checkout_sdk/sessions/sessions.py | 127 ++++++++++++++---- tests/checkout_test_utils.py | 5 +- tests/payments/payments_test_utils.py | 3 +- .../request_apm_payments_integration_test.py | 81 ++++++++++- .../payment_sessions_integration_test.py | 2 +- ...quest_and_get_sessions_integration_test.py | 19 ++- tests/sessions/sessions_test_utils.py | 9 +- 16 files changed, 441 insertions(+), 49 deletions(-) diff --git a/checkout_sdk/accounts/accounts.py b/checkout_sdk/accounts/accounts.py index d08335ca..38946ca3 100644 --- a/checkout_sdk/accounts/accounts.py +++ b/checkout_sdk/accounts/accounts.py @@ -40,9 +40,14 @@ class EntityEmailAddresses: primary: str +class Invitee: + email: str + + class ContactDetails: phone: Phone email_addresses: EntityEmailAddresses + invitee: Invitee class Profile: @@ -97,10 +102,73 @@ class TaxVerification: front: str +class ArticlesOfAssociationType(str, Enum): + MEMORANDUM_OF_ASSOCIATION = "memorandum_of_association" + ARTICLES_OF_ASSOCIATION = "articles_of_association" + + +class BankVerificationType(str, Enum): + BANK_STATEMENT = 'bank_statement' + + +class BankVerification: + type: BankVerificationType + front: str + + +class ShareholderStructureType(str, Enum): + CERTIFIED_SHAREHOLDER_STRUCTURE = 'certified_shareholder_structure' + + +class ShareholderStructure: + type: ShareholderStructureType + front: str + + +class ProofOfLegalityType(str, Enum): + PROOF_OF_LEGALITY = 'proof_of_legality' + + +class ProofOfLegality: + type: ProofOfLegalityType + front: str + + +class ProofOfPrincipalAddressType(str, Enum): + PROOF_OF_ADDRESS = 'proof_of_address' + + +class ProofOfPrincipalAddress: + type: ProofOfPrincipalAddressType + front: str + + +class AdditionalDocument: + front: str + + +class FinancialVerificationType(str, Enum): + FINANCIAL_STATEMENT = 'financial_statement' + + +class FinancialVerification: + type: FinancialVerificationType + front: str + + class OnboardSubEntityDocuments: identity_verification: EntityIdentificationDocument company_verification: CompanyVerification + articles_of_association: ArticlesOfAssociationType + bank_verification: BankVerification + shareholder_structure: ShareholderStructure + proof_of_legality: ProofOfLegality + proof_of_principal_address: ProofOfPrincipalAddress + additional_document_1: AdditionalDocument + additional_document_2: AdditionalDocument + additional_document_3: AdditionalDocument tax_verification: TaxVerification + financial_verification: FinancialVerification class EntityRepresentative: @@ -129,16 +197,25 @@ class EntityFinancialDetails: currency: Currency +class DateOfIncorporation: + month: int + year: int + + class Company: business_registration_number: str business_type: BusinessType legal_name: str trading_name: str + business_registration_number: str + date_of_incorporation: DateOfIncorporation + regulatory_licence_number: str principal_address: Address registered_address: Address - document: EntityDocument representatives: list # EntityRepresentative + document: EntityDocument financial_details: EntityFinancialDetails + business_type: BusinessType class Identification: @@ -159,13 +236,31 @@ class Individual: financial_details: EntityFinancialDetails +class ProcessingDetails: + settlement_country: str + target_countries: list # str + annual_processing_volume: int + average_transaction_value: int + highest_transaction_value: int + currency: Currency + + +class AdditionalInfo: + field1: str + field2: str + field3: str + + class OnboardEntityRequest: reference: str - contact_details: ContactDetails + is_draft: bool profile: Profile + contact_details: ContactDetails company: Company + processing_details: ProcessingDetails individual: Individual documents: OnboardSubEntityDocuments + additional_info: AdditionalInfo class InstrumentDocument: diff --git a/checkout_sdk/checkout_api.py b/checkout_sdk/checkout_api.py index 5979d113..0de88469 100644 --- a/checkout_sdk/checkout_api.py +++ b/checkout_sdk/checkout_api.py @@ -73,4 +73,4 @@ def __init__(self, configuration: CheckoutConfiguration): self.financial = FinancialClient(api_client=base_api_client, configuration=configuration) self.issuing = IssuingClient(api_client=base_api_client, configuration=configuration) self.contexts = PaymentContextsClient(api_client=base_api_client, configuration=configuration) - self.sessions = PaymentSessionsClient(api_client=base_api_client, configuration=configuration) + self.payment_sessions = PaymentSessionsClient(api_client=base_api_client, configuration=configuration) diff --git a/checkout_sdk/common/common.py b/checkout_sdk/common/common.py index 314a1292..63f998bd 100644 --- a/checkout_sdk/common/common.py +++ b/checkout_sdk/common/common.py @@ -1,7 +1,7 @@ from datetime import datetime from enum import Enum -from checkout_sdk.common.enums import AccountHolderIdentificationType, AccountHolderType, Country +from checkout_sdk.common.enums import AccountHolderIdentificationType, AccountHolderType, Country, AccountType class Address: @@ -25,6 +25,10 @@ class CustomerRequest: phone: Phone +class CustomerRetry: + max_attempts: int + + class ResidentialStatusType(str, Enum): RESIDENT = 'resident' NON_RESIDENT = 'non_resident' @@ -39,8 +43,12 @@ class AccountHolderIdentification: class AccountHolder: type: AccountHolderType + full_name: str first_name: str + middle_name: str last_name: str + email: str + gender: str company_name: str tax_id: str date_of_birth: str @@ -49,9 +57,7 @@ class AccountHolder: billing_address: Address phone: Phone identification: AccountHolderIdentification - email: str - gender: str - middle_name: str + account_name_inquiry: bool class BankDetails: @@ -113,3 +119,16 @@ class ShippingInfo: class QueryFilterDateRange: from_: datetime to: datetime + + +class Destination: + account_type: AccountType + account_number: str + bank_code: str + branch_code: str + iban: str + bban: str + swift_bic: str + country: Country + account_holder: AccountHolder + bank: BankDetails diff --git a/checkout_sdk/common/enums.py b/checkout_sdk/common/enums.py index 160ee0e5..fb751399 100644 --- a/checkout_sdk/common/enums.py +++ b/checkout_sdk/common/enums.py @@ -471,6 +471,11 @@ class PaymentSourceType(str, Enum): TRUSTLY = 'trustly' CVCONNECT = 'cvconnect' SEPA = 'sepa' + ACH = 'ach' + BIZUM = 'bizum' + OCTOPUS = 'octopus' + PLAID = 'plaid' + SEQURA = 'sequra' class ChallengeIndicator(str, Enum): @@ -515,3 +520,32 @@ class DocumentType(str, Enum): CITIZEN_CARD = 'citizen_card' RESIDENCE_PERMIT = 'residence_permit' ELECTORAL_ID = 'electoral_id' + + +class AccountChangeIndicatorType(str, Enum): + THIS_TRANSACTION = "this_transaction" + LESS_THAN_THIRTY_DAYS = "less_than_thirty_days" + THIRTY_TO_SIXTY_DAYS = "thirty_to_sixty_days" + MORE_THAN_SIXTY_DAYS = "more_than_sixty_days" + + +class AccountPasswordChangeIndicatorType(str, Enum): + NO_CHANGE = "no_change" + THIS_TRANSACTION = "this_transaction" + LESS_THAN_THIRTY_DAYS = "less_than_thirty_days" + THIRTY_TO_SIXTY_DAYS = "thirty_to_sixty_days" + MORE_THAN_SIXTY_DAYS = "more_than_sixty_days" + + +class AccountTypeCardProductType(str, Enum): + CREDIT = "credit" + DEBIT = "debit" + NOT_APPLICABLE = "not_applicable" + + +class CardholderAccountAgeIndicatorType(str, Enum): + LESS_THAN_THIRTY_DAYS = "less_than_thirty_days" + MORE_THAN_SIXTY_DAYS = "more_than_sixty_days" + NO_ACCOUNT = "no_account" + THIRTY_TO_SIXTY_DAYS = "thirty_to_sixty_days" + THIS_TRANSACTION = "this_transaction" diff --git a/checkout_sdk/payments/hosted/hosted_payments.py b/checkout_sdk/payments/hosted/hosted_payments.py index a8c826a3..ecf18e1b 100644 --- a/checkout_sdk/payments/hosted/hosted_payments.py +++ b/checkout_sdk/payments/hosted/hosted_payments.py @@ -3,18 +3,21 @@ from checkout_sdk.common.common import CustomerRequest from checkout_sdk.common.enums import Currency from checkout_sdk.payments.payments import BillingDescriptor, PaymentType, ShippingDetails, ThreeDsRequest, \ - RiskRequest, PaymentRecipient, ProcessingSettings + RiskRequest, PaymentRecipient, ProcessingSettings, PaymentSender, PaymentRetryRequest from checkout_sdk.payments.payments_previous import BillingInformation class HostedPaymentsSessionRequest: - payment_type: PaymentType.REGULAR amount: int currency: Currency + payment_type: PaymentType.REGULAR payment_ip: str billing_descriptor: BillingDescriptor reference: str description: str + display_name: str + processing_channel_id: str + amount_allocations: list # values of AmountAllocations customer: CustomerRequest shipping: ShippingDetails billing: BillingInformation @@ -24,6 +27,8 @@ class HostedPaymentsSessionRequest: disabled_payment_methods: list # PaymentSourceType products: list # common.Product risk: RiskRequest + customer_retry: PaymentRetryRequest + sender: PaymentSender success_url: str cancel_url: str failure_url: str @@ -32,6 +37,3 @@ class HostedPaymentsSessionRequest: three_ds: ThreeDsRequest capture: bool capture_on: datetime - # Not available on Previous - processing_channel_id: str - amount_allocations: list # values of AmountAllocations diff --git a/checkout_sdk/payments/links/payments_links.py b/checkout_sdk/payments/links/payments_links.py index 23d35fd0..24628fb0 100644 --- a/checkout_sdk/payments/links/payments_links.py +++ b/checkout_sdk/payments/links/payments_links.py @@ -1,20 +1,23 @@ from datetime import datetime -from checkout_sdk.common.common import CustomerRequest +from checkout_sdk.common.common import CustomerRequest, CustomerRetry from checkout_sdk.common.enums import Currency from checkout_sdk.payments.payments import BillingDescriptor, PaymentType, ShippingDetails, ThreeDsRequest, \ - RiskRequest, PaymentRecipient, ProcessingSettings + RiskRequest, PaymentRecipient, ProcessingSettings, PaymentSender from checkout_sdk.payments.payments_previous import BillingInformation class PaymentLinkRequest: - payment_type: PaymentType.REGULAR amount: int currency: Currency + payment_type: PaymentType.REGULAR payment_ip: str billing_descriptor: BillingDescriptor reference: str description: str + display_name: str + processing_channel_id: str + amount_allocations: list # values of AmountAllocations expires_in: int customer: CustomerRequest shipping: ShippingDetails @@ -22,13 +25,14 @@ class PaymentLinkRequest: recipient: PaymentRecipient processing: ProcessingSettings allow_payment_methods: list # PaymentSourceType + disabled_payment_methods: list # PaymentSourceType products: list # common.Product metadata: dict three_ds: ThreeDsRequest risk: RiskRequest + customer_retry: CustomerRetry + sender: PaymentSender return_url: str locale: str capture: bool capture_on: datetime - processing_channel_id: str - amount_allocations: list # values of AmountAllocations diff --git a/checkout_sdk/payments/payment_apm.py b/checkout_sdk/payments/payment_apm.py index 783d8b56..1e475979 100644 --- a/checkout_sdk/payments/payment_apm.py +++ b/checkout_sdk/payments/payment_apm.py @@ -3,7 +3,7 @@ from datetime import datetime from checkout_sdk.common.common import Address, AccountHolder -from checkout_sdk.common.enums import PaymentSourceType, Country, Currency +from checkout_sdk.common.enums import PaymentSourceType, Country, Currency, AccountType from checkout_sdk.payments.payments import PaymentRequestSource, BillingPlan, PaymentMethodDetails from checkout_sdk.tokens.tokens import ApplePayTokenData @@ -98,6 +98,7 @@ def __init__(self): class RequestEpsSource(PaymentRequestSource): purpose: str + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.EPS) @@ -244,3 +245,41 @@ class RequestSepaSource(PaymentRequestSource): def __init__(self): super().__init__(PaymentSourceType.SEPA) + + +class RequestAchSource(PaymentRequestSource): + account_type: AccountType + country: Country + account_number: str + bank_code: str + account_holder: AccountHolder + + def __init__(self): + super().__init__(PaymentSourceType.ACH) + + +class RequestBizumSource(PaymentRequestSource): + mobile_number: str + + def __init__(self): + super().__init__(PaymentSourceType.BIZUM) + + +class RequestOctopusSource(PaymentRequestSource): + def __init__(self): + super().__init__(PaymentSourceType.OCTOPUS) + + +class RequestPlaidSource(PaymentRequestSource): + token: str + account_holder: AccountHolder + + def __init__(self): + super().__init__(PaymentSourceType.PLAID) + + +class RequestSequraSource(PaymentRequestSource): + billing_address: Address + + def __init__(self): + super().__init__(PaymentSourceType.SEQURA) diff --git a/checkout_sdk/payments/payments.py b/checkout_sdk/payments/payments.py index 6c79ad03..7b01656f 100644 --- a/checkout_sdk/payments/payments.py +++ b/checkout_sdk/payments/payments.py @@ -64,6 +64,7 @@ class Exemption(str, Enum): OTHER = 'other' LOW_RISK_PROGRAM = 'low_risk_program' DATA_SHARE = 'data_share' + RECURRING_OPERATION = 'recurring_operation' class ThreeDSFlowType(str, Enum): @@ -153,6 +154,7 @@ def __init__(self, type_p: PaymentSenderType): class PaymentCorporateSender(PaymentSender): company_name: str address: Address + reference: str reference_type: str source_of_funds: str identification: AccountHolderIdentification @@ -164,6 +166,7 @@ def __init__(self): class PaymentGovermentSender(PaymentSender): company_name: str address: Address + reference: str reference_type: str source_of_funds: str identification: AccountHolderIdentification @@ -179,6 +182,7 @@ class PaymentIndividualSender(PaymentSender): dob: str address: Address identification: AccountHolderIdentification + reference: str reference_type: str source_of_funds: str date_of_birth: str @@ -213,6 +217,7 @@ class PaymentRequestCardSource(PaymentRequestSource): store_for_future_use: bool billing_address: Address phone: Phone + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.CARD) @@ -224,6 +229,7 @@ class PaymentRequestTokenSource(PaymentRequestSource): phone: Phone stored: bool store_for_future_use: bool + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.TOKEN) @@ -241,6 +247,7 @@ class PaymentRequestNetworkTokenSource(PaymentRequestSource): cvv: str billing_address: Address phone: Phone + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.NETWORK_TOKEN) @@ -252,6 +259,7 @@ class PaymentRequestIdSource(PaymentRequestSource): payment_method: str stored: bool store_for_future_use: bool + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.ID) @@ -280,6 +288,7 @@ def __init__(self): class RequestCustomerSource(PaymentRequestSource): id: str + account_holder: AccountHolder def __init__(self): super().__init__(PaymentSourceType.CUSTOMER) @@ -439,6 +448,10 @@ class PaymentRetryRequest: # Request Payment +class PartialAuthorization: + enabled: bool + + class PaymentRequest: payment_context_id: str source: PaymentRequestSource @@ -449,6 +462,7 @@ class PaymentRequest: reference: str description: str authorization_type: AuthorizationType + partial_authorization: PartialAuthorization capture: bool capture_on: datetime customer: PaymentCustomerRequest diff --git a/checkout_sdk/payments/sessions/sessions.py b/checkout_sdk/payments/sessions/sessions.py index dfa88fca..c9cfd222 100644 --- a/checkout_sdk/payments/sessions/sessions.py +++ b/checkout_sdk/payments/sessions/sessions.py @@ -70,4 +70,5 @@ class PaymentSessionsRequest: three_ds: ThreeDsRequest sender: PaymentSender capture: bool + capture_on: datetime ip_address: str diff --git a/checkout_sdk/sessions/sessions.py b/checkout_sdk/sessions/sessions.py index e0e77251..6f777cf7 100644 --- a/checkout_sdk/sessions/sessions.py +++ b/checkout_sdk/sessions/sessions.py @@ -1,18 +1,21 @@ +from datetime import datetime from enum import Enum from checkout_sdk.common.common import Phone, Address -from checkout_sdk.common.enums import Currency, ChallengeIndicator +from checkout_sdk.common.enums import Currency, ChallengeIndicator, CardholderAccountAgeIndicatorType, \ + AccountChangeIndicatorType, AccountPasswordChangeIndicatorType, AccountTypeCardProductType class ChannelType(str, Enum): - BROWSER = 'browser' APP = 'app' + BROWSER = 'browser' + MERCHANT_INITIATED = 'merchant_initiated' class SdkInterfaceType(str, Enum): - NATIVE = 'native' - HTML = 'html' BOTH = 'both' + HTML = 'html' + NATIVE = 'native' class ThreeDsMethodCompletion(str, Enum): @@ -34,11 +37,11 @@ class SessionSourceType(str, Enum): class AuthenticationType(str, Enum): - REGULAR = 'regular' - RECURRING = 'recurring' + ADD_CARD = 'add_card' INSTALLMENT = 'installment' MAINTAIN_CARD = 'maintain_card' - ADD_CARD = 'add_card' + RECURRING = 'recurring' + REGULAR = 'regular' class Category(str, Enum): @@ -47,11 +50,11 @@ class Category(str, Enum): class TransactionType(str, Enum): - GOODS_SERVICE = 'goods_service' - CHECK_ACCEPTANCE = 'check_acceptance' ACCOUNT_FUNDING = 'account_funding' - QUASHI_CARD_TRANSACTION = 'quashi_card_transaction' + CHECK_ACCEPTANCE = 'check_acceptance' + GOODS_SERVICE = 'goods_service' PREPAID_ACTIVATION_AND_LOAD = 'prepaid_activation_and_load' + QUASHI_CARD_TRANSACTION = 'quashi_card_transaction' class UIElements(str, Enum): @@ -72,12 +75,12 @@ class SessionScheme(str, Enum): class AuthenticationMethod(str, Enum): - NO_AUTHENTICATION = 'no_authentication' - OWN_CREDENTIALS = 'own_credentials' FEDERATED_ID = 'federated_id' + FIDO = 'fido' ISSUER_CREDENTIALS = 'issuer_credentials' + NO_AUTHENTICATION = 'no_authentication' + OWN_CREDENTIALS = 'own_credentials' THIRD_PARTY_AUTHENTICATION = 'third_party_authentication' - FIDO = 'fido' class DeliveryTimeframe(str, Enum): @@ -133,7 +136,7 @@ def __init__(self): class BrowserSession(ChannelData): - three_ds_method_completion: ThreeDsMethodCompletion + three_ds_method_completion: ThreeDsMethodCompletion = ThreeDsMethodCompletion.U accept_header: str java_enabled: bool javascript_enabled: bool @@ -149,6 +152,27 @@ def __init__(self): super().__init__(ChannelType.BROWSER) +class RequestType(str, Enum): + ACCOUNT_VERIFICATION = "account_verification" + ADD_CARD = "add_card" + INSTALLMENT_TRANSACTION = "installment_transaction" + MAIL_ORDER = "mail_order" + MAINTAIN_CARD_INFORMATION = "maintain_card_information" + OTHER_PAYMENT = "other_payment" + RECURRING_TRANSACTION = "recurring_transaction" + SPLIT_OR_DELAYED_SHIPMENT = "split_or_delayed_shipment" + TELEPHONE_ORDER = "telephone_order" + TOP_UP = "top_up" + WHITELIST_STATUS_CHECK = "whitelist_status_check" + + +class MerchantInitiatedSession(ChannelData): + request_type: RequestType + + def __init__(self): + super().__init__(ChannelType.MERCHANT_INITIATED) + + # Completion class Completion: type: CompletionInfoType @@ -193,7 +217,7 @@ class SessionCardSource(SessionSource): expiry_month: int expiry_year: int name: str - stored: bool + stored: bool = False store_for_future_use: bool def __init__(self): @@ -226,6 +250,10 @@ def __init__(self): super().__init__(SessionSourceType.NETWORK_TOKEN) +class ThreeDsRequestorAuthenticationInfo: + pass + + class CardholderAccountInfo: purchase_count: int account_age: str @@ -234,7 +262,30 @@ class CardholderAccountInfo: account_name_matches_shipping_name: bool suspicious_account_activity: bool transactions_today: int + # @deprecated This property will be removed in the future, and should not be used. authentication_method: AuthenticationMethod + cardholder_account_age_indicator: CardholderAccountAgeIndicatorType + account_change: datetime + account_change_indicator: AccountChangeIndicatorType + account_date: datetime + account_password_change: str + account_password_change_indicator: AccountPasswordChangeIndicatorType + transactions_per_year: int + payment_account_age: datetime + shipping_address_usage: datetime + account_type: AccountTypeCardProductType + account_id: str + three_ds_requestor_authentication_info: ThreeDsRequestorAuthenticationInfo + + +class ReorderItemsIndicatorType(str, Enum): + FIRST_TIME_ORDERED = "first_time_ordered" + REORDERED = "reordered" + + +class PreOrderPurchaseIndicatorType(str, Enum): + FUTURE_AVAILABILITY = "future_availability" + MERCHANDISE_AVAILABLE = "merchandise_available" class MerchantRiskInfo: @@ -243,40 +294,68 @@ class MerchantRiskInfo: is_preorder: bool is_reorder: bool shipping_indicator: ShippingIndicator + reorder_items_indicator: ReorderItemsIndicatorType + pre_order_purchase_indicator: PreOrderPurchaseIndicatorType + pre_order_date: datetime + gift_card_amount: str + gift_card_currency: str + gift_card_count: str class Recurring: - days_between_payments: int - expiry: str + days_between_payments: int = 1 + expiry: str = '99991231' class Installment: number_of_payments: int - days_between_payments: int - expiry: str + days_between_payments: int = 1 + expiry: str = '99991231' + + +class OptimizedProperties: + field: str + original_value: str + optimized_value: str + + +class Optimization: + optimized: bool + framework: str + optimized_properties: list # OptimizedProperties + + +class InitialTransaction: + acs_transaction_id: str + authentication_method: str + authentication_timestamp: str + authentication_data: str + initial_session_id: str class SessionRequest: - source: SessionSource + source: SessionSource = SessionCardSource() amount: int currency: Currency processing_channel_id: str marketplace: SessionMarketplaceData - authentication_type: AuthenticationType - authentication_category: Category + authentication_type: AuthenticationType = AuthenticationType.REGULAR + authentication_category: Category = Category.PAYMENT account_info: CardholderAccountInfo - challenge_indicator: ChallengeIndicator + challenge_indicator: ChallengeIndicator = ChallengeIndicator.NO_PREFERENCE billing_descriptor: SessionsBillingDescriptor reference: str merchant_risk_info: MerchantRiskInfo prior_transaction_reference: str - transaction_type: TransactionType + transaction_type: TransactionType = TransactionType.GOODS_SERVICE shipping_address: SessionAddress shipping_address_matches_billing: bool completion: Completion channel_data: ChannelData recurring: Recurring installment: Installment + optimization: Optimization + initial_transaction: InitialTransaction class ThreeDsMethodCompletionRequest: diff --git a/tests/checkout_test_utils.py b/tests/checkout_test_utils.py index 2c3a747c..2a67317b 100644 --- a/tests/checkout_test_utils.py +++ b/tests/checkout_test_utils.py @@ -6,7 +6,7 @@ from pathlib import Path from checkout_sdk.common.common import Address, Phone, CustomerRequest, AccountHolder -from checkout_sdk.common.enums import Country +from checkout_sdk.common.enums import Country, AccountHolderType from checkout_sdk.exception import CheckoutException, CheckoutApiException from checkout_sdk.payments.payments import Payer, PaymentRecipient @@ -19,6 +19,7 @@ FAILURE_URL = 'https://testing.checkout.com/failure' PAYEE_NOT_ONBOARDED = 'payee_not_onboarded' APM_SERVICE_UNAVAILABLE = 'apm_service_unavailable' +APM_CURRENCY_NOT_SUPPORTED = 'currency_not_supported' _logger = logging.getLogger('checkout') @@ -84,10 +85,12 @@ def phone() -> Phone: def account_holder() -> AccountHolder: _account_holder = AccountHolder() + _account_holder.type = AccountHolderType.INDIVIDUAL _account_holder.first_name = 'John' _account_holder.last_name = 'Doe' _account_holder.billing_address = address() _account_holder.phone = phone() + _account_holder.account_name_inquiry = False return _account_holder diff --git a/tests/payments/payments_test_utils.py b/tests/payments/payments_test_utils.py index 89210027..3f4f69c2 100644 --- a/tests/payments/payments_test_utils.py +++ b/tests/payments/payments_test_utils.py @@ -10,7 +10,7 @@ from checkout_sdk.payments.payments_previous import RequestTokenSource from checkout_sdk.tokens.tokens import CardTokenRequest from tests.checkout_test_utils import VisaCard, address, phone, assert_response, random_email, new_uuid, FIRST_NAME, \ - LAST_NAME, NAME, SUCCESS_URL, FAILURE_URL + LAST_NAME, NAME, SUCCESS_URL, FAILURE_URL, account_holder def make_card_payment(default_api: CheckoutApi, amount: int = 10, capture_on: datetime = None, @@ -23,6 +23,7 @@ def make_card_payment(default_api: CheckoutApi, amount: int = 10, capture_on: da request_card_source.name = VisaCard.name request_card_source.billing_address = address() request_card_source.phone = phone() + request_card_source.account_holder = account_holder() customer_request = CustomerRequest() customer_request.email = random_email() diff --git a/tests/payments/request_apm_payments_integration_test.py b/tests/payments/request_apm_payments_integration_test.py index dab11860..841a5bdc 100644 --- a/tests/payments/request_apm_payments_integration_test.py +++ b/tests/payments/request_apm_payments_integration_test.py @@ -12,13 +12,14 @@ PaymentRequestWeChatPaySource, RequestAlipayPlusSource, RequestP24Source, RequestKnetSource, \ RequestBancontactSource, RequestMultiBancoSource, RequestPostFinanceSource, RequestStcPaySource, RequestAlmaSource, \ RequestKlarnaSource, RequestFawrySource, RequestTrustlySource, RequestCvConnectSource, RequestIllicadoSource, \ - RequestSepaSource, RequestGiropaySource + RequestSepaSource, RequestGiropaySource, RequestEpsSource, RequestBizumSource, RequestOctopusSource, \ + RequestPlaidSource, RequestSequraSource from checkout_sdk.payments.payments import PaymentRequest, ProcessingSettings, FawryProduct, PaymentCustomerRequest, \ ShippingDetails, PaymentMethodDetails from checkout_sdk.payments.payments_apm_previous import RequestSofortSource from tests.checkout_test_utils import assert_response, SUCCESS_URL, FAILURE_URL, retriable, address, FIRST_NAME, \ LAST_NAME, phone, check_error_item, PAYEE_NOT_ONBOARDED, APM_SERVICE_UNAVAILABLE, random_email, new_uuid, \ - account_holder, REFERENCE, DESCRIPTION + account_holder, REFERENCE, DESCRIPTION, APM_CURRENCY_NOT_SUPPORTED @pytest.mark.skip(reason='not available') @@ -486,3 +487,79 @@ def test_should_make_sepa_payment(default_api): check_error_item(callback=default_api.payments.request_payment, error_item=APM_SERVICE_UNAVAILABLE, payment_request=payment_request) + + +def test_should_request_eps_payment(default_api): + payment_request = PaymentRequest() + payment_request.source = RequestEpsSource() + payment_request.source.account_holder = account_holder() + payment_request.source.purpose = 'Mens black t-shirt L' + payment_request.amount = 100 + payment_request.currency = Currency.EUR + payment_request.capture = True + payment_request.success_url = SUCCESS_URL + payment_request.failure_url = FAILURE_URL + + check_error_item(callback=default_api.payments.request_payment, + error_item=PAYEE_NOT_ONBOARDED, + payment_request=payment_request) + + +def test_should_make_bizum_payment(default_api): + payment_request = PaymentRequest() + payment_request.source = RequestBizumSource() + payment_request.source.mobile_number = '+447700900986' + payment_request.amount = 10 + payment_request.currency = Currency.EUR + payment_request.capture = True + payment_request.success_url = SUCCESS_URL + payment_request.failure_url = FAILURE_URL + + check_error_item(callback=default_api.payments.request_payment, + error_item=APM_SERVICE_UNAVAILABLE, + payment_request=payment_request) + + +def test_should_make_octopus_payment(default_api): + payment_request = PaymentRequest() + payment_request.source = RequestOctopusSource() + payment_request.amount = 10 + payment_request.currency = Currency.USD + payment_request.capture = True + payment_request.success_url = SUCCESS_URL + payment_request.failure_url = FAILURE_URL + + check_error_item(callback=default_api.payments.request_payment, + error_item=APM_CURRENCY_NOT_SUPPORTED, + payment_request=payment_request) + + +def test_should_make_plaid_payment(default_api): + payment_request = PaymentRequest() + payment_request.source = RequestPlaidSource() + payment_request.source.token = 'token' + payment_request.source.account_holder = account_holder() + payment_request.amount = 10 + payment_request.currency = Currency.USD + payment_request.capture = True + payment_request.success_url = SUCCESS_URL + payment_request.failure_url = FAILURE_URL + + check_error_item(callback=default_api.payments.request_payment, + error_item=PAYEE_NOT_ONBOARDED, + payment_request=payment_request) + + +def test_should_make_sequra_payment(default_api): + payment_request = PaymentRequest() + payment_request.source = RequestSequraSource() + payment_request.billing_address = address() + payment_request.amount = 10 + payment_request.currency = Currency.EUR + payment_request.capture = True + payment_request.success_url = SUCCESS_URL + payment_request.failure_url = FAILURE_URL + + check_error_item(callback=default_api.payments.request_payment, + error_item=PAYEE_NOT_ONBOARDED, + payment_request=payment_request) diff --git a/tests/payments/sessions/payment_sessions_integration_test.py b/tests/payments/sessions/payment_sessions_integration_test.py index 3d52c79f..a6eaf9d1 100644 --- a/tests/payments/sessions/payment_sessions_integration_test.py +++ b/tests/payments/sessions/payment_sessions_integration_test.py @@ -10,7 +10,7 @@ def test_should_create_payment_sessions(default_api): request = create_payment_sessions_request() - response = default_api.sessions.create_payment_sessions(request) + response = default_api.payment_sessions.create_payment_sessions(request) assert_response(response, 'id', diff --git a/tests/sessions/request_and_get_sessions_integration_test.py b/tests/sessions/request_and_get_sessions_integration_test.py index 53a04231..998f6480 100644 --- a/tests/sessions/request_and_get_sessions_integration_test.py +++ b/tests/sessions/request_and_get_sessions_integration_test.py @@ -6,10 +6,27 @@ from checkout_sdk.checkout_api import CheckoutApi from checkout_sdk.sessions.sessions import Category, TransactionType from tests.checkout_test_utils import assert_response -from tests.sessions.sessions_test_utils import get_browser_session, get_non_hosted_session, get_app_session +from tests.sessions.sessions_test_utils import get_browser_session, get_non_hosted_session, get_app_session, \ + get_merchant_initiated_session @pytest.mark.skip(reason='unstable') +def test_request_and_get_card_session_merchant_initiated_session(oauth_api: CheckoutApi): + browser_session = get_merchant_initiated_session() + session_request = get_non_hosted_session(browser_session, Category.PAYMENT, + ChallengeIndicator.NO_PREFERENCE, TransactionType.GOODS_SERVICE) + + request_session_response = oauth_api.sessions.request_session(session_request) + assert_response(request_session_response, 'id', 'session_secret') + + session_id = request_session_response.id + session_secret = request_session_response.session_secret + + assert_response(oauth_api.sessions.get_session_details(session_id), 'id', 'session_secret') + assert_response(oauth_api.sessions.get_session_details(session_id, session_secret), 'id') + + +# @pytest.mark.skip(reason='unstable') def test_request_and_get_card_session_browser_session(oauth_api: CheckoutApi): browser_session = get_browser_session() session_request = get_non_hosted_session(browser_session, Category.PAYMENT, diff --git a/tests/sessions/sessions_test_utils.py b/tests/sessions/sessions_test_utils.py index e43f8f61..32a74dc6 100644 --- a/tests/sessions/sessions_test_utils.py +++ b/tests/sessions/sessions_test_utils.py @@ -3,10 +3,17 @@ SessionMarketplaceData, \ SessionsBillingDescriptor, NonHostedCompletionInfo, SessionRequest, ChannelData, \ TransactionType, AppSession, SdkEphemeralPublicKey, SdkInterfaceType, UIElements, HostedCompletionInfo, \ - AuthenticationType, Category, SessionCardSource + AuthenticationType, Category, SessionCardSource, MerchantInitiatedSession, RequestType from tests.checkout_test_utils import VisaCard, random_email, phone +def get_merchant_initiated_session(): + merchant_initiated_session = MerchantInitiatedSession() + merchant_initiated_session.request_type = RequestType.RECURRING_TRANSACTION + + return merchant_initiated_session + + def get_browser_session(): browser_session = BrowserSession() browser_session.accept_header = 'Accept: *.*, q=0.1'