from .formals import (
KTI1, Account3, BankIdentifier,
SynchronisationMode, TwoStepParametersCommon,
- TANMediaType2, TANMediaClass4,
+ TANMediaType2, TANMediaClass4, CUSTOMER_ID_ANONYMOUS,
)
from .message import FinTSInstituteMessage, FinTSMessageOLD
from .models import (
PinTanDummyEncryptionMechanism, PinTanOneStepAuthenticationMechanism,
PinTanTwoStepAuthenticationMechanism,
)
-from .segments import HIBPA3, HIRMG2, HIRMS2, HIUPA4, HIPINS1
+from .segments import HIBPA3, HIRMG2, HIRMS2, HIUPA4, HIPINS1, HKKOM4
from .segments.accounts import HISPA1, HKSPA, HKSPA1
from .segments.auth import HKTAB, HKTAN, HKTAB4, HKTAB5, HKTAN3, HKTAN5
from .segments.depot import HKWPD5, HKWPD6
logger.debug('No HIWPD response segment found - maybe account has no holdings?')
return []
+ def get_communication_endpoints(self):
+ with self._get_dialog() as dialog:
+ hkkom = self._find_highest_supported_command(HKKOM4)
+ #hkkom = HKKOM4
+
+ responses = self._fetch_with_touchdowns(
+ dialog,
+ lambda touchdown: hkkom(
+ touchdown_point=touchdown,
+ ),
+ 'HIKOM'
+ )
+
+ return responses
+
def start_simple_sepa_transfer(self, account: SEPAAccount, iban: str, bic: str,
recipient_name: str, amount: Decimal, account_name: str, reason: str,
endtoend_id='NOTPROVIDED'):
class FinTS3PinTanClient(FinTS3Client):
def __init__(self, bank_identifier, user_id, pin, server, customer_id=None, *args, **kwargs):
- self.pin = Password(pin)
+ self.pin = Password(pin) if pin is not None else pin
self._pending_tan = None
self.connection = FinTSHTTPSConnection(server)
self.allowed_security_functions = []
super().__init__(bank_identifier=bank_identifier, user_id=user_id, customer_id=customer_id, *args, **kwargs)
def _new_dialog(self, lazy_init=False):
- if not self.selected_security_function or self.selected_security_function == '999':
+ if self.pin is None:
+ enc = None
+ auth = []
+ elif not self.selected_security_function or self.selected_security_function == '999':
enc = PinTanDummyEncryptionMechanism(1)
- auth = PinTanOneStepAuthenticationMechanism(self.pin)
+ auth = [PinTanOneStepAuthenticationMechanism(self.pin)]
else:
enc = PinTanDummyEncryptionMechanism(2)
- auth = PinTanTwoStepAuthenticationMechanism(
+ auth = [PinTanTwoStepAuthenticationMechanism(
self,
self.selected_security_function,
self.pin,
- )
+ )]
return FinTSDialog(self,
lazy_init=lazy_init,
enc_mechanism=enc,
- auth_mechanisms=[auth],
+ auth_mechanisms=auth,
)
def _ensure_system_id(self):
- if self.system_id != SYSTEM_ID_UNASSIGNED:
+ if self.system_id != SYSTEM_ID_UNASSIGNED or self.user_id == CUSTOMER_ID_ANONYMOUS:
return
with self._get_dialog(lazy_init=True) as dialog:
import io
from .formals import (
- BankIdentifier, Language2, SynchronisationMode, SystemIDStatus,
+ BankIdentifier, Language2, SynchronisationMode, SystemIDStatus, CUSTOMER_ID_ANONYMOUS,
)
from .message import (
FinTSCustomerMessage, FinTSMessage, FinTSMessageOLD, MessageDirection,
self.client.bank_identifier,
self.client.customer_id,
self.client.system_id,
- SystemIDStatus.ID_NECESSARY
+ SystemIDStatus.ID_NECESSARY if self.client.customer_id != CUSTOMER_ID_ANONYMOUS else SystemIDStatus.ID_UNNECESSARY
),
HKVVB3(
self.client.bpd_version,
self.finish_message(message)
assert message.segments[0].message_number == self.next_message_number[message.DIRECTION]
- self.messages[message.segments[0].message_number] = message
+ self.messages[message.DIRECTION][message.segments[0].message_number] = message
self.next_message_number[message.DIRECTION] += 1
response = self.client.connection.send(message)
##assert response.segments[0].message_number == self.next_message_number[response.DIRECTION]
# FIXME Better handling of HKEND in exception case
- self.messages[response.segments[0].message_number] = message
+ self.messages[response.DIRECTION][response.segments[0].message_number] = response
self.next_message_number[response.DIRECTION] += 1
if self.enc_mechanism:
from fints.fields import *
from fints.utils import RepresentableEnum, ShortReprMixin
+CUSTOMER_ID_ANONYMOUS = '9999999999'
class DataElementGroup(Container):
pass
max_length_input = DataElementField(type='num', max_length=2, _d="Maximale Länge des Eingabewertes im Zwei-Schritt-Verfahren")
allowed_format = CodeField(enum=AllowedFormat, length=1, _d="Erlaubtes Format im Zwei-Schritt-Verfahren")
text_return_value = DataElementField(type='an', max_length=30, _d="Text zur Belegung des Rückgabewertes im Zwei-Schritt-Verfahren")
- max_length_return_value = DataElementField(type='num', max_length=3, _d="Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren")
+ max_length_return_value = DataElementField(type='num', max_length=4, _d="Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren")
number_of_supported_lists = DataElementField(type='num', length=1, _d="Anzahl unterstützter aktiver TAN-Listen")
multiple_tans_allowed = DataElementField(type='jn', _d="Mehrfach-TAN erlaubt")
tan_time_dialog_association = CodeField(enum=TANTimeDialogAssociation, length=1, _d="TAN Zeit- und Dialogbezug")
max_length_input = DataElementField(type='num', max_length=2, _d="Maximale Länge des Eingabewertes im Zwei-Schritt-Verfahren")
allowed_format = CodeField(enum=AllowedFormat, length=1, _d="Erlaubtes Format im Zwei-Schritt-Verfahren")
text_return_value = DataElementField(type='an', max_length=30, _d="Text zur Belegung des Rückgabewertes im Zwei-Schritt-Verfahren")
- max_length_return_value = DataElementField(type='num', max_length=3, _d="Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren")
+ max_length_return_value = DataElementField(type='num', max_length=4, _d="Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren")
multiple_tans_allowed = DataElementField(type='jn', _d="Mehrfach-TAN erlaubt")
tan_time_dialog_association = CodeField(enum=TANTimeDialogAssociation, length=1, _d="TAN Zeit- und Dialogbezug")
cancel_allowed = DataElementField(type='jn', _d="Auftragsstorno erlaubt")
max_transfer_count = DataElementField(type='num', max_length=7, _d="Maximale Anzahl CreditTransferTransactionInformation")
sum_amount_required = DataElementField(type='jn', _d="Summenfeld benötigt")
single_booking_allowed = DataElementField(type='jn', _d="Einzelbuchung erlaubt")
+
+class ServiceType2(RepresentableEnum):
+ T_ONLINE = 1 #: T-Online
+ TCP_IP = 2 #: TCP/IP (Protokollstack SLIP/PPP)
+ HTTPS = 3 #: https
+
+class CommunicationParameter2(DataElementGroup):
+ """Kommunikationsparameter, version 2
+
+ Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Formals"""
+ service_type = IntCodeField(enum=ServiceType2, max_length=2, _d="Kommunikationsdienst")
+ address = DataElementField(type='an', max_length=512, _d="Kommunikationsadresse")
+ address_adjunct = DataElementField(type='an', max_length=512, required=False, _d="Kommunikationsadresszusatz")
+ filter_function = DataElementField(type='an', length=3, required=False, _d="Filterfunktion")
+ filter_function_version = DataElementField(type='num', max_length=3, required=False, _d="Version der Filterfunktion")
SecurityClass, SecurityDateTime, SecurityIdentificationDetails,
SecurityProfile, SecurityRole, SegmentHeader, SegmentSequenceField,
SignatureAlgorithm, SupportedHBCIVersions2, SupportedLanguages2, UPDUsage,
- UserDefinedSignature,
+ UserDefinedSignature, Language2, CommunicationParameter2,
)
from fints.utils import SubclassesMixin, classproperty
min_timeout = DataElementField(type='num', max_length=4, required=False, _d="Minimaler Timeout-Wert")
max_timeout = DataElementField(type='num', max_length=4, required=False, _d="Maximaler Timeout-Wert")
+class HKKOM4(FinTS3Segment):
+ """Kommunikationszugang anfordern, version 4
+
+ Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Formals"""
+ start_bank_identifier = DataElementGroupField(type=BankIdentifier, required=False, _d="Von Kreditinstitutskennung")
+ end_bank_identifier = DataElementGroupField(type=BankIdentifier, required=False, _d="Bis Kreditinstitutskennung")
+ max_number_responses = DataElementField(type='num', max_length=4, required=False, _d="Maximale Anzahl Einträge")
+ touchdown_point = DataElementField(type='an', max_length=35, required=False, _d="Aufsetzpunkt")
+
+class HIKOM4(FinTS3Segment):
+ """Kommunikationszugang rückmelden, version 4
+
+ Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Formals"""
+ bank_identifier = DataElementGroupField(type=BankIdentifier, _d="Kreditinstitutskennung")
+ default_language = CodeField(enum=Language2, max_length=3, _d="Standardsprache")
+ communication_parameters = DataElementGroupField(type=CommunicationParameter2, min_count=1, max_count=9, _d="Kommunikationsparameter")
+
from . import (
accounts, auth, debit, depot, dialog, message, saldo, statement, transfer,
)
cls.protected = False
def __str__(self):
- return '***' if self.protected else self.value
+ return '***' if self.protected else str(self.value)
def __repr__(self):
return self.__str__().__repr__()