Skip to content

Commit 123d57b

Browse files
committed
Prioritize SCA-required responses over generic init errors
1 parent e1384c0 commit 123d57b

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

fints/client.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,21 @@ def __init__(self, bank_identifier, user_id, pin, server, customer_id=None, tan_
12731273
self._bootstrap_mode = True
12741274
super().__init__(bank_identifier=bank_identifier, user_id=user_id, customer_id=customer_id, *args, **kwargs)
12751275

1276+
def process_response_message(self, dialog, message: FinTSInstituteMessage, internal_send=True):
1277+
previous_sca_required_response = getattr(self, "_processing_sca_required_response", False)
1278+
self._processing_sca_required_response = self._message_has_sca_required_response(message)
1279+
try:
1280+
return super().process_response_message(dialog, message, internal_send=internal_send)
1281+
finally:
1282+
self._processing_sca_required_response = previous_sca_required_response
1283+
1284+
def _message_has_sca_required_response(self, message):
1285+
for seg in list(message.find_segments(HIRMG2)) + list(message.find_segments(HIRMS2)):
1286+
for response in seg.responses:
1287+
if response.code == '9075':
1288+
return True
1289+
return False
1290+
12761291
def _new_dialog(self, lazy_init=False):
12771292
if self.pin is None:
12781293
enc = None
@@ -1601,7 +1616,16 @@ def _process_response(self, dialog, segment, response):
16011616
raise FinTSClientError("Error during dialog initialization, could not fetch BPD. Please check that you "
16021617
"passed the correct bank identifier to the HBCI URL of the correct bank.")
16031618

1604-
if ((not dialog.open and response.code.startswith('9')) and not self._bootstrap_mode) or response.code in ('9340', '9910', '9930', '9931', '9942'):
1619+
sca_required_in_message = getattr(self, "_processing_sca_required_response", False)
1620+
if (
1621+
(
1622+
not dialog.open
1623+
and response.code.startswith('9')
1624+
and not self._bootstrap_mode
1625+
and not sca_required_in_message
1626+
)
1627+
or response.code in ('9340', '9910', '9930', '9931', '9942')
1628+
):
16051629
# Assume all 9xxx errors in a not-yet-open dialog refer to the PIN or authentication
16061630
# During a dialog also listen for the following codes which may explicitly indicate an
16071631
# incorrect pin: 9340, 9910, 9930, 9931, 9942

tests/test_client.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from fints.client import FinTS3PinTanClient, TransactionResponse, NeedTANResponse, ResponseStatus, NeedRetryResponse
2-
from fints.exceptions import FinTSClientPINError, FinTSClientTemporaryAuthError
2+
from fints.exceptions import FinTSClientPINError, FinTSClientTemporaryAuthError, FinTSSCARequiredError
3+
from fints.parser import FinTS3Parser
34
from decimal import Decimal
45
import pytest
56

@@ -73,6 +74,27 @@ def test_pin_locked(fints_server):
7374
str(client.pin)
7475

7576

77+
def test_sca_required_takes_precedence_over_unopened_dialog_error(fints_server):
78+
client = FinTS3PinTanClient(
79+
'12345678',
80+
'test1',
81+
'1234',
82+
fints_server,
83+
product_id="TEST-123", product_version="1.2.3",
84+
)
85+
client._bootstrap_mode = False
86+
dialog = type("Dialog", (), {"open": False})()
87+
message = FinTS3Parser().parse_message(
88+
b"HIRMG:3:2+9050::Nachricht enthaelt Fehler.'"
89+
b"HIRMS:4:2:3+9075::Starke Kundenauthentifizierung notwendig.'"
90+
)
91+
92+
with pytest.raises(FinTSSCARequiredError):
93+
client.process_response_message(dialog, message)
94+
95+
assert not client.pin.blocked
96+
97+
7698
def test_resume(fints_client, fints_server):
7799
with fints_client:
78100
system_id = fints_client.system_id

0 commit comments

Comments
 (0)