Skip to content

Commit 8e142b4

Browse files
committed
Persist on fail
1 parent f47343b commit 8e142b4

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

Diff for: src/ActionService.php

+26-17
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,24 @@ public function login(FinTs $finTs, string $persistedInstanceFilePath = null): v
4141

4242
public function action(FinTs $finTs, BaseAction $action, string $persistedInstanceFilePath = null): void
4343
{
44-
$finTs->execute($action);
44+
try {
45+
$finTs->execute($action);
4546

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;
4857
}
4958

5059
$this->persist($finTs, $persistedInstanceFilePath);
5160
}
5261

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-
6062
/**
6163
* This function as well as handleTan() and handleDecoupled() below are key to how FinTS works in times of PSD2
6264
* regulations.
@@ -90,6 +92,13 @@ public function handleStrongAuthentication(FinTs $finTs, BaseAction $action): vo
9092
}
9193
}
9294

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+
93102
/**
94103
* This function handles strong authentication for the case where the user needs to enter a TAN into the PHP
95104
* application.
@@ -140,7 +149,7 @@ protected function handleTan(FinTs $finTs, BaseAction $action): void
140149
// handling, not just one like in this simplified example). You *only* need to carry over the $persistedInstance
141150
// and the $persistedAction (which are simple strings) by storing them in some database or file where you can load
142151
// 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:');
144153
$tan = trim(fgets(STDIN));
145154

146155
$this->output(sprintf('Submitting TAN: %s', $tan));
@@ -172,18 +181,18 @@ protected function handleDecoupled(FinTs $finTs, BaseAction $action): void
172181
// without polling entirely and just let the user confirm manually in all cases (i.e. only implement the `else`
173182
// branch below).
174183
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.');
176185
sleep($tanMode?->getFirstDecoupledCheckDelaySeconds());
177186
for ($attempt = 0;
178187
$tanMode?->getMaxDecoupledChecks() === 0 || $attempt < $tanMode?->getMaxDecoupledChecks();
179188
++$attempt
180189
) {
181190
if ($finTs->checkDecoupledSubmission($action)) {
182-
$this->output("Confirmed.");
191+
$this->output('Confirmed.');
183192
return;
184193
}
185194

186-
$this->output("Still waiting...");
195+
$this->output('Still waiting...');
187196
sleep($tanMode?->getPeriodicDecoupledCheckDelaySeconds());
188197
}
189198

@@ -196,13 +205,13 @@ protected function handleDecoupled(FinTs $finTs, BaseAction $action): void
196205
"Please type 'done' and hit Return when you've completed the authentication on the other device."
197206
);
198207
while (trim(fgets(STDIN)) !== 'done') {
199-
$this->output("Try again.");
208+
$this->output('Try again.');
200209
}
201210

202-
$this->output("Confirming that the action is done.");
211+
$this->output('Confirming that the action is done.');
203212
} while (! $finTs->checkDecoupledSubmission($action));
204213

205-
$this->output("Confirmed");
214+
$this->output('Confirmed');
206215
} else {
207216
throw new AssertionError('Server allows neither automated polling nor manual confirmation');
208217
}

0 commit comments

Comments
 (0)