SepaXml erzeugt jetzt zusätzlich pain.001.001.09 (Dt-Element für den Ausführungstermin, BICFI statt BIC, UETR je Zahlung) für Banken, die das ältere pain.001.001.03 nicht mehr führen. FinTsUeberweisung fängt außerdem die UnsupportedException ab, die php-fints wirft, wenn die Bank Namensabgleich-Volltreffer und TAN-Anfrage in einem Antwortsatz kombiniert, und lässt den vorhandenen automatischen Volltreffer-Namensabgleich den Rest erledigen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
112 lines
5 KiB
PHP
112 lines
5 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
use Fhp\Model\VopVerificationResult;
|
||
use Fhp\UnsupportedException;
|
||
use Finanzmanager\Services\FinTsUeberweisung;
|
||
|
||
/**
|
||
* Namensabgleich vor der Überweisung (Verification of Payee).
|
||
*
|
||
* Seit Oktober 2025 gleicht die Bank den Empfängernamen mit dem Kontoinhaber
|
||
* ab. Stimmt beides überein, bestätigt der Finanzmanager selbst und geht direkt
|
||
* zur TAN; weicht der Name ab, wird gefragt. Geprüft wird hier, was sich ohne
|
||
* Bankverbindung prüfen lässt: die Aufbereitung dessen, was die Bank meldet,
|
||
* und dass ohne wartenden Vorgang niemand etwas bestätigen kann.
|
||
*/
|
||
class NamensabgleichTest extends TestCase
|
||
{
|
||
protected string $testName = 'Test 40: Namensabgleich vor der Überweisung';
|
||
|
||
public function run(): void
|
||
{
|
||
$this->jedesErgebnisHatEinenDeutschenSatz();
|
||
$this->derBanktextWirdKlartext();
|
||
$this->ohneWartendenVorgangGehtNichts();
|
||
$this->dieBekannteVopTanLueckeWirdErkannt();
|
||
}
|
||
|
||
private function jedesErgebnisHatEinenDeutschenSatz(): void
|
||
{
|
||
$ergebnisse = [
|
||
VopVerificationResult::CompletedFullMatch,
|
||
VopVerificationResult::CompletedCloseMatch,
|
||
VopVerificationResult::CompletedNoMatch,
|
||
VopVerificationResult::CompletedPartialMatch,
|
||
VopVerificationResult::NotApplicable,
|
||
];
|
||
|
||
$saetze = [];
|
||
foreach ($ergebnisse as $ergebnis) {
|
||
$satz = FinTsUeberweisung::vopUrteil($ergebnis);
|
||
$this->assertNotEmpty($satz, 'Ergebnis ' . $ergebnis . ' hat einen Satz');
|
||
$this->assert(
|
||
!str_contains($satz, 'Completed') && !str_contains($satz, 'Match'),
|
||
'Ergebnis ' . $ergebnis . ' steht auf Deutsch da'
|
||
);
|
||
$saetze[] = $satz;
|
||
}
|
||
|
||
$this->assertEquals(count($ergebnisse), count(array_unique($saetze)), 'Jedes Ergebnis hat seinen eigenen Satz');
|
||
|
||
// Auch ein unbekanntes oder fehlendes Ergebnis darf den Dialog nicht leer lassen.
|
||
$this->assertNotEmpty(FinTsUeberweisung::vopUrteil(null), 'Ohne Ergebnis steht trotzdem ein Satz da');
|
||
$this->assertNotEmpty(FinTsUeberweisung::vopUrteil('Unbekannt'), 'Unbekanntes Ergebnis ebenso');
|
||
}
|
||
|
||
private function derBanktextWirdKlartext(): void
|
||
{
|
||
// So liefern die Banken den Aufklärungstext: HTML mit Auszeichnung.
|
||
$html = 'Der Name stimmt <b>nicht</b> überein.<br>Bitte prüfen.'
|
||
. '<p><b>Wichtiger Hinweis:</b> Die Überweisung wird ohne Korrektur ausgeführt.</p>';
|
||
|
||
$text = FinTsUeberweisung::vopHinweis($html);
|
||
|
||
$this->assert(!str_contains($text, '<'), 'Die Auszeichnung ist weg');
|
||
$this->assert(str_contains($text, 'Der Name stimmt nicht überein.'), 'Der Satz bleibt vollständig');
|
||
$this->assert(str_contains($text, 'Bitte prüfen.'), 'Entities werden aufgelöst');
|
||
$this->assert(str_contains($text, "überein.\nBitte prüfen."), 'Aus <br> wird ein Zeilenumbruch');
|
||
$this->assert(
|
||
str_contains($text, 'Wichtiger Hinweis: Die Überweisung wird ohne Korrektur ausgeführt.'),
|
||
'Auch der letzte Absatz steht da'
|
||
);
|
||
$this->assert(!str_contains($text, "\n\n\n"), 'Keine Leerzeilenwüsten');
|
||
|
||
$this->assertEquals('', FinTsUeberweisung::vopHinweis(''), 'Ohne Text bleibt es leer');
|
||
$this->assertEquals('', FinTsUeberweisung::vopHinweis(' '), 'Leerraum zählt als kein Text');
|
||
}
|
||
|
||
private function ohneWartendenVorgangGehtNichts(): void
|
||
{
|
||
$this->assertNull(FinTsUeberweisung::offeneVopAnfrage(), 'Ohne Vorgang wartet kein Namensabgleich');
|
||
|
||
$ergebnis = FinTsUeberweisung::vopBestaetigen();
|
||
$this->assertEquals('fehler', $ergebnis['status'], 'Ohne Vorgang lässt sich nichts bestätigen');
|
||
$this->assertNotEmpty($ergebnis['meldung'], 'Und es gibt eine Erklärung dazu');
|
||
}
|
||
|
||
/**
|
||
* Meldet die Bank Namensabgleich (Volltreffer) und TAN-Anfrage im selben
|
||
* Antwortsatz, wirft php-fints (Stand v4.1.4) dafür eine rohe
|
||
* `UnsupportedException`, statt die Kombination zu behandeln – obwohl der
|
||
* Vorgang beide Angaben zu diesem Zeitpunkt schon trägt. Ungefangen landete
|
||
* ihr englischer Text als Fehlermeldung beim Nutzer (Fix #89). Geprüft wird
|
||
* hier die Erkennung selbst; der volle Ablauf (automatische Bestätigung,
|
||
* anschließende TAN-Anfrage) lässt sich ohne Bankverbindung nicht auslösen.
|
||
*/
|
||
private function dieBekannteVopTanLueckeWirdErkannt(): void
|
||
{
|
||
$istLuecke = new ReflectionMethod(FinTsUeberweisung::class, 'istBekannteVopTanLuecke');
|
||
$istLuecke->setAccessible(true);
|
||
|
||
$this->assert(
|
||
$istLuecke->invoke(null, new UnsupportedException('Combined VOP match confirmation and TAN request')),
|
||
'Die bekannte Meldung wird erkannt'
|
||
);
|
||
$this->assert(
|
||
!$istLuecke->invoke(null, new UnsupportedException('The bank does not support the XML schema x')),
|
||
'Eine andere UnsupportedException der Bibliothek wird nicht mit ihr verwechselt'
|
||
);
|
||
}
|
||
}
|