Comments (19)
Es spricht ja nichts dagegen ruhig beide Werte zu verwenden, falls irgendwann eine Bank doch unterschiedliche Wartzeiten erfordert. Hab die Änderungen hier in einer PR hochgeladen. Alles weitere lässt sich dann ja dort besprechen.
from hbci4java.
Die Prüfung, ob die Freigabe in der PushTAN App durchgeführt wurde, ist schlicht nicht implementiert, da das den Aufwand deutlich erhöht hätte. Du kannst mir hierzu gern einen PR senden, welcher diesen Fall mit berücksichtigt.
from hbci4java.
Danke für die schelle Antwort! Ich werde definitiv mal einen Blick in die Implementierung werfen.
Nach meiner naiven Vorstellung muss hierfür ja "nur" bei der 3956 Nachricht wiederholt der NEED_PT_DECOUPLED
callback aufgerufen werden. Da fehlt mir aber vermutlich einfach das Verständnis in der Materie.
Hast du irgendwelche Tipps/Hinweise, weswegen das ganze eigentlich komplexer ist?
from hbci4java.
Du musst im Hintergrund einen zweiten Thread starten, den korrekt mit der aktuellen HBCI4Java-Session initialisieren und dann in zyklischen Abständen bei der Bank mit einem speziellen Dialog pollen, um den aktuellen Status abzufragen. Das gesamte Multi-Threading innerhalb einer HBCI-Session ist bisher gar nicht vorgesehen.
from hbci4java.
Ah, verstehe. Das ist in sofern interessant, als das ich für meinen use-case diese Library bereits in einem multithreading context verwende.
Ich starte den HBCI Dialog in einem neuen thread, welchen ich pausiere, wenn ein relevanter callback kommt. Dann kriegt der Nutzer im Frontend Bescheid, und mit der relevanten Antwort wird der thread, und damit auch der callback resumed.
Demnach war meine Vorstellung von der Decoupled Implementierung in HBCI4Java komplett ohne threads. Es würde einfach bei jedem callback Return nach NEED_PT_DECOUPLED
der Status des Dialog's geprüft, und bei einer 3956 Antwort der selbe callback erneut aufgerufen. Ob das dann alle 5 Sekunden in einem neuen Thread, oder nur manuell nach Interaktion des user's passiert sollte dem Nutzer der Library überlassen sein.
Entspricht das einfach nicht deiner Vorstellung von dem Decoupled Feature, oder gibt es technische Gründe, weswegen eine solche Implementierung problematisch wäre?
from hbci4java.
Das weiss ich nicht. So genau habe ich das Thema nicht beleuchtet.
from hbci4java.
Hallo @guyyst
Ich sitze gerade selber an dem Thema und versuch die PushTan zu implementieren. Noch bin ich nicht an einem GV dran, sondern lediglich dabei ein Vertrauenswürdiges Gerät zu authorisieren. Dafür schaue ich grad in den HBCIUser rein, da die erste PushTan bereits beim fetchUPD auftritt.
Bist Du mit dem Thema weitergekommen? Ich frage mich derzeit generell zwei Dinge:
- Wie frage ich die Bank ab, ob die Pushnachricht bereits positiv in der App bestätigt wurde?
- Für GVs, wie würde ich eine solche Abfrage im Callback auslösen können?
Über einen Austausch würde ich mich sehr freuen.
Viele Grüße,
Alexander
from hbci4java.
Hallo @ahachmann, ich bin, wie in meinem oberen Kommentar als Idee erwähnt, einen "einfacheren" Weg gegangen, indem ich lediglich den selben Job, welcher aktuell ja bereits 1 mal nach einem NEED_PT_DECOUPLED
callback ausgeführt wird, wiederhole, wenn die Response den code 3956
enthält.
Meine Lösung basiert also zu 100% darauf, dass Nutzer der Library bei jedem NEED_PT_DECOUPLED
callback den thread für eine vernünftige Zeit pausieren, sonst pausiert die Library selbst, um Refresh-Spamming zu verhindern. Es wird keinerlei Multi-Threading in der library gemacht.
Mein erster Ansatz für diese Implementierung ist hier, mit dem relevanten Task-Redo code in GVTAN2Step.java
. Der Redo-Teil ist eigentlich relativ kurz, das ganze drum-herum sind nur die checks der BPDs welche die Refresh-Parameter definieren.
Ich bin mir nicht sicher wie akzeptabel dieser Ansatz für die Library ist, oder ob eine komplexere Multi-Threading Lösung mit automatischem Background-Refreshing erforderlich ist. Für meine Zwecke ist die von mir implementiere Funktionalität genau richtig, da meine Programm sich bereits um das Multi-Threading kümmert.
@willuhn Vielleicht kannst du einen Blick drauf werfen und deine Meinung abgeben, bevor ich das ganze in einen Pull-Request Zustand bringe. Einige Fragen und Unsicherheiten habe ich eh noch bevor das ganze benutzbar wäre.
from hbci4java.
Danke für den Code-Vorschlag. Ich glaube, ich verstehe ihn aber noch nicht.
- HBCI4Java müsste doch eigentlich zyklisch eine erneute dedizierte Nachricht mit dem HKTAN im Sinne von "Hat der User zwischenzeitlich bestätigt?" an die Bank senden. Das Senden dieser Nachricht ist in dem Code doch gar nicht enthalten. Wo passiert das denn?
- Wenn die Bank im HITAN mit einem Code 3956 antwortet, um zu signalisieren, dass der User die Anfrage auf dem Smartphone noch nicht bestätigt hat, dann wird erneut ein Callback des Typs NEED_PT_DECOUPLED ausgelöst. Die Anwendung, welche HBCI4Java verwendet, kann dann aber nicht unterscheiden, ob es sich um eine erneute Rückfrage zu dem vorherigen Callback im Sinne von "Du hast im Smartphone immer noch nicht auf "OK" geklickt" handelt oder es die Anfrage für einen anderen Geschäftsvorfall ist. Die Anwendung sollte das unterscheiden können, um unterschiedliche Dialoge anzeigen zu können.
- Dass das Warten per "Thread.sleep(sleepMs)" nur noch über die Rest-Zeit abzüglich Dauer des Callbacks passiert, finde ich eine gute Lösung. Auf die Weise hat die aufrufende Anwendung die Möglichkeit, dass Warten für den User zu visualisieren. Aus meiner Sicht wäre es hier sinnvoll, wenn die Anwendung die wartende Zeit mit übergeben bekommen würde. Dann wüsste sie, wie lange sie den User hinhalten muss, bevor der erneut auf "OK" klicken kann. Auch aufgrund des vorherigen Punkts wäre es vermutlich sinnvoll, einen zusätzlichen Callback "NEED_PT_DECOUPLED_RETRY" einzuführen, der das Timeout per Payload übergeben kriegt.
from hbci4java.
-
Nach meinem Verständnis ist die HKTAN welche hier erstellt wird genau diese "Hat der User zwischenzeitlich bestätigt?" Nachricht. Wie in den Specs beschrieben, hat diese 2. HKTAN beim Decoupled Verfahren ja den Prozess
S
, und erhält bei noch ausstehender Bestätigung in der HITAN Antwort den Code3956
. Bevor ich irgendwelche Änderungen gemacht habe, war das ja bereits der Ablauf. Mit meinem Change wird lediglich als Reaktion auf den Code3956
durch diese Zeile inGVTAN2Step.java
der selbe HKTAN wiederholt. Also quasi der Zurück-Sprung auf Schritt 2a. Ich dachte nicht, dass dafür eine dedizierte Nachricht erstellt werden müsste, da es ja eigentlich exakt die selbe Abfrage ist. (Und da es bei meinen Tests auch genau so geklappt hat :p). -
Ich hab einen neuen Commit gemacht, und nach deinem Vorschlag einen
NEED_PT_DECOUPLED_RETRY
callback hinzugefügt. BeideNEED_PT_DECOUPLED
callbacks liefern jetzt auch inretData
die erforderliche Sleep Dauer. Das ganze hatte ich vorher dadurch gelöst, dassgetMinimumTimeBeforeFirstDecoupledRefresh()
undgetMinimumTimeBeforeNextDecoupledRefresh()
einfach öffentlich waren, und die aufrufenden Anwendung somit bereits die Möglichkeit hatte die Wartezeit zu visualisieren. Aber ich gebe dir Recht, es ist einfacher und sauberer das überretData
zu erledigen.
from hbci4java.
- Nach meinem Verständnis ist die HKTAN welche hier erstellt wird genau diese "Hat der User zwischenzeitlich bestätigt?" Nachricht.
Korrekt. Aber wie löst du diese HBCI-Nachricht nochmal erneut aus? Erstellst du hierfür in deinem Code nochmal separat ein "GVTAN2Step", das du dann manuell an die Bank sendest? Das muss ja eine einzelne HBCI-Nachricht sein, die nur genau das enthält.
from hbci4java.
Ah verstehe, da habe ich mich auf den existierenden Code in HBCIDialog.java
verlassen, welcher task.redo()
checked, und falls es einen Redo gibt, eine neue Message mit nur diesem redo-job erstellt.
from hbci4java.
Kannst du vielleicht mal ein Schnipsel des Codes von deiner Seite posten? Ich kann mir immer noch nicht so richtig erklären, wie du die Nachfrage-Nachricht auslöst.
from hbci4java.
Also mein Verständnis des Ablaufs, durch welchen die Nachfrage-Nachricht wiederholt versandt wird, ist wie folgt:
- Die aller erste Status-Nachfrage wird in
AbstractPinTanPassport.java
mit diesen Zeilen erstellt und der queue hinzugefügt:
final GVTAN2Step hktan2 = (GVTAN2Step) handler.newJob("TAN2Step");
hktan2.setProcess(proc);
hktan2.setExternalId(task.getExternalId()); // externe ID auch an HKTAN2 durchreichen
hktan2.setSegVersion(segversion);
hktan2.setParam("notlasttan","N");
// in dem zweiten HKTAN-Job eine referenz auf den originalen job
// speichern, damit die antwortdaten für den job, die als antwortdaten
// für hktan2 ankommen, dem richtigen job zugeordnet werden können
HBCIUtils.log("storing reference to original job in new HKTAN segment",HBCIUtils.LOG_DEBUG);
hktan2.setTask(task);
// in dem ersten HKTAN-job eine referenz auf den zweiten speichern,
// damit der erste die auftragsreferenz später im zweiten speichern kann
hktan.setStep2(hktan2);
// Dahinter eine neue Nachricht mit dem einzelnen HKTAN#2
HBCIUtils.log("adding new message with HKTAN(p=2) after current one",HBCIUtils.LOG_DEBUG);
HBCIMessage newMsg = queue.insertAfter(message);
newMsg.append(hktan2);
-
Dann wird in der
doJobs()
Methode vonHBCIDialog.java
diese Nachricht versandt, und durch den Aufruf vontask.fillJobResult(msgstatus,segnum)
in Zeile 311 wird meine Änderung inextractResults()
ausGVTAN2Step.java
aufgerufen, wo, durch die Zeilethis.redo = this;
dem Status-Refresh Task gesagt wird, dass er sich selbst wiederholen soll. -
Die
extractResults()
Methode returned, und wir sind wieder indoJobs()
vonHBCIDialog.java
, wo durch diese Zeilen erkannt wird, dass es einen redo-task gibt (unser Status-Nachfrage-Task). Es wird eine neue Nachricht erstellt, der Task angehängt und die Nachricht auf die queue gepackt:
HBCIMessage newMsg = null;
for (HBCIJobImpl task:tasks)
{
final String name = task.getName();
if (task.skipped())
{
HBCIUtils.log("skipping repeat for task " + name, HBCIUtils.LOG_DEBUG);
continue;
}
HBCIJobImpl redo = task.redo();
if (redo != null)
{
// Nachricht bei Bedarf erstellen und an die Queue haengen
if (newMsg == null)
{
newMsg = new HBCIMessage();
queue.append(newMsg);
}
// Task hinzufuegen
HBCIUtils.log("repeat task " + redo.getName(),HBCIUtils.LOG_DEBUG);
newMsg.append(redo);
}
}
- Der
while(true)
loop inHBCIDialog.java
springt wieder nach oben, die Zeile 206 greift unsere eben erstellte Message von der queue und die erneute Nachfrage-Nachricht wird in Zeile 287 abgeschickt:
msg = this.queue.poll();
[...]
msgstatus = k.rawDoIt(msgPassports,HBCIKernelImpl.SIGNIT,HBCIKernelImpl.CRYPTIT,HBCIKernelImpl.NEED_CRYPT);
Vielleicht verstehe ich hier irgendwas falsch, aber mit dem Debugger kann ich diese Schritte alle nachprüfen und die Logs geben den erfolgreich Versand der Nachricht auch wieder.
from hbci4java.
Ah, jetzt. Ich hatte einfach das "this.redo = this" übersehen. OK, erstaunlich, dass das so funktioniert ;)
Jetzt ist mir noch 1 Sache aufgefallen: Ich würde das Warten in HBCIPassportPinTan (Zeile 407ff) ersatzlos streichen. Grund: Das ist ja der erste Callback für die PushTAN. Zu dem Zeitpunkt ist noch nicht bekannt, ob überhaupt ein Retry notwendig sein wird. Das wissen wir erst, wenn das erste 3956 als Response eintrifft. Das ist in GVTAN2Step. Und dort wird ja dann auch gewartet (entweder direkt im Callback durch den Nutzer der API oder im Anschluss mit dem Thread.sleep). Das Sleep in HBCIPassportPinTan ist da aus meiner Sicht überflüssig.
from hbci4java.
Bei dem Warten in HBCIPassportPinTan.java
war ich mir auch erst nicht sicher, aber ich glaube schon, dass das der Spezifikation entspricht. Wenn wir in Schritt 1b diese Nachricht von der Bank bekommen: 3955::Auftrag empfangen - Bitte Auftrag in Ihrer App freigeben
erfolgt danach in Schritt 2a ja die aller erste Statusabfrage (bei uns die aus HBCIPassportPinTan.java
). Diese wird immer notwendig sein.
Nachdem diese Statusabfrage eingereicht wurde, und wir daraufhin ein 3956
erhalten, erfolgt dann das erste Retry. Aber die Tatsache, dass es in den BPDs sowohl decoupled_time_before_next_status_request
, als auch decoupled_time_before_first_status_request
gibt, lässt mich vermuten, dass wir auch vor der aller ersten Statusabfrage (also die, welche in HBCIPassportPinTan.java
erstellt wird) warten müssen.
from hbci4java.
Das glaube ich nicht. Bisher habe ich es in Hibiscus ja auch komplett ohne Retry umgesetzt und ich beachte da auch die Retry-Zeiten nicht. Einfach deshalb, weil es da gar keinen Status-Request sondern nur die initiale PushTAN-Abfrage. Also User kriegt den TAN-Dialog in der App angezeigt, bestätigt in der App und danach in Hibiscus. Fertig. HKTAN wird eingereicht und die Bank genehmigt den Auftrag. Genau wie bisher bei allen anderen TAN-Verfahren auch. Nur eben, dass das HKTAN keine TAN mehr enthält. Soweit ist es in HBCIPassportPinTan umgesetzt.
Die Prozessergänzung für die Retries kommt erst danach in's Spiel, falls der User in den Callbackl bestätigt hat, obwohl er in der App noch nicht freigegeben hat. Nur in dem Fall ist das Retry ja überhaupt nötig. Und erst dann muss gewartet werden. Also erst dann, wenn ein erneutes HKTAN an die Bank gesendet werden soll.
from hbci4java.
Würdest du dann aber sagen, dass in GVTAN2Step.java
beim ersten Retry decoupled_time_before_first_status_request
gewartet, und bei allen weiteren decoupled_time_before_next_status_request
gewartet wird? Oder würde decoupled_time_before_first_status_request
dann komplett wegfallen? (Abgesehen davon, dass die Werte bei mir bisher immer beide 1 Sekunde waren.)
from hbci4java.
Ja, so sollte es aus meiner Sicht implementiert sein. Beim ersten Retry decoupled_time_before_first_status_request alle folgenden decoupled_time_before_next_status_request. ich glaube allerdings nicht, dass es eine Bank gibt, die dort unterschiedliche Werte verwendet. Und wie bei deiner Bank werden die meisten Banken überhaupt keine relevanten Wartezeiten liefern.
Ich denke, man könnte einfach pauschal decoupled_time_before_next_status_request verwenden - auch für den ersten.
from hbci4java.
Related Issues (20)
- Support HBCI-Geschäftsvorfälle DKKKU (Umsätze) und DKKKS (Saldo) HOT 5
- NEED_PT_TANMEDIA wird nicht im ThreadedCallback behandelt HOT 1
- Problem bei Verbindung zur Deutschen Bank: 'Fehler beim Registrieren der Nutzerdaten' HOT 7
- Status Echtzeitueberweisungen? HOT 8
- org.kapott.hbci.exceptions.ParseErrorException: Fehler beim Erzeugen eines Syntax-DEs für DialogInitRes.MsgHead.SegHead.code HOT 13
- ING DiBa Connection HOT 2
- Customer's IBAN is being cut off at 27 characters HOT 1
- IBAN geht beim Parsen von KInfo6 verloren HOT 7
- Detach fork HOT 1
- ClassNotFoundException with newer jaxb-versions and java 17 HOT 23
- Support für PushTAN 2.0 (Decoupled Verfahren) HOT 7
- Fachliche Fehlermeldungen der Bank gehen verloren HOT 1
- Anonymous: HBCI_Exception: Fehler beim Erzeugen eines HBCIHandler Objektes" HOT 2
- "Duplicate property key" in blz.properties: 75062026 HOT 1
- Client Pain Version HOT 16
- Unterstützung für verteilte Unterschriften per HBCI HOT 4
- Fehler bei Comdirect photoTan HOT 2
- String bei callback `NEED_PT_TANMEDIA` ist seit 3.1.80 leer (Sparkasse) HOT 3
- PushTan beim registerUser (fetchUPD) benötigt. Wie registriere ich mein Vertrauenswürdiges Gerät? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hbci4java.