From aeb8254840f4327ae8ec11e1fac688a655df2146 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Wed, 19 Aug 2026 08:15:45 +0200 Subject: [PATCH] Fix #21: Bargeld-Tool auch bei Adresse mit /api/v1 erreichen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Verbindungstest meldete „Das Bargeld-Tool kennt die Schnittstelle nicht (HTTP 404)“, sobald die hinterlegte Adresse den Schnittstellenpfad schon enthielt: Der Finanzmanager hängt ihn selbst an und fragte damit unter /api/v1/api/v1/status an. Die Adresse aus der Browserzeile zu kopieren ist der naheliegende Weg, und der Pfad ist dort mit dabei. Ein abschließendes /api oder /api/v1 kürzt BargeldTool::basisadresse() deshalb weg – beim Speichern und noch einmal im Konstruktor, damit auch schon gespeicherte Adressen greifen. Ein Unterverzeichnis davor bleibt erhalten, ein Hostname wie apianbieter.example bleibt unangetastet. Bereits gespeicherte Adressen räumt Migration 017 auf. Co-Authored-By: Claude Opus 5 --- Changes.md | 8 +++++ docs/buchungen.md | 5 +++ migrations/017_bargeld_url_ohne_pfad.sql | 14 +++++++++ src/Controllers/VerwaltungController.php | 4 ++- src/Services/BargeldTool.php | 17 +++++++++- src/Views/verwaltung/bargeld.php | 3 +- tests/34_BargeldAbgleichTest.php | 40 ++++++++++++++++++++++++ 7 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 migrations/017_bargeld_url_ohne_pfad.sql diff --git a/Changes.md b/Changes.md index 974c46a..97d6330 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,13 @@ # Änderungen +## Bargeld-Tool: Adresse mit `/api/v1` (19.08.2026) + +Der Verbindungstest scheiterte mit „Das Bargeld-Tool kennt die Schnittstelle nicht +(HTTP 404)“, wenn die hinterlegte Adresse den Schnittstellenpfad schon enthielt – der +Finanzmanager hängt ihn selbst an und fragte dann unter `/api/v1/api/v1/status` an. Ein +abschließendes `/api` bzw. `/api/v1` kürzt er jetzt beim Speichern weg; bereits +gespeicherte Adressen räumt Migration 017 auf. + ## Abgleich mit dem Bargeld-Tool (19.08.2026) Bargeldausgaben werden in einem zweiten Programm erfasst; im Finanzmanager kommen sie als diff --git a/docs/buchungen.md b/docs/buchungen.md index 33a047d..0e64fc7 100644 --- a/docs/buchungen.md +++ b/docs/buchungen.md @@ -262,3 +262,8 @@ nicht (404), prüft der Verbindungstest über eine Suchabfrage. Der Betrag geht vorzeichenbehaftet über die Leitung, so wie er im Finanzmanager steht: Ausgaben negativ. Führt das Bargeld-Tool seine Beträge positiv, muss es umrechnen. + +`{adresse}` ist die Basisadresse **ohne** Schnittstellenpfad. Steht am Ende der eingetragenen +Adresse trotzdem `/api` oder `/api/v1`, kürzt der Finanzmanager sie beim Speichern – die +Adresse aus der Browserzeile zu kopieren ist der naheliegende Weg und führte sonst zu +`/api/v1/api/v1/status` und einem 404 im Verbindungstest. diff --git a/migrations/017_bargeld_url_ohne_pfad.sql b/migrations/017_bargeld_url_ohne_pfad.sql new file mode 100644 index 0000000..e7222fd --- /dev/null +++ b/migrations/017_bargeld_url_ohne_pfad.sql @@ -0,0 +1,14 @@ +-- Die Adresse des Bargeld-Tools ohne den Schnittstellenpfad. +-- +-- Der Finanzmanager hängt `/api/v1/...` selbst an die hinterlegte Adresse. +-- Wer sie aus dem Browser kopiert hat, trug den Pfad mit ein – dann fragte +-- der Verbindungstest unter `/api/v1/api/v1/status` an und bekam ein 404. +-- Neue Eingaben kürzt der Finanzmanager beim Speichern; bereits gespeicherte +-- Adressen räumt diese Migration auf. +-- +-- Idempotent: Auf einer bereits gekürzten Adresse ändert der Ausdruck nichts. + +UPDATE einstellungen + SET wert = REGEXP_REPLACE(TRIM(wert), '/+api(/+v[0-9]+)?/*$', '') + WHERE schluessel = 'bargeld_url' + AND wert REGEXP '/+api(/+v[0-9]+)?/*$'; diff --git a/src/Controllers/VerwaltungController.php b/src/Controllers/VerwaltungController.php index f142a80..4341f1b 100644 --- a/src/Controllers/VerwaltungController.php +++ b/src/Controllers/VerwaltungController.php @@ -232,7 +232,9 @@ class VerwaltungController extends BaseController return; } - Einstellung::set('bargeld_url', rtrim($url, '/'), 'bargeld'); + // Ein mitkopiertes „/api/v1“ am Ende fliegt raus – sonst hinge der + // Schnittstellenpfad ein zweites Mal dran. + Einstellung::set('bargeld_url', $url === '' ? '' : BargeldTool::basisadresse($url), 'bargeld'); Einstellung::set('bargeld_benutzer', trim($this->post('bargeld_benutzer')), 'bargeld'); // Wie bei der FinTS-PIN: Ein leeres Feld heißt „unverändert“, sonst diff --git a/src/Services/BargeldTool.php b/src/Services/BargeldTool.php index 46dc40d..e199bd6 100644 --- a/src/Services/BargeldTool.php +++ b/src/Services/BargeldTool.php @@ -41,11 +41,26 @@ class BargeldTool /** Höchstzahl der Treffer, die die Gegenstelle liefern soll. */ private const GRENZE = 20; + private string $basisUrl; + public function __construct( - private string $basisUrl, + string $basisUrl, private string $benutzer = '', private string $passwort = '' ) { + $this->basisUrl = self::basisadresse($basisUrl); + } + + /** + * Die Basisadresse ohne den Schnittstellenpfad. Wer die Adresse aus dem + * Browser kopiert, hat `/api/v1` schon dabei – ohne diese Kürzung fragte + * der Finanzmanager unter `/api/v1/api/v1/status` an und bekam ein 404. + */ + public static function basisadresse(string $url): string + { + $url = rtrim(trim($url), '/'); + + return (string)preg_replace('#/api(?:/v\\d+)?$#i', '', $url); } /** diff --git a/src/Views/verwaltung/bargeld.php b/src/Views/verwaltung/bargeld.php index 8a26bee..d295403 100644 --- a/src/Views/verwaltung/bargeld.php +++ b/src/Views/verwaltung/bargeld.php @@ -55,7 +55,8 @@ include __DIR__ . '/../layout/kopf.php'; placeholder="https://…" inputmode="url">

