]> git.ipfire.org Git - thirdparty/python-fints.git/commitdiff
Parse TAN challenge
authorRaphael Michel <mail@raphaelmichel.de>
Wed, 25 Jul 2018 14:26:24 +0000 (16:26 +0200)
committerRaphael Michel <mail@raphaelmichel.de>
Wed, 25 Jul 2018 14:26:24 +0000 (16:26 +0200)
fints/client.py
fints/dialog.py
fints/message.py
fints/models.py

index 569d0dcf45fda1e16c606db89e68579efd1ee669..c00a8bb55826098acda99deabdf9738d5e733479 100644 (file)
@@ -10,7 +10,7 @@ from .connection import FinTSHTTPSConnection
 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
@@ -268,9 +268,9 @@ class FinTS3Client:
 
         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,
@@ -290,33 +290,48 @@ class FinTS3Client:
         }
         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()
index 7f1f05dc34858ad9a91dcccbba156367caff4937..dc3c395f9a19c892cdd6e5e3242a09d1066716dc 100644 (file)
@@ -62,6 +62,7 @@ class FinTSDialog:
         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))
@@ -69,6 +70,7 @@ class FinTSDialog:
         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()
 
index 97af1b92a80d67a4bce177778743caab58b67abd..f75038a974258ae2ba06dc0b6917a774a3c29472 100644 (file)
@@ -66,7 +66,6 @@ class FinTSResponse:
     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)
index 04071e087ba5deb05d741098a6d1f5c7f2dc4396..4da5e5f69cc1e9cfa59280d8fe31b70f933ea352 100644 (file)
@@ -8,9 +8,7 @@ Holding = namedtuple('Holding',
                      '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)
@@ -21,12 +19,17 @@ class TANMethod:
     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',
@@ -36,9 +39,38 @@ class TANMethod5(TANMethod):
 
 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