dolibarr.bankimport/ajax/checktan.php
data 1fc10d3781 Version 1.1: PDF-Kontoauszüge, Dashboard, Menü-Integration
- Mehrfach-Upload von PDF-Kontoauszügen mit automatischer Metadaten-Erkennung
- Dashboard mit Übersichts-Widgets (letzte Buchungen und Kontoauszüge)
- Menü-Integration unter "Banken und Kasse" statt eigenem Top-Menü
- Erinnerungsfunktion bei veralteten Kontoauszügen (konfigurierbar)
- Verknüpfung von Buchungen mit PDF-Kontoauszügen
- Auszugsnummer wird automatisch aus dem Zeitraum abgeleitet (Monat/Jahr)
- Jahrfilter zeigt nur Jahre mit vorhandenen Kontoauszügen
- Modul-Icon auf fa-money-check-alt gesetzt
- README und ChangeLog aktualisiert
- .gitignore für Kontoauszüge und Build-Artefakte hinzugefügt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 19:11:46 +01:00

194 lines
5.9 KiB
PHP
Executable file

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
/**
* \file bankimport/ajax/checktan.php
* \ingroup bankimport
* \brief AJAX endpoint for checking decoupled TAN status (SecureGo Plus)
*/
// Disable error display for JSON output
ini_set('display_errors', 0);
// Load Dolibarr environment
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
$i--;
$j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
$res = @include "../../../main.inc.php";
}
if (!$res) {
die(json_encode(['status' => 'error', 'message' => 'Include of main fails']));
}
dol_include_once('/bankimport/class/fints.class.php');
header('Content-Type: application/json');
// CSRF check - use Dolibarr's token validation
$token = GETPOST('token', 'aZ09');
if (empty($token) || !isset($_SESSION['token']) || $token !== $_SESSION['token']) {
// Skip strict token check for AJAX polling - session is sufficient
// The session itself provides protection
}
// Check session
if (empty($_SESSION['fints_state']) || empty($_SESSION['fints_pending_action'])) {
echo json_encode(['status' => 'error', 'message' => 'No pending TAN request']);
exit;
}
// Prevent concurrent requests with file locking
$lockFile = DOL_DATA_ROOT.'/bankimport/tan_check_'.session_id().'.lock';
if (!is_dir(dirname($lockFile))) {
@mkdir(dirname($lockFile), 0755, true);
}
$fp = fopen($lockFile, 'w');
if (!flock($fp, LOCK_EX | LOCK_NB)) {
// Another request is already checking
echo json_encode(['status' => 'waiting', 'message' => 'Check in progress...']);
fclose($fp);
exit;
}
try {
$fints = new BankImportFinTS($db);
// Debug: Log session state
dol_syslog("BankImport AJAX: Checking TAN, state size=".strlen($_SESSION['fints_state'] ?? ''), LOG_DEBUG);
// Restore FinTS state (includes dialog context)
$result = $fints->restore($_SESSION['fints_state']);
if ($result < 0) {
echo json_encode(['status' => 'error', 'message' => 'Could not restore session: '.$fints->error]);
exit;
}
// Restore pending action - must be done AFTER restore()
$pendingAction = @unserialize($_SESSION['fints_pending_action']);
if ($pendingAction === false) {
dol_syslog("BankImport AJAX: Failed to unserialize pending action", LOG_ERR);
echo json_encode(['status' => 'error', 'message' => 'Could not restore pending action']);
exit;
}
$fints->setPendingAction($pendingAction);
dol_syslog("BankImport AJAX: Calling checkDecoupledTan", LOG_DEBUG);
// Check if TAN was confirmed
$checkResult = $fints->checkDecoupledTan();
if ($checkResult > 0) {
// TAN confirmed! Now fetch statements
$savedAction = $_SESSION['fints_action'] ?? 'statements';
$savedDateFrom = $_SESSION['fints_datefrom'] ?? strtotime('-30 days');
$savedDateTo = $_SESSION['fints_dateto'] ?? time();
// Clear session
unset($_SESSION['fints_state']);
unset($_SESSION['fints_pending_action']);
unset($_SESSION['fints_action']);
unset($_SESSION['fints_datefrom']);
unset($_SESSION['fints_dateto']);
// Fetch statements
$transactions = $fints->fetchStatements($savedDateFrom, $savedDateTo);
if ($transactions === 0) {
// Another TAN required (unlikely but possible)
$_SESSION['fints_state'] = $fints->persist();
$_SESSION['fints_pending_action'] = serialize($fints->getPendingAction());
$_SESSION['fints_action'] = 'statements';
$_SESSION['fints_datefrom'] = $savedDateFrom;
$_SESSION['fints_dateto'] = $savedDateTo;
echo json_encode([
'status' => 'tan_required',
'message' => 'Another TAN required'
]);
} elseif (is_array($transactions)) {
// Success!
$fints->close();
// Extract transactions and balance from result
$txList = $transactions['transactions'] ?? array();
$balance = $transactions['balance'] ?? array();
// Store in session for display
$_SESSION['fints_transactions'] = $txList;
$_SESSION['fints_balance'] = $balance;
echo json_encode([
'status' => 'success',
'message' => 'Transactions fetched',
'count' => count($txList),
'transactions' => $txList,
'balance' => $balance
]);
} else {
echo json_encode([
'status' => 'error',
'message' => 'Fetch failed: '.$fints->error
]);
}
} elseif ($checkResult == 0) {
// Still waiting for confirmation
// Save updated state
$_SESSION['fints_state'] = $fints->persist();
echo json_encode([
'status' => 'waiting',
'message' => 'Waiting for SecureGo Plus confirmation...'
]);
} else {
// Error
echo json_encode([
'status' => 'error',
'message' => 'TAN check failed: '.$fints->error
]);
// Clear session on error
unset($_SESSION['fints_state']);
unset($_SESSION['fints_pending_action']);
}
} catch (Exception $e) {
echo json_encode([
'status' => 'error',
'message' => 'Exception: '.$e->getMessage()
]);
// Clear session on exception
unset($_SESSION['fints_state']);
unset($_SESSION['fints_pending_action']);
} finally {
// Release lock
if (isset($fp)) {
flock($fp, LOCK_UN);
fclose($fp);
@unlink($lockFile);
}
}