Die Basisadresse des Bargeld-Tools ohne Pfad; der Finanzmanager hängt - /api/v1/buchungen selbst an. Leer lassen schaltet den Abgleich ab – + /api/v1/buchungen selbst an. Ein mitkopiertes /api/v1 + am Ende entfernt er beim Speichern. Leer lassen schaltet den Abgleich ab – das Kontoblatt zeigt dann überall den grauen Kreis.

diff --git a/tests/34_BargeldAbgleichTest.php b/tests/34_BargeldAbgleichTest.php index 6819f5c..20e4638 100644 --- a/tests/34_BargeldAbgleichTest.php +++ b/tests/34_BargeldAbgleichTest.php @@ -39,6 +39,7 @@ class BargeldAbgleichTest extends TestCase $this->stammdaten(); $this->antwortAuswerten(); + $this->basisadresseKuerztDenSchnittstellenpfad(); $this->kategorienauswahl(); $this->ohneAdresseKeinAbgleich(); $this->passwortStehtVerschluesselt(); @@ -113,6 +114,45 @@ class BargeldAbgleichTest extends TestCase $this->assert($ohneFeld['fehler'], 'Ohne Feld „buchungen“ ist die Antwort unbrauchbar'); } + // ── Basisadresse ───────────────────────────────────────────────────────── + + /** + * Wer die Adresse aus dem Browser kopiert, hat `/api/v1` schon dabei. + * Bleibt es stehen, fragt der Finanzmanager unter `/api/v1/api/v1/status` + * an und der Verbindungstest scheitert mit einem 404. + */ + private function basisadresseKuerztDenSchnittstellenpfad(): void + { + $erwartet = 'https://bargeld.example.org'; + + foreach ([ + 'https://bargeld.example.org', + 'https://bargeld.example.org/', + 'https://bargeld.example.org/api', + 'https://bargeld.example.org/api/v1', + 'https://bargeld.example.org/api/v1/', + ' https://bargeld.example.org/api/v2 ', + ] as $eingabe) { + $this->assertEquals( + $erwartet, + BargeldTool::basisadresse($eingabe), + 'Basisadresse aus „' . trim($eingabe) . '“' + ); + } + + $this->assertEquals( + 'https://example.org/fscash', + BargeldTool::basisadresse('https://example.org/fscash/api/v1'), + 'Ein Unterverzeichnis vor dem Schnittstellenpfad bleibt erhalten' + ); + + $this->assertEquals( + 'https://apianbieter.example.org', + BargeldTool::basisadresse('https://apianbieter.example.org'), + 'Nur ein eigener Pfadteil „api“ wird gekürzt, kein Namensbestandteil' + ); + } + // ── Auswahl der Kategorien ─────────────────────────────────────────────── private function kategorienauswahl(): void