nemiah / phpFinTS

PHP library to communicate with FinTS/HBCI servers
MIT License
130 stars 42 forks source link

Probleme beim Volksbank getStatements #448

Closed seem2810 closed 2 months ago

seem2810 commented 3 months ago

Hallo zusammen,

mein Code funktioniert mit Sparkassen und Deutschen Banken. Jetzt haben wir ein Konto bei der Volksbank und auf einmal klappt es nicht, die Statements zu laden.

Nutze ich SecureTan Push, erhalte ich einen Fehler. Nutze ich nur SecureTan muss ich dauerhaft in einer Endlos-Schleife einen TAN eingeben.

Jemand eine Idee?

 'message' => 'FinTS errors:
9050 (global): Die Nachricht enthält Fehler.
9800 (global): Dialog abgebrochen
9120 (global): Die Nachricht hat nicht die erwartete Nachrichtennummer.
9010 (wrt seg 3): Auftrag wegen genereller Fehler in Auftragsnachricht nicht verarbeitet.
Request segments:
HKTAN:3:7+S++++egV40vM/9JABAADga2wOh7BCCgQA+N\'',
ampaze commented 3 months ago

Klingt als würdest du die "Session" nicht korrekt speichern.

Grob sieht das so aus:

Nach TAN-benötigt-Antwort der Bank

$session = $fints->persist(true);

Vor dem Senden der TAN

$fints->loadPersistedInstance($session)
seem2810 commented 2 months ago

Danke! Nun erhalte ich die meldung, dass nur der Push-Tan freigeschaltet ist. Hier erhalte ich nach der Freigabe nach wie vor einen Fehler..

[2024-08-05 08:37:48] developing.ERROR: Fhp\BaseAction::getNextRequest(): Argument #1 ($bpd) must be of type Fhp\Protocol\BPD, null given, called in nemiah/php-fints/lib/Fhp/PaginateableAction.php on line 104 {"userId":1,"exception":"[object] (Exception(code: 0): Fhp\\BaseAction::getNextRequest(): Argument #1 ($bpd) must be of type Fhp\\Protocol\\BPD, null given, called in nemiah/php-fints/lib/Fhp/PaginateableAction.php on line 104 at /src/Connectors/HBCI.php:324)
Philipp91 commented 2 months ago

Das scheint mit https://github.com/nemiah/phpFinTS/commit/4e12ffbef9bc73a6ba563e83b77339b4b3b37d8a und https://github.com/nemiah/phpFinTS/commit/4c1104ff3bc8790cc39c1ab9d34749595d33f72f zusammenzuhängen. Hier wird aus ?BPD ein BPD ohne weitere Prüfung.

@ampaze

ampaze commented 2 months ago

@seem2810

Auf die Schnelle könntest du $session = $fints->persist(); nutzen d.h. ohne Parameter aufrufen, dann werden die Bankparameterdaten auch in der Session gespeichert.


@Philipp91

Meine Idee den Fehler zu beheben, wäre in FinTs::execute bei paginierbaren Actions, die BPD frisch abzurufen, wenn sie nicht da sind.

if ($action instanceof PaginateableAction) {
    $this->ensureBpdAvailable();
}

$requestSegments = $action->getNextRequest($this->bpd, $this->upd);
seem2810 commented 2 months ago

Habe ich schon versucht...

        // SAVE TAN REQUEST:
        $persistedAction = serialize($action);
        $persistedFints = $this->fints->persist();
        \Cache::put('crBaRe', serialize([$persistedFints, $persistedAction]), now()->addMinutes(10));

Dann der load in handleDecoupleCheck()

        $currentTanRequest = \Cache::get('crBaRe');
        if (!empty($currentTanRequest)) {
            list($persistedInstance, $persistedAction) = unserialize($currentTanRequest);

            if ($this->credentials == null) {
                $this->handleException('missing_login');
            }

            $this->fints = \Fhp\FinTs::new($this->options, $this->credentials, $persistedInstance);
            $action = unserialize($persistedAction);
            $timeout = 30;

            $tanMode = $this->fints->getSelectedTanMode();
            $tanRequest = $action->getTanRequest();

            try {
                if ($tanMode->getMaxDecoupledChecks() !== 0 && $this->attempt >= $tanMode->getMaxDecoupledChecks()) {
                    return $this->handleException();
                }

                if (!$this->fints->checkDecoupledSubmission($action)) {
                    if ($tanMode->allowsAutomatedPolling()) $timeout = $tanMode->getPeriodicDecoupledCheckDelaySeconds();

                    if ($timeout < 5) $timeout = 5;

                    $this->attempt++;

                    return [
                        'result' => 'tan_confirm',
                        'tanMode' => $tanMode,
                        'tanRequest' => $tanRequest,
                        'attempt' => $this->attempt,
                        'timeout' => $timeout
                    ];
                }
            } catch (\Throwable $exception) {
                return $this->handleException($exception->getMessage());
            }
        }
Philipp91 commented 2 months ago

Hier erhalte ich nach der Freigabe nach wie vor einen Fehler..

Bitte schick uns noch den kompletten Stack Trace von dem Fehler. Offenbar wird ja execute() aufgerufen, aber von wo genau?

Philipp91 commented 2 months ago

Meine Idee den Fehler zu beheben, wäre in FinTs::execute bei paginierbaren Actions, die BPD frisch abzurufen, wenn sie nicht da sind.

Ist einen Versuch wert: https://github.com/nemiah/phpFinTS/pull/449

Wenn es damit funktioniert, können wir es vielleicht noch an die korrekte Stelle schieben (anhand vom Stack Trace). Weil an dieser zentralen Stelle sollte es eigentlich nicht nötig sein, die BPD abzurufen. Ich frage mich, ob das hier in einem submitTan()-Aufruf passiert, wo nach der TAN-Eingabe die erste von mehreren Seiten zurückkommt. Normalerweise senden Banken dann die BPD auch gleich mit und wir extrahieren sie hier, aber das kann auch false zurückgeben und nichts tun. Wenn das das Szenario hier ist, sollte nwir den ensureBpdAvailable() Aufruf lieber hier einfügen.

Ah und ich glaube, beides wird nicht funktionieren. Weil execute() setzt voraus, dass ein Dialog offen ist (außer man ruft es zum Dialog-Öffnen auf) und ensureBpdAvailable() setzt das Gegenteil voraus. Also können wir nicht ensureBpdAvailable() aus execute() aufrufen.

Wenn es wirklich das oben beschriebene Szenario ist, sollten wir dafür sorgen, dass die Bank uns die BPD liefert wenn wir die TAN schicken. execute() verwendet buildMessage() und daher createWrappedMessage(). Irgendwo dort könnten wir evtl. ein HKVVB hinzufügen, so wie in ensureBpdAvailable(). Nur dass letzteres mit createPlainMessage() arbeitet. D.h. man müsste sich erst schlaumachen, ob das HKVVB in die innere Message oder in den Wrapper gehört.

seem2810 commented 2 months ago

Okay! Nun, keine Ahnung warum, erhalte ich keinen Fehler mehr... (Ein bug in meiner Software war, dass beim decoubleCheck die neue Session nicht gespeichert wird) Aber unabhänig davon, erhalte ich nun ein true beim $check, sobald ich freigegeben habe. Warum auch immer, führt er die restliche Transaktion dennoch nicht aus - bzw. ich gehe davon aus, dass er ausführt, aber anschließend fehlt der Programmcode der das verarbeitet.

Da muss ich mir dann mal überlegen, wie ich das hin kriege.. Bei der Volksbank muss ich auch jeden Bankabruf freigeben, bei der Sparkasse & DB nicht.. Vermutlich geht deswegen mein Code bei den anderen Banken.

     $check = $this->fints->checkDecoupledSubmission($this->action);

                \Log::debug('handleDecoupledRequest', [
                    'state' => $check,
                    'request' => request()->all()
                ]);
                if (!$check) {
seem2810 commented 2 months ago

Okay! Yes. Damit geht es nun. Ich calle meine readTransactions methode anschließend und kriege die Transaktionen.

Vorgang daher closed.