@@ -41,22 +41,24 @@ public function login(FinTs $finTs, string $persistedInstanceFilePath = null): v
41
41
42
42
public function action (FinTs $ finTs , BaseAction $ action , string $ persistedInstanceFilePath = null ): void
43
43
{
44
- $ finTs ->execute ($ action );
44
+ try {
45
+ $ finTs ->execute ($ action );
45
46
46
- if ($ action ->needsTan ()) {
47
- $ this ->handleStrongAuthentication ($ finTs , $ action );
47
+ if ($ action ->needsTan ()) {
48
+ $ this ->handleStrongAuthentication ($ finTs , $ action );
49
+ }
50
+ } catch (\Throwable $ exception ) {
51
+ // If the action failed
52
+ // we still want to persist the FinTs instance
53
+ // because otherwise the next call will be broken
54
+ $ this ->persist ($ finTs , $ persistedInstanceFilePath );
55
+
56
+ throw $ exception ;
48
57
}
49
58
50
59
$ this ->persist ($ finTs , $ persistedInstanceFilePath );
51
60
}
52
61
53
- protected function persist (FinTs $ finTs , string $ persistedInstanceFilePath = null ): void
54
- {
55
- if ($ persistedInstanceFilePath !== null ) {
56
- file_put_contents ($ persistedInstanceFilePath , base64_encode ($ finTs ->persist ()));
57
- }
58
- }
59
-
60
62
/**
61
63
* This function as well as handleTan() and handleDecoupled() below are key to how FinTS works in times of PSD2
62
64
* regulations.
@@ -90,6 +92,13 @@ public function handleStrongAuthentication(FinTs $finTs, BaseAction $action): vo
90
92
}
91
93
}
92
94
95
+ protected function persist (FinTs $ finTs , string $ persistedInstanceFilePath = null ): void
96
+ {
97
+ if ($ persistedInstanceFilePath !== null ) {
98
+ file_put_contents ($ persistedInstanceFilePath , base64_encode ($ finTs ->persist ()));
99
+ }
100
+ }
101
+
93
102
/**
94
103
* This function handles strong authentication for the case where the user needs to enter a TAN into the PHP
95
104
* application.
@@ -140,7 +149,7 @@ protected function handleTan(FinTs $finTs, BaseAction $action): void
140
149
// handling, not just one like in this simplified example). You *only* need to carry over the $persistedInstance
141
150
// and the $persistedAction (which are simple strings) by storing them in some database or file where you can load
142
151
// them again in a new PHP process when the user sends the TAN.
143
- $ this ->output (" Please enter the TAN: " );
152
+ $ this ->output (' Please enter the TAN: ' );
144
153
$ tan = trim (fgets (STDIN ));
145
154
146
155
$ this ->output (sprintf ('Submitting TAN: %s ' , $ tan ));
@@ -172,18 +181,18 @@ protected function handleDecoupled(FinTs $finTs, BaseAction $action): void
172
181
// without polling entirely and just let the user confirm manually in all cases (i.e. only implement the `else`
173
182
// branch below).
174
183
if ($ tanMode ?->allowsAutomatedPolling() === true ) {
175
- $ this ->output (" Polling server to detect when the decoupled authentication is complete. " );
184
+ $ this ->output (' Polling server to detect when the decoupled authentication is complete. ' );
176
185
sleep ($ tanMode ?->getFirstDecoupledCheckDelaySeconds());
177
186
for ($ attempt = 0 ;
178
187
$ tanMode ?->getMaxDecoupledChecks() === 0 || $ attempt < $ tanMode ?->getMaxDecoupledChecks();
179
188
++$ attempt
180
189
) {
181
190
if ($ finTs ->checkDecoupledSubmission ($ action )) {
182
- $ this ->output (" Confirmed. " );
191
+ $ this ->output (' Confirmed. ' );
183
192
return ;
184
193
}
185
194
186
- $ this ->output (" Still waiting... " );
195
+ $ this ->output (' Still waiting... ' );
187
196
sleep ($ tanMode ?->getPeriodicDecoupledCheckDelaySeconds());
188
197
}
189
198
@@ -196,13 +205,13 @@ protected function handleDecoupled(FinTs $finTs, BaseAction $action): void
196
205
"Please type 'done' and hit Return when you've completed the authentication on the other device. "
197
206
);
198
207
while (trim (fgets (STDIN )) !== 'done ' ) {
199
- $ this ->output (" Try again. " );
208
+ $ this ->output (' Try again. ' );
200
209
}
201
210
202
- $ this ->output (" Confirming that the action is done. " );
211
+ $ this ->output (' Confirming that the action is done. ' );
203
212
} while (! $ finTs ->checkDecoupledSubmission ($ action ));
204
213
205
- $ this ->output (" Confirmed " );
214
+ $ this ->output (' Confirmed ' );
206
215
} else {
207
216
throw new AssertionError ('Server allows neither automated polling nor manual confirmation ' );
208
217
}
0 commit comments