Merge pull request 'Feature: FinTS-TAN-Verfahren per Verbindung konfigurierbar + Decoupled-Polling-Fix' (#88) from fds2610-bot/Steuerkram:main into main
Reviewed-on: https://codeberg.org/fds2610/Steuerkram/pulls/88
This commit is contained in:
commit
5c067e3ce8
5 changed files with 43 additions and 10 deletions
3
migrations/073_bank_sources_tan_mode_id.sql
Normal file
3
migrations/073_bank_sources_tan_mode_id.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE bank_sources
|
||||||
|
ADD COLUMN IF NOT EXISTS tan_mode_id INT NULL DEFAULT NULL
|
||||||
|
COMMENT 'Bevorzugte FinTS-TAN-Verfahren-ID (z.B. 913 für chipTAN QR); NULL = erstes verfügbares';
|
||||||
|
|
@ -443,6 +443,7 @@ class BankController extends BaseController
|
||||||
'fints_url' => $isFints ? (trim($_POST['fints_url'] ?? '') ?: null) : null,
|
'fints_url' => $isFints ? (trim($_POST['fints_url'] ?? '') ?: null) : null,
|
||||||
'benutzerkennung' => $isFints ? (trim($_POST['benutzerkennung'] ?? '') ?: null) : null,
|
'benutzerkennung' => $isFints ? (trim($_POST['benutzerkennung'] ?? '') ?: null) : null,
|
||||||
'pin' => $isFints ? (trim($_POST['pin'] ?? '') ?: null) : null,
|
'pin' => $isFints ? (trim($_POST['pin'] ?? '') ?: null) : null,
|
||||||
|
'tan_mode_id' => $isFints ? (($_POST['tan_mode_id'] ?? '') !== '' ? (int)$_POST['tan_mode_id'] : null) : null,
|
||||||
'account_filter' => null, // Konten werden beim ersten Abruf ausgewählt
|
'account_filter' => null, // Konten werden beim ersten Abruf ausgewählt
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -547,6 +548,7 @@ class BankController extends BaseController
|
||||||
'fints_url' => trim($_POST['fints_url'] ?? '') ?: null,
|
'fints_url' => trim($_POST['fints_url'] ?? '') ?: null,
|
||||||
'benutzerkennung' => trim($_POST['benutzerkennung'] ?? '') ?: null,
|
'benutzerkennung' => trim($_POST['benutzerkennung'] ?? '') ?: null,
|
||||||
'pin' => $newPin !== '' ? $newPin : $source['pin'],
|
'pin' => $newPin !== '' ? $newPin : $source['pin'],
|
||||||
|
'tan_mode_id' => ($_POST['tan_mode_id'] ?? '') !== '' ? (int)$_POST['tan_mode_id'] : null,
|
||||||
];
|
];
|
||||||
$filterUpdate = BankSource::computeFilterFromPost(
|
$filterUpdate = BankSource::computeFilterFromPost(
|
||||||
$source['account_filter'] ?? null,
|
$source['account_filter'] ?? null,
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ class BankSource
|
||||||
'buchungstext_template_debit', 'buchungstext_template_credit',
|
'buchungstext_template_debit', 'buchungstext_template_credit',
|
||||||
'sandbox', 'last_fetched_at', 'fetch_range',
|
'sandbox', 'last_fetched_at', 'fetch_range',
|
||||||
'app_name', 'client_id_enc', 'secret_enc',
|
'app_name', 'client_id_enc', 'secret_enc',
|
||||||
'blz', 'fints_url', 'benutzerkennung', 'pin_enc', 'account_filter',
|
'blz', 'fints_url', 'benutzerkennung', 'pin_enc', 'account_filter', 'tan_mode_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
$out = [];
|
$out = [];
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,25 @@ class FinTsFetchService
|
||||||
$log(sprintf(' [%d] %s (ID %d)', $idx, $mode->getName(), $mode->getId()));
|
$log(sprintf(' [%d] %s (ID %d)', $idx, $mode->getName(), $mode->getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$selectedTanMode = reset($tanModes);
|
$preferredId = isset($this->source['tan_mode_id']) && $this->source['tan_mode_id'] !== null
|
||||||
$log('Auswahl: ' . $selectedTanMode->getName() . ' (erstes verfügbares Verfahren)');
|
? (int)$this->source['tan_mode_id']
|
||||||
|
: null;
|
||||||
|
$selectedTanMode = null;
|
||||||
|
if ($preferredId !== null) {
|
||||||
|
foreach ($tanModes as $mode) {
|
||||||
|
if ($mode->getId() === $preferredId) {
|
||||||
|
$selectedTanMode = $mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($selectedTanMode === null) {
|
||||||
|
$log('WARNUNG: TAN-Verfahren ID ' . $preferredId . ' nicht gefunden – nutze erstes verfügbares.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($selectedTanMode === null) {
|
||||||
|
$selectedTanMode = reset($tanModes);
|
||||||
|
}
|
||||||
|
$log('Auswahl: ' . $selectedTanMode->getName() . ' (ID ' . $selectedTanMode->getId() . ')');
|
||||||
|
|
||||||
$selectedTanMedium = null;
|
$selectedTanMedium = null;
|
||||||
if ($selectedTanMode->needsTanMedium()) {
|
if ($selectedTanMode->needsTanMedium()) {
|
||||||
|
|
@ -288,11 +305,14 @@ class FinTsFetchService
|
||||||
$period = max(1, (int)$tanMode->getPeriodicDecoupledCheckDelaySeconds());
|
$period = max(1, (int)$tanMode->getPeriodicDecoupledCheckDelaySeconds());
|
||||||
for ($attempt = 0; $attempt < $maxChecks; $attempt++) {
|
for ($attempt = 0; $attempt < $maxChecks; $attempt++) {
|
||||||
try {
|
try {
|
||||||
$this->fints->checkDecoupledSubmission($action);
|
if ($this->fints->checkDecoupledSubmission($action)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
sleep($period);
|
$log(' → Polling-Fehler: ' . $e->getMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
sleep($period);
|
||||||
}
|
}
|
||||||
$log(' → Zeitüberschreitung bei App-Bestätigung.');
|
$log(' → Zeitüberschreitung bei App-Bestätigung.');
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ $connectionsJson = json_encode(array_map(fn($c) => [
|
||||||
'benutzerkennung' => $c['benutzerkennung'] ?? '',
|
'benutzerkennung' => $c['benutzerkennung'] ?? '',
|
||||||
'account_filter' => $c['account_filter'] ?? null,
|
'account_filter' => $c['account_filter'] ?? null,
|
||||||
'fetch_range' => $c['fetch_range'] ?? 'last_fetched',
|
'fetch_range' => $c['fetch_range'] ?? 'last_fetched',
|
||||||
|
'tan_mode_id' => isset($c['tan_mode_id']) && $c['tan_mode_id'] !== null ? (int)$c['tan_mode_id'] : null,
|
||||||
], $connections));
|
], $connections));
|
||||||
|
|
||||||
$fetchRangeOptions = [
|
$fetchRangeOptions = [
|
||||||
|
|
@ -292,6 +293,11 @@ $fetchRangeOptions = [
|
||||||
<label for="edit-fints-url">FinTS-Server-URL <span class="text-muted text-sm">(optional)</span></label>
|
<label for="edit-fints-url">FinTS-Server-URL <span class="text-muted text-sm">(optional)</span></label>
|
||||||
<input type="url" id="edit-fints-url" name="fints_url" placeholder="https://...">
|
<input type="url" id="edit-fints-url" name="fints_url" placeholder="https://...">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="edit-tan-mode-id">TAN-Verfahren-ID <span class="text-muted text-sm">(optional)</span></label>
|
||||||
|
<input type="number" id="edit-tan-mode-id" name="tan_mode_id" min="1" placeholder="z.B. 913 für chipTAN QR">
|
||||||
|
<div class="text-muted text-sm">Leer = erstes verfügbares Verfahren</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="edit-fetch-range-fints">Abrufen ab</label>
|
<label for="edit-fetch-range-fints">Abrufen ab</label>
|
||||||
<select id="edit-fetch-range-fints" name="fetch_range" disabled>
|
<select id="edit-fetch-range-fints" name="fetch_range" disabled>
|
||||||
|
|
@ -463,6 +469,7 @@ $fetchRangeOptions = [
|
||||||
const editBenutzer = document.getElementById('edit-benutzerkennung');
|
const editBenutzer = document.getElementById('edit-benutzerkennung');
|
||||||
const editPin = document.getElementById('edit-pin');
|
const editPin = document.getElementById('edit-pin');
|
||||||
const editFintsUrl = document.getElementById('edit-fints-url');
|
const editFintsUrl = document.getElementById('edit-fints-url');
|
||||||
|
const editTanModeId = document.getElementById('edit-tan-mode-id');
|
||||||
const editAccountList = document.getElementById('edit-account-list');
|
const editAccountList = document.getElementById('edit-account-list');
|
||||||
const editResetAcc = document.getElementById('edit-reset-accounts');
|
const editResetAcc = document.getElementById('edit-reset-accounts');
|
||||||
const editFetchRangeApi = document.getElementById('edit-fetch-range-api');
|
const editFetchRangeApi = document.getElementById('edit-fetch-range-api');
|
||||||
|
|
@ -839,10 +846,11 @@ $fetchRangeOptions = [
|
||||||
editSandbox.checked = conn.sandbox === true;
|
editSandbox.checked = conn.sandbox === true;
|
||||||
}
|
}
|
||||||
if (isFints) {
|
if (isFints) {
|
||||||
editBlz.value = conn.blz || '';
|
editBlz.value = conn.blz || '';
|
||||||
editBenutzer.value = conn.benutzerkennung || '';
|
editBenutzer.value = conn.benutzerkennung || '';
|
||||||
editPin.value = '';
|
editPin.value = '';
|
||||||
editFintsUrl.value = conn.fints_url || '';
|
editFintsUrl.value = conn.fints_url || '';
|
||||||
|
editTanModeId.value = conn.tan_mode_id != null ? conn.tan_mode_id : '';
|
||||||
editResetAcc.checked = false;
|
editResetAcc.checked = false;
|
||||||
|
|
||||||
// Konto-Checkboxen aus account_filter aufbauen
|
// Konto-Checkboxen aus account_filter aufbauen
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue