Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TAN request with response code 3955 during initialization of the dialog #171

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

meyerj
Copy link

@meyerj meyerj commented Sep 28, 2024

This patch fixed a similar issue as in #155 for me with the "Sparkasse Vorderpfalz": Since a few days a push TAN is required even to request an account balance or get transactions of the last view days. Before, this was working with only the PIN.

I tracked the issue down to two issues by debugging the exchanged messages as described in the documentation, for which I propose a fix here.

  • The string "DUMMY" sent as the tan_medium_name was somehow rejected by the bank. Even the call to client.get_tan_media() in minimal_interactive_cli_bootstrap() already triggered the error as described in DKB does not accept connections anymore #121, with the first response being

    [...]
                      fints.segments.dialog.HIRMS2( # Rückmeldungen zu Segmenten
                          header = fints.formals.SegmentHeader('HIRMS', 4, 2, 4), # Segmentkopf
                          responses = [ # Rückmeldung
                                      fints.formals.Response( # Rückmeldung
                                          code = '3920',
                                          reference_element = None,
                                          text = 'Zugelassene Zwei-Schritt-Verfahren für den Benutzer.',
                                          parameters = [
                                                  '923',
                                              ],
                                      ),
                                      fints.formals.Response( # Rückmeldung
                                          code = '9955',
                                          reference_element = None,
                                          text = 'Auftrag nicht ausgeführt - Die Gerätebezeichnung ist unbekannt. (MBV07390100255)',
                                      ),
                              ],
                      ),
    [...]
    

    followed by

    [...]
                      fints.segments.dialog.HIRMG2( # Rückmeldungen zur Gesamtnachricht
                          header = fints.formals.SegmentHeader('HIRMG', 3, 2), # Segmentkopf
                          responses = [ # Rückmeldung
                                      fints.formals.Response( # Rückmeldung
                                          code = '9050',
                                          reference_element = None,
                                          text = 'Die Nachricht enthält Fehler.',
                                      ),
                                      fints.formals.Response( # Rückmeldung
                                          code = '9800',
                                          reference_element = None,
                                          text = 'Dialog abgebrochen',
                                      ),
                                      fints.formals.Response( # Rückmeldung
                                          code = '9010',
                                          reference_element = None,
                                          text = 'Die angegebene Bankreferenz/Dialog-ID ist nicht gültig.',
                                      ),
                              ],
                      ),
                      fints.segments.dialog.HIRMS2( # Rückmeldungen zu Segmenten
                          header = fints.formals.SegmentHeader('HIRMS', 4, 2, 3), # Segmentkopf
                          responses = [ # Rückmeldung
                                      fints.formals.Response( # Rückmeldung
                                          code = '9010',
                                          reference_element = None,
                                          text = 'Auftrag wegen genereller Fehler in Auftragsnachricht nicht verarbeitet.',
                                      ),
                              ],
                      ),
    [...]
    

    after the subsequent call to client.get_sepa_accounts() (HKSPA1), likely because the dialog was never actually accepted by the server. Should a 9xxx response code already trigger an exception in FinTSDialog.init()?

    Sending an empty tan_medium_name works and triggers the response in the next bullet point. So I set client.selected_tan_medium = '' before calling minimal_interactive_cli_bootstrap(client) to already skip the call to get_tan_media() (with my patch). I guess this only works because there is only one for my account. I tried different strings, the name of my device and the UUID shown in the Push Tan app in "Verbindungen", nothing worked. And even get_tan_media() requires a TAN when the dialog starts, so it is a kind of chicken-and-egg problem and I have not found a way to not add the HKTAN7 segment to the dialog initialization request triggered by get_tan_media().

  • With the empty tan_medium_name the bank server responds with a TAN request and code 3955. That was added in Fix #155 -- Implement HKTAN7 and decoupled TAN process #162 to the client's _send_with_possible_retry() method to react on a TAN request when sending a request after the dialog has been established, but not in FinTSDialog.init() if the bank already sends that response:

    [...]
                      fints.segments.dialog.HIRMG2( # Rückmeldungen zur Gesamtnachricht
                          header = fints.formals.SegmentHeader('HIRMG', 3, 2), # Segmentkopf
                          responses = [ # Rückmeldung
                                      fints.formals.Response( # Rückmeldung
                                          code = '3060',
                                          reference_element = None,
                                          text = 'Bitte beachten Sie die enthaltenen Warnungen/Hinweise.',
                                      ),
                                      fints.formals.Response( # Rückmeldung
                                          code = '3920',
                                          reference_element = None,
                                          text = 'Zugelassene Zwei-Schritt-Verfahren für den Benutzer.',
                                          parameters = [
                                                  '923',
                                              ],
                                      ),
                              ],
                      ),
                      fints.segments.dialog.HIRMS2( # Rückmeldungen zu Segmenten
                          header = fints.formals.SegmentHeader('HIRMS', 4, 2, 5), # Segmentkopf
                          responses = [ # Rückmeldung
                                      fints.formals.Response( # Rückmeldung
                                          code = '3955',
                                          reference_element = None,
                                          text = 'Auftrag empfangen - Bitte Auftrag in Ihrer App freigeben.(MBT62870200005)',
                                      ),
                              ],
                      ),
                      fints.segments.auth.HITAN7( # Zwei-Schritt-TAN-Einreichung Rückmeldung, version 7
                          header = fints.formals.SegmentHeader('HITAN', 5, 7, 5), # Segmentkopf
                          tan_process = '4', # TAN-Prozess
                          task_reference = '3115-09-28-19.28.05.705284', # Auftragsreferenz
                          challenge = 'Bitte Auftrag in Ihrer App freigeben.', # Challenge
                      ),
    [...]
    

    So I assume it was an oversight in Fix #155 -- Implement HKTAN7 and decoupled TAN process #162 to not also patch the other method?

So these two changes work for me with an application similar to the one in the troubleshooting guide. I have not found a way to retrieve transactions without having to confirm that with a push TAN via the app interactively. Ideally there would be a way to remember that "device" at least for a couple of days, like it also works with interactive logins via the web page.

This patch may resolve #121 and #165, at least when also setting selected_tan_medium to an empty string (or something else if you already know a valid value) before the call to minimal_interactive_cli_bootstrap(f):

f = FinTS3PinTanClient(*client_args, product_id=product_id)
f.selected_tan_medium = ''
minimal_interactive_cli_bootstrap(f)

@DerMistkaefer
Copy link

Thanks a lot for this. This fixed the problem for me with "Erzgebirgsparkasse".
But I still need to set f.selected_tan_medium = ''

The second problem is that I now need to confirm the python script as a new device on my bank account every time.
Can we implement something that identify the device to the bank?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DKB does not accept connections anymore
2 participants