PK!aPPwirecard/__init__.pyfrom .wirecard import AccountHolder, Card, RequestedAmount, Wirecard # noqa F401PK!Xwirecard/constants.py# Transaction Types CHECK_ENROLLMENT = 'check-enrollment' PURCHASE = 'purchase' # Transaction States SUCCESS = 'success' # Return Codes and Transaction Statuses # https://document-center.wirecard.com/display/PTD/Return+Codes+and+Transaction+Statuses CREATION_SUCCESS_ID = '201.0000' CREATION_SUCCESS = 'Creation Success' CARD_ELIGIBLE_3D_ID = '200.1077' CARD_ELIGIBLE_3D = 'Card/Cardholder eligible for 3-D authentication process' PK!swirecard/exceptions.pyclass WirecardFailedInit(Exception): pass class WirecardInvalidCard(Exception): pass class WirecardInvalidRequestedAmount(Exception): pass class WirecardFailedTransaction(Exception): def __init__(self, transaction_id, action, statuses): self.transaction_id = transaction_id self.action = action self.statuses = statuses super().__init__(transaction_id, action, statuses) PK!ⷱvvwirecard/wirecard.pyfrom base64 import b64encode from decimal import Decimal import os import uuid from glom import glom import requests from .constants import * # noqa F403 from .exceptions import ( WirecardFailedInit, WirecardFailedTransaction, WirecardInvalidCard, ) class RequestedAmount: def __init__(self, amount, currency): self.amount = Decimal(amount) self.currency = currency self.validate() def as_dict(self): return { 'value': self.amount, 'currency': self.currency, } def validate(self): if len(self.currency) != 3: raise WirecardInvalidCard('currency length should be 3') integer_part, fractional_part = str(self.amount).split('.') if len(integer_part) > 18: raise WirecardInvalidCard('integer_part length should be less than 8') if len(fractional_part) > 2: raise WirecardInvalidCard('fractional_part length should be less than 2') class AccountHolder: def __init__(self, first_name, last_name, **kwargs): self.first_name = first_name self.last_name = last_name self.other_info = kwargs def as_dict(self): return { 'first-name': self.first_name, 'last-name': self.last_name, **self.other_info, } class Card: def __init__(self, account_number, expiration_month, expiration_year, security_code, _type): self.account_number = account_number self.expiration_month = expiration_month self.expiration_year = expiration_year self.security_code = security_code self.type = _type self._clean() self.validate() def _clean(self): self.type = self.type.lower() self.account_number = self.account_number.replace(' ', '') def as_dict(self): return { 'account-number': self.account_number, 'expiration-month': self.expiration_month, 'expiration-year': self.expiration_year, 'card-security-code': self.security_code, 'card-type': self.type, } def validate(self): if len(self.expiration_month) != 2: raise WirecardInvalidCard('expiration_month length should be 2') if len(self.expiration_year) != 4: raise WirecardInvalidCard('expiration_year length should be 4') if len(self.security_code) != 3: raise WirecardInvalidCard('security_code length should be 3') class Wirecard: def __init__(self, username=None, password=None, merchant_account_id=None, url=None): self.username = os.getenv('WIRECARD_USERNAME', username) self.password = os.getenv('WIRECARD_PASSWORD', password) self.merchant_account_id = os.getenv('WIRECARD_MERCHANT_ACCOUNT_ID', merchant_account_id) self.url = os.getenv('WIRECARD_API_URL', url) self.basic_authorization = None self.validate() def check_3d_enrollment(self, card, account_holder, requested_amount): data = { 'payment': { 'merchant-account-id': { 'value': self.merchant_account_id, }, 'request-id': self._generate_request_id(), 'transaction-type': CHECK_ENROLLMENT, 'requested-amount': requested_amount.as_dict(), 'account-holder': account_holder.as_dict(), 'card': card.as_dict(), }, } headers = self._make_headers() result = requests.post(self.url, json=data, headers=headers) response = result.json() statuses = glom(response, 'payment.statuses.status') statuses_codes = [status.get('code') for status in statuses] transaction_state = glom(response, 'payment.transaction-state') success_conditions = [ CREATION_SUCCESS_ID in statuses_codes, CARD_ELIGIBLE_3D_ID in statuses_codes, transaction_state == SUCCESS, ] if all(success_conditions): return response transaction_id = glom(response, 'payment.transaction-id') raise WirecardFailedTransaction(transaction_id, 'check_3d_enrollment', statuses) def payment_request_with_pares(self, pares, parent_transaction_id): data = { 'payment': { 'merchant-account-id': { 'value': self.merchant_account_id, }, 'request-id': self._generate_request_id(), 'transaction-type': PURCHASE, 'parent-transaction-id': parent_transaction_id, 'three-d': { 'pares': pares, }, }, } headers = self._make_headers() result = requests.post(self.url, json=data, headers=headers) response = result.json() statuses = glom(response, 'payment.statuses.status') statuses_codes = [status.get('code') for status in statuses] transaction_state = glom(response, 'payment.transaction-state') success_conditions = [ CREATION_SUCCESS_ID in statuses_codes, transaction_state == SUCCESS, ] if all(success_conditions): return response raise WirecardFailedTransaction( parent_transaction_id, 'payment_request_with_pares', statuses, ) def validate(self): failed_conditions = [ self.username is None, self.password is None, self.merchant_account_id is None, self.url is None, ] if any(failed_conditions): message = 'Parameters username, password, merchant_account_id and url are required' raise WirecardFailedInit(message) def _generate_request_id(self): return str(uuid.uuid4()) def _generate_basic_authorization(self): if self.basic_authorization: return self.basic_authorization username_password = f'{self.username}:{self.password}' basic_credentials = b64encode(bytes(username_password.encode())).decode() self.basic_authorization = f'Basic {basic_credentials}' return self.basic_authorization def _make_headers(self): return { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': self._generate_basic_authorization(), } PK!HڽTUwirecard-0.1.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H. !wirecard-0.1.0.dist-info/METADATAQ]O0}h&`06@T1s+lޡ⫼5'>* wxd*Aw&\ 9p)<JU@EhE湷mi3!kfr"Cu {="Ƹ)+M)=y[,Gёc92FfσAZk3t@|ok_c|pDT{{a/ʁ-3AрMOŨO&ށr^ 7 IUJܗկ|PK!HhDUwirecard-0.1.0.dist-info/RECORD}ιv@@ol* 0QٗOMҽג^]rٳeG;#VN8U3kHf5(W;Z5iGҲҪ|n :k!75$}~+ֹwPW6Yb0˰/ w>~V|Jqh^PlJ <`K͢2%) xn,v݉Tڇ 2<4m RŌ$ e(6_S$Z(ؓS{ߨ؂,BFt鰱NBrmF dLPK!aPPwirecard/__init__.pyPK!Xwirecard/constants.pyPK!sgwirecard/exceptions.pyPK!ⷱvvEwirecard/wirecard.pyPK!HڽTUwirecard-0.1.0.dist-info/WHEELPK!H. !}wirecard-0.1.0.dist-info/METADATAPK!HhDUwirecard-0.1.0.dist-info/RECORDPKn!