from .dialog import FinTSDialog
from .message import FinTSMessage
from .message import FinTSResponse
-from .models import SEPAAccount, TANMethod
+from .models import SEPAAccount, TANMethod, TANChallenge6, TANChallenge5, TANChallenge3, TANChallenge4
from .segments.accounts import HKSPA
from .segments.auth import HKTAN, HKTAB
from .segments.depot import HKWPD
return 'Ok'
- def start_simple_sepa_transfer(self, account: SEPAAccount, tan_method, iban: str, bic: str, recipient_name: str,
- amount: Decimal, account_name: str, reason: str, endtoend_id='NOTPROVIDED',
- tan_description=''):
+ def start_simple_sepa_transfer(self, account: SEPAAccount, tan_method: TANMethod, iban: str, bic: str,
+ recipient_name: str, amount: Decimal, account_name: str, reason: str,
+ endtoend_id='NOTPROVIDED', tan_description=''):
config = {
"name": account_name,
"IBAN": account.iban,
}
sepa.add_payment(payment)
xml = sepa.export().decode()
- self.start_sepa_transfer(account, xml, tan_method, tan_description)
+ return self.start_sepa_transfer(account, xml, tan_method, tan_description)
+
+ def _get_start_sepa_transfer_message(self, dialog, account: SEPAAccount, pain_message: str, tan_description):
+ segHKCCS = HKCCS(3, account, pain_message)
+ segHKTAN = HKTAN(4, 4, '', tan_description)
+ return self._new_message(dialog, [
+ segHKCCS,
+ segHKTAN
+ ])
def start_sepa_transfer(self, account: SEPAAccount, pain_message: str, tan_method, tan_description=''):
dialog = self._new_dialog()
dialog.sync()
-
- dialog.tan_mechs = [tan_method.security_feature]
+ dialog.tan_mechs = [tan_method]
dialog.init()
- def _get_msg():
- segHKCCS = HKCCS(3, account, pain_message)
- segHKTAN = HKTAN(4, 4, '', tan_description)
- return self._new_message(dialog, [
- segHKCCS,
- segHKTAN
- ])
-
with self.pin.protect():
- logger.debug('Sending HKCCS: {}'.format(_get_msg()))
+ logger.debug('Sending HKCCS: {}'.format(self._get_start_sepa_transfer_message(
+ dialog, account, pain_message, tan_description
+ )))
- resp = dialog.send(_get_msg())
+ resp = dialog.send(self._get_start_sepa_transfer_message(dialog, account, pain_message, tan_description))
logger.debug('Got HKCCS response: {}'.format(resp))
- response = {}
- response['response'] = resp
- response['dialog'] = dialog
- return response
+ seg = resp._find_segment('HITAN')
+ s = split_for_data_groups(seg)
+ spl = split_for_data_elements(s[0])
+ if spl[2] == '3':
+ model = TANChallenge3
+ elif spl[2] == '4':
+ model = TANChallenge4
+ elif spl[2] == '5':
+ model = TANChallenge5
+ elif spl[2] == '6':
+ model = TANChallenge6
+ else:
+ raise NotImplementedError(
+ "HITAN segment version {} is currently not implemented".format(
+ spl[2]
+ )
+ )
+ return model(dialog, *s[1:1 + len(model.args)])
def get_tan_methods(self):
dialog = self._new_dialog()
self.bankname = resp.get_bank_name()
self.hksalversion = resp.get_hksal_max_version()
self.hkkazversion = resp.get_hkkaz_max_version()
+ self.hktanversion = resp._get_segment_max_version('HKTAN')
self.tan_mechs = resp.get_supported_tan_mechanisms()
logger.debug('Bank name: {}'.format(self.bankname))
logger.debug('Dialog ID: {}'.format(self.dialogid))
logger.debug('HKKAZ max version: {}'.format(self.hkkazversion))
logger.debug('HKSAL max version: {}'.format(self.hksalversion))
+ logger.debug('HKTAN max version: {}'.format(self.hktanversion))
logger.debug('TAN mechanisms: {}'.format(', '.join(str(t) for t in self.tan_mechs)))
self.end()
RE_UNWRAP = re.compile('HNVSD:\d+:\d+\+@\d+@(.+)\'\'')
RE_SEGMENTS = re.compile("'(?=[A-Z]{4,}:\d|')")
RE_SYSTEMID = re.compile("HISYN:\d+:\d+:\d+\+(.+)")
- RE_TANMECH = re.compile('\d{3}')
def __init__(self, data):
self.response = self._unwrap(data)
'ISIN name market_value value_symbol valuation_date pieces total_value acquisitionprice')
-class TANMethod:
- args = ['security_feature']
-
+class DataClass:
def __init__(self, *args, **kwargs):
for i, a in enumerate(args):
setattr(self, self.args[i], a)
def __repr__(self):
return '{}({})'.format(
self.__class__.__name__,
- ', '.join(['{}={}'.format(k, repr(getattr(self, k))) for k in self.args])
+ ', '.join(['{}={}'.format(k, repr(getattr(self, k, None))) for k in self.args])
)
+class TANMethod(DataClass):
+ pass
+
+
class TANMethod5(TANMethod):
# Source: PIN/TAN docs – Verfahrensparameter Zwei-Schritt-Verfahren, Elementversion #5
+ version = 5
args = ['security_feature', 'tan_process', 'tech_id', 'zka_id', 'zka_version', 'name', 'max_length_input',
'allowed_format', 'text_returnvalue', 'max_length_returnvalue', 'number_of_supported_lists',
'multiple_tans_allowed', 'tan_time_dialog_association', 'tan_list_number_required', 'cancel_allowed',
class TANMethod6(TANMethod):
# Source: PIN/TAN docs – Verfahrensparameter Zwei-Schritt-Verfahren, Elementversion #6
+ version = 6
args = ['security_feature', 'tan_process', 'tech_id', 'zka_id', 'zka_version', 'name', 'max_length_input',
'allowed_format', 'text_returnvalue', 'max_length_returnvalue', 'multiple_tans_allowed',
'tan_time_dialog_association', 'cancel_allowed', 'sms_charge_account_required',
'principal_account_required',
'challenge_class_required', 'challenge_structured', 'initialization_mode', 'description_required',
'hhd_uc_required', 'supported_media_number']
+
+
+class TANChallenge(DataClass):
+ pass
+
+
+class TANChallenge3(TANChallenge):
+ version = 3
+ args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_datetime',
+ 'tan_list_number', 'ben', 'medium_description']
+
+
+class TANChallenge4(TANChallenge):
+ version = 4
+ args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime',
+ 'tan_list_number', 'ben', 'medium_description']
+
+
+class TANChallenge5(TANChallenge):
+ version = 5
+ args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime',
+ 'tan_list_number', 'ben', 'medium_description']
+
+
+class TANChallenge6(TANChallenge):
+ version = 6
+ args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime',
+ 'medium_description']
\ No newline at end of file