Skip to content

Conversation

@Philipp91
Copy link
Contributor

@Philipp91 Philipp91 commented Oct 15, 2025

This is based on the draft implementation of @ampaze in #499.

@Philipp91 Philipp91 marked this pull request as draft October 15, 2025 20:59
if ($this->bpd?->vopRequiredForRequest($requestSegments) !== null) {
$hkvpp = VopHelper::createHKVPPForInitialRequest($this->bpd);
$message->add($hkvpp);
}
Copy link
Contributor

@ampaze ampaze Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HKVPP muss immer als erstes Segment bzw. vor dem eigentlichen Geschäftsvorfall geschickt werden.

@ampaze
Copy link
Contributor

ampaze commented Oct 16, 2025

Find ich sehr übersichtlich. Hoffe du kannst schnell weitermachen, es fehlt ja nicht mehr viel.

Was mir bzgl. Polling und Aufsetzpunkten noch eingefallen ist, es reicht ja eigentlich nicht das jeweils letzte HIVPP an der Action zu speichern. Es müsste eine Art "CombinedHIVPP" geben, der ggf. den Report so wie in der Spezifikation beschrieben aus mehreren HIVPP Antworten zusammensetzt. Dies würde ich aber überhaupt erst weiterdenken wenn VoP bereits funktioniert und ansonsten fertig ist, da dies sowohl auf XML Ebene als auch durch "einfaches Zusammensetzen" stattfindet, also nicht trivial ist.

@Philipp91
Copy link
Contributor Author

HKVPP muss immer als erstes Segment bzw. vor dem eigentlichen Geschäftsvorfall geschickt werden.

Echt, wo steht das? Ich finde nur (mehrfach) den Hinweis "HKVPP und der Zahlungsauftrag werden immer zusammen geschickt."

Es müsste eine Art "CombinedHIVPP" geben, der ggf. den Report so wie in der Spezifikation beschrieben aus mehreren HIVPP Antworten zusammensetzt.

Guter Punkt. Ich glaube, GetStatementOfAccountXML ist in einer ähnlichen SItuation. Und da geben wir einfach ein string[] Array an den Aufrufer raus. D.h. die phpFinTS-Bibliothek hält sich nicht nur aus dem XML-Parsing an sich raus, sondern auch aus dieser "combine XML" Angelegenheit.

@ampaze
Copy link
Contributor

ampaze commented Oct 16, 2025

HKVPP muss immer als erstes Segment bzw. vor dem eigentlichen Geschäftsvorfall geschickt werden.

Echt, wo steht das? Ich finde nur (mehrfach) den Hinweis "HKVPP und der Zahlungsauftrag werden immer zusammen geschickt."

Hab es getestet mit HKVPX nach dem Geschäftsvorfall, ging ohne Probleme. Ich habe mich wohl durch die Ablaufdiagramme in die Irre führen lassen. Mein Test hat die Segmente nun aber vorher, das kriegst du aber einfach händisch umgeändert oder?

Es müsste eine Art "CombinedHIVPP" geben, der ggf. den Report so wie in der Spezifikation beschrieben aus mehreren HIVPP Antworten zusammensetzt.

Guter Punkt. Ich glaube, GetStatementOfAccountXML ist in einer ähnlichen SItuation. Und da geben wir einfach ein string[] Array an den Aufrufer raus. D.h. die phpFinTS-Bibliothek hält sich nicht nur aus dem XML-Parsing an sich raus, sondern auch aus dieser "combine XML" Angelegenheit.

Es ist nicht ganz vergleichbar:
So wie ich es verstanden hab, kann eine Bank sich entscheiden "schrittweise Übertragung" zu machen. In diesem Falle wird ein unvollständiger Report geliefert, der für manche Einträge PDNG also Pending enthält. Per Aufsetzpunkt werden dann nur die Einträge nachgeliefert die vorher PDNG waren. D.h. an irgendeiner Stelle müssten die PDNG Einträge aus dem initialen XML durch die nachgelieferten korrekten Antworten ersetzt werden.

Und das ist zusätzlich zu eine eventuell nötigen Konkatenation von XML Teilstücken.

@seem2810
Copy link
Contributor

@ampaze ich habe versucht mit deinem REPO mal meine System zu füttern. Leider erhalte ich schon beim INIT
[2025-10-16 14:05:48] production.ERROR: Invalid response from server {"userId":1,"exception":"[object] (Exception(code: 0): Invalid response from server at /var/www/dcm/lean/vendor/ds/bank/src/Connectors/HBCI.php:339)

Mein Debugging muss ich die Tage weiter machen. Jemand sonst vielleicht eine Idee?

@ampaze
Copy link
Contributor

ampaze commented Oct 16, 2025

Hast du diesen PR oder #499 ausprobiert?

@seem2810
Copy link
Contributor

seem2810 commented Oct 16, 2025

Hast du diesen PR oder #499 ausprobiert?

#499 Ich checke diesen gleich auch noch mal.
Ich cleane gerade erstmal alles
Update: nun erhalte ich Too many elements for Fhp\Segment\CCM\HICCMSv1: HICCMS:78:1:3+1+1+0+1000:J:N'
Update 2: Nun gibt's probleme mit der Serialize. Ich muss vermutlich meine HBCI Connection Logik umbauen. (Loop)

[2025-10-17 07:33:36] production.ERROR: Cannot serialize this action, because it is not waiting for a TAN. {"userId":1,"exception":"[object] (RuntimeException(code: 0): Cannot serialize this action, because it is not waiting for a TAN. at /var/www/dcm/lean/vendor/seem2810/php-fints/lib/Fhp/BaseAction.php:84)
[stacktrace]
#0 [internal function]: Fhp\\BaseAction->__serialize()
#1 /var/www/dcm/lean/vendor/ds/bank/src/Connectors/HBCI.php(662): serialize()

Update 3: Nach Merge von #513 sieht es besser aus, nun erhalte ich: Falsche Segmentzusammenstellung [HKVPP]

@seem2810
Copy link
Contributor

Ok, da Einzelüberweisungen gehen, vermute ich, dass Sammelüberweisungen, Terminüberweisungen etc. noch nicht implementiert sind?
Ich muss mich sonst später mal mit den Segmenten auseinander setzen.

@ampaze
Copy link
Contributor

ampaze commented Oct 17, 2025

Ok, da Einzelüberweisungen gehen, vermute ich, dass Sammelüberweisungen, Terminüberweisungen etc. noch nicht implementiert sind? Ich muss mich sonst später mal mit den Segmenten auseinander setzen.

Ich bin verwirrt, du scheinst mir PRs zu vermischen? In #499 hab ich SendSEPATransferVoP implementiert und somit alle bisher unterstützten Überweisungsarten auch unterstützt. Für #499 ist keine weiterer PR nötig. Diesem PR (also #513) fehlen noch einige Dinge, damit es funktionieren kann.

@Philipp91
Copy link
Contributor Author

@ampaze @seem2810 Jetzt sollte dieser PR ähnlich viel Funktionalität bieten wie #499. Das heißt, ich bin soweit fertig.

Aber ich gehe davon aus, dass bei weiteren Tests (ohne dass ihr jetzt besonders ausgiebig testen müsstet; ich meine einfach nur bei den nächsten Gehversuchen) neue "Sonder"-Fälle auftauchen werden, die noch nicht abgedeckt sind. Idealerweise könntet ihr immer den Traffic mit der Bank mitschneiden und irgendwo so lokal bei euch speichern, dass nichts verloren geht. Wenn dann ein neuer Fall auftaucht, den die aktuelle Implementierung mit UnsupportedException, UnexpectedResponseException oder Schlimmerem quittiert, dann könnten wir direkt im Log nachsehen, wodurch sich der neue Fall auszeichnet, sodass wir gleich mit einem neuen Unit Test weitermachen können.

Wenn der Code so wie er jetzt ist zwei drei Testläufe von euch bestanden hat, würde ich mergen, dann können mehr Leute über Composer dev-master testen und ihre Erfahrungen teilen.

Lasst mich gerne auch wissen, wenn ihr Kommentare zum Code an sich habt, insbesondere wenn ihr die Dokumentation nicht verständlich findet.

@Philipp91 Philipp91 force-pushed the vop branch 2 times, most recently from 4ef8266 to 0843886 Compare October 19, 2025 15:45
@Philipp91 Philipp91 requested a review from ampaze October 19, 2025 15:48
@Philipp91 Philipp91 marked this pull request as ready for review October 19, 2025 15:48
@seem2810
Copy link
Contributor

@Philipp91 ich habe gerade deine Branch vop in meinen Gemerged und getestet.
Ich erhalte bei einer SEPA Sammelüberweisung folgende Meldung:

[2025-10-20 09:04:48] production.ERROR: FinTS errors:
9050 (global): Die Nachricht enthält Fehler.
9800 (global): Dialog abgebrochen
9110 (global): Falsche Segmentzusammenstellung [HKVPP] {"userId":1,"exception":"[object] (Exception(code: 0): FinTS errors:
9050 (global): Die Nachricht enthält Fehler.
9800 (global): Dialog abgebrochen
9110 (global): Falsche Segmentzusammenstellung [HKVPP] 

@Philipp91
Copy link
Contributor Author

@seem2810

Falsche Segmentzusammenstellung [HKVPP]

Das ist natürlich keine besonders ausführliche Info :-)

Um welche Bank handelt es sich denn?

Und könntest du bitte den Nachrichtenverlauf mitschneiden ($fints->setLogger(...)) und dann die Nachricht mit dem HKVPP-Segment posten (also die an den Server gehende Nachricht unmittelbar bevor dieser Fehler passiert)? Nur das HKVPP daraus (also bis zum nächsten ') sollte reichen, falls der Rest private Daten enthält.

@Philipp91
Copy link
Contributor Author

@ampaze In der Spezifikation auf PDF-Seite 32 (E.8.1.1.1) sieht man, dass bei einem "Match" HIVPP und HITAN gleichzeitig kommen. (Wie oben diskutiert, hast du richtigerweise darauf hingewiesen, dass man deswegen HKVPA nicht einfach weglassen darf, außer es wäre auch 3091 in der Antwort enthalten.) Aber in deinem Unit-Test sind HKVPA und HITAN separat. Liegt das daran, dass du den Unit-Test einfach vom "Close Match"-Case geforkt hast (auf der darauffolgenden PDF-Seite sieht man ja, dass in dem Fall erst HKVPA und dann später erst HITAN kommt), oder macht deine Bank das wirklich immer separat?

@Philipp91
Copy link
Contributor Author

Ich habe mal Testfälle zusammengezimmert, bei denen (a) VOP übersprungen wird aber trotzdem eine TAN nötig ist bzw. (b) beides übersprungen wird, sodass ganz ohne Polling und weitere Nachfragen der Auftrag direkt ausgeführt wird.

Wenn ihr solche Szenarien mit euren Banken nachstellen könnt, dann könnte ich den Test anhand von einem Nachrichtenverlauf verfeinern. Bis jetzt habe ich einfach nur Schnipsel von anderen Testfällen zusammengetragen, um Bank-Antworten zu erstellen, wie die Spezifikation sie grob umschreibt.

Ein drittes interessantes Szenario wäre (siehe vorheriger Post) weiterhin (c) der Fall wo sowohl VOP als auch TAN nötig sind, aber weil es ein Match ist, kann beides in einem einzigen nächsten Request abgefrühstückt werden. Denn wenn das wirklich passiert, dann hätten wir needsTan()==true && needsVopConfirmation()==true. Der Nutzer müsste dann submitTan() (nicht confirmVop()) aufrufen (das müssten wir dokumentieren), damit es weitergeht, und die submitTan()-Implementierung müsste lernen, eine VOP-Bestätigung zu schicken, falls sie noch ausstehend ist.

@ampaze
Copy link
Contributor

ampaze commented Oct 21, 2025

@ampaze In der Spezifikation auf PDF-Seite 32 (E.8.1.1.1) sieht man, dass bei einem "Match" HIVPP und HITAN gleichzeitig kommen. (Wie oben diskutiert, hast du richtigerweise darauf hingewiesen, dass man deswegen HKVPA nicht einfach weglassen darf, außer es wäre auch 3091 in der Antwort enthalten.) Aber in deinem Unit-Test sind HKVPA und HITAN separat. Liegt das daran, dass du den Unit-Test einfach vom "Close Match"-Case geforkt hast (auf der darauffolgenden PDF-Seite sieht man ja, dass in dem Fall erst HKVPA und dann später erst HITAN kommt), oder macht deine Bank das wirklich immer separat?

Ich hatte ja oben eine Antwort eines fertigen HIVPP gepostet, da ist kein HITAN dabei. HIVPP und HITAN kann evtl. gleichzeitig kommen wenn das Prüfergebnis sofort verfügbar ist, also ohne Polling. Vlt kriege ich das getestet.

@Philipp91
Copy link
Contributor Author

Ich hatte ja oben eine Antwort eines fertigen HIVPP gepostet

Ah stimmt, die Verbindung zwischen den beiden Threads habe ich im Kopf nicht gemacht. Ok perfekt, dann wissen wir, dass deine Bank es schonmal nicht so handhabt. Bei anderen Banken könnte es durchaus so sein, aber darum kümmern wir uns, wenn es zum ersten Mal passiert. Mir ist dazu gerade noch der rote Kasten aufgefallen: "Beim Decoupled-Verfahren, sollte das positive Prüfergebnis dem Kunden im Kundenprodukt parallel zur Freigabeaufforderung angezeigt werden." Also ist es schon so, dass Bibliothek und Anwendung diese Gleichzeitigkeit unterstützen müssen (wenn sie dann in der Realität vorkommt).

@ampaze
Copy link
Contributor

ampaze commented Oct 21, 2025

Also grundsätzlich läuft der PR bei mir jetzt. 👍

Ich habe Einzelüberweisungen und auch eine Echtzeitüberweisung gemacht. Auch mit Unterbrechung des PHP Prozesses.

@timrasche
Copy link

Also grundsätzlich läuft der PR bei mir jetzt. 👍

Ich habe Einzelüberweisungen und auch eine Echtzeitüberweisung gemacht. Auch mit Unterbrechung des PHP Prozesses.

Darf man fragen wie genau du das gemacht hast mit der Echtzeitüberweisung? Welche Indikatoren nutzt du dazu um es so einzureichen?

@ampaze
Copy link
Contributor

ampaze commented Oct 21, 2025

Also grundsätzlich läuft der PR bei mir jetzt. 👍
Ich habe Einzelüberweisungen und auch eine Echtzeitüberweisung gemacht. Auch mit Unterbrechung des PHP Prozesses.

Darf man fragen wie genau du das gemacht hast mit der Echtzeitüberweisung? Welche Indikatoren nutzt du dazu um es so einzureichen?

Dafür gibt es die SendSEPARealtimeTransfer Action. Mittlerweile macht Echtzeit oder nicht aber kaum noch einen Unterschied. Normale Überweisungen müssen auch innerhalb von Minuten durchgeführt werden.

@roben
Copy link

roben commented Nov 4, 2025

Nein, das wäre ein gigantischer Datenschutz-GAU wenn das möglich wäre.

Tatsächlich macht das die Sparkassen-App aber genau so. Ich war auch erstaunt.
WhatsApp Image 2025-10-30 at 10 48 01

Der Gedanke ist vermutlich, dass die Leute nicht einfach trotzdem die Überweisung durchwinken, wenn sie es mit einem Betrüger zu tun haben. Die Überprüfung ist in dem Fall einfach schon aktiviert worden, weil der Zweitname in der Überweisung gefehlt hat.

Aber ich brauche das auch nicht unbedingt.

@Philipp91
Copy link
Contributor Author

Nein, das wäre ein gigantischer Datenschutz-GAU wenn das möglich wäre.

"wäre" ...

https://www.heise.de/news/Ueberweisungen-haengen-fest-Die-Tuecken-der-Empfaengerverifikation-10761239.html#nav_bank_offenbart__1

@ampaze
Copy link
Contributor

ampaze commented Nov 4, 2025

Nein, das wäre ein gigantischer Datenschutz-GAU wenn das möglich wäre.

"wäre" ...

https://www.heise.de/news/Ueberweisungen-haengen-fest-Die-Tuecken-der-Empfaengerverifikation-10761239.html#nav_bank_offenbart__1

Hätte ich mir denken müssen, dass die Banken selbst das noch verbocken.

@Masegi
Copy link

Masegi commented Nov 4, 2025

Danke, das Beispiel kannte ich nicht, mit der Implementierung klappt ein confirm all.

p.s. das war mir trotzdem nicht ganz klar, aber ich muss danach noch ein needsTan dann machen, was in dem beispiel denke ich nicht passieren würde

@wienen-it-dev
Copy link

9310 (wrt seg 3): SEPA-Nachrichtenformat ungültig. (MDC17760326714)

Das hat nichts mit VoP zu tun, sondern:

Ebenfalls bis zum November 2025 muss auch das XML-Format pain.001.001.03, das allgemein für SEPA-Zahlungen genutzt wird, auf pain.001.001.09 umgestellt werden.

Vielen Dank für die Info.
Ist dies mit #495 bereits gelöst, oder sind noch weitere Änderungen notwendig? PR 495 ist so wie es aussieht in diesem PR bereits integriert?

Die Sepa-XML-Datei für die Transfers erzeugt man ja selber außerhalb von phpFinTS. Da musst du mal schauen, wo das in deinem Code passiert.

Vielen Dank für den Hinweis. Für die XML-Datei wird https://github.com/nemiah/phpSepaXml genutzt. Allerdings tritt nun ein anderer Fehler auf. Das XML ist unten anbei. Liegt dies an der XML-Datei oder daran, dass für VoP noch Anpassungen an der Applikation notwendig sind?

9050 (global): Die Nachricht enthält Fehler.
9010 (wrt seg 5): Zeichen außerhalb SEPA-Range
FinTS warnings:
3905 (global): Es wurde keine Challenge erzeugt.
Request segments:
HKVPP:5:1+urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.002.001.10'

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 EPC132-08_2025_V1.0_pain.001.001.09.xsd">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>1762355030</MsgId>
      <CreDtTm>2025-11-05T16:03:50</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <InitgPty>
        <Nm>XXXXX GmbH</Nm>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>1762355030</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <PmtTpInf>
        <SvcLvl>
          <Cd>SEPA</Cd>
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>
        <addChild>2025-11-05</addChild>
      </ReqdExctnDt>
      <Dbtr>
        <Nm>Y GmbH</Nm>
      </Dbtr>
      <DbtrAcct>
        <Id>
          <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
        </Id>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BIC>SXXXXXXXXXX</BIC>
        </FinInstnId>
      </DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>BelegID 221</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">10</InstdAmt>
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BIC>GXXXXXXXXXX</BIC>
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>XXXXXX GmbH</Nm>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>RE-Nr 243234234</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

@Masegi
Copy link

Masegi commented Nov 5, 2025

Wenn ich von 001 auf 009 wechsel erhalte ich auch die Meldung "Die Nachricht enthält Fehler." bzw "Das gesendete SEPA-Dokument ist nicht valide."

Ich habe dazu ein detailiertes Log im privaten bereitgestellt.

@ampaze
Copy link
Contributor

ampaze commented Nov 5, 2025

Ich würde euch empfehlen euch die entsprechende XSD zu besorgen und eure XML Dateien damit zu prüfen. Z.B. von hier https://github.com/hbci4j/hbci4java/blob/master/src/main/resources/pain.001.001.09.xsd

Es reicht nicht einfach nur 001 in 009 zu ändern, es gibt auch Änderungen an der Struktur.

@Masegi
Copy link

Masegi commented Nov 5, 2025

Also mir wird das angezeigt beim validieren:

Cvc-complex-type.2.3: Element 'ReqdExctnDt' Cannot Have Character [children], Because The Type's Content Type Is Element-only., Line '22', Column '44'.
Cvc-complex-type.2.4.b: The Content Of Element 'ReqdExctnDt' Is Not Complete. One Of '{"urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":Dt, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":DtTm}' Is Expected., Line '22', Column '44'.
Cvc-complex-type.2.4.a: Invalid Content Was Found Starting With Element '{"urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":BIC}'. One Of '{"urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":BICFI, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":ClrSysMmbId, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":LEI, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":Nm, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":PstlAdr, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":Othr}' Is Expected., Line '33', Column '16'.
Cvc-complex-type.2.4.a: Invalid Content Was Found Starting With Element '{"urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":BIC}'. One Of '{"urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":BICFI, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":ClrSysMmbId, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":LEI, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":Nm, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":PstlAdr, "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09":Othr}' Is Expected., Line '46', Column '18'.

Ich habe versucht das Datum auf ein DateTime zu setzen aber erhalte dann "Call to a member function format() on string in .../vendor/nemiah/php-sepa-xml/src/nemiah/phpSepaXml/SEPATransfer.php:39"

Da steht ja default "1999-01-01" aber das müsste wohl mit Uhrzeit sein laut dem hier oder?

<xs:element name="ReqdExctnDt" type="DateAndDateTime2Choice"/>
  <xs:complexType name="DateAndDateTime2Choice">
        <xs:choice>
            <xs:element name="Dt" type="ISODate"/>
            <xs:element name="DtTm" type="ISODateTime"/>
        </xs:choice>
    </xs:complexType>

@wienen-it-dev
Copy link

Ich würde euch empfehlen euch die entsprechende XSD zu besorgen und eure XML Dateien damit zu prüfen. Z.B. von hier https://github.com/hbci4j/hbci4java/blob/master/src/main/resources/pain.001.001.09.xsd

Es reicht nicht einfach nur 001 in 009 zu ändern, es gibt auch Änderungen an der Struktur.

Vielen Dank für den Hinweis, bei Ausführungsdatum und bei BIC waren Anpassungen notwendig.

Allerdings treten weiterhin Fehler auf bei Sparkasse (s.u.).

https://github.com/nemiah/phpSepaXml liefert für schemaLocation Folgendes:

<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 EPC132-08_2025_V1.0_pain.001.001.09.xsd">

Ist dies korrekt, oder müsste es dies sein?

<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd">

Bei Variante 2 liefert die Bank für Ausführungsdatum=aktuelles Datum eine Fehlermeldung:
9210 (wrt seg 5): Bitte geben Sie ein späteres Ausführungsdatum an. (MDC17760200012)
Mit Ausführungsdatum in der Zukunft dann eine andere Fehlermeldung (s. Variante 2).

Vollständige Fehlermeldungen:

Variante 1)

9050 (global): Die Nachricht enthält Fehler.
9010 (wrt seg 5): Zeichen außerhalb SEPA-Range
FinTS warnings:
3905 (global): Es wurde keine Challenge erzeugt.
Request segments:
HKVPP:5:1+urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.002.001.10'


<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 EPC132-08_2025_V1.0_pain.001.001.09.xsd">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>1762408392</MsgId>
      <CreDtTm>2025-11-06T06:53:12</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <InitgPty>
        <Nm/>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>1762408392</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <PmtTpInf>
        <SvcLvl>
          <Cd>SEPA</Cd>
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>
        <Dt>2025-11-07</Dt>
      </ReqdExctnDt>
      <Dbtr>
        <Nm/>
      </Dbtr>
      <DbtrAcct>
        <Id>
          <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
        </Id>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BICFI>SXXXXXXXXXX</BICFI>
        </FinInstnId>
      </DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>BelegID 221</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">10.00</InstdAmt>
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BICFI>GXXXXXXXXXX</BICFI>
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>X GmbH</Nm>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>RE-Nr 243234234 Knd-Nr 345</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

Variante 2

9050 (global): Die Nachricht enthält Fehler.
9010 (wrt seg 5): Der Auftrag wurde nicht ausgeführt.
9310 (wrt seg 3): SEPA-Nachrichtenformat ungültig. (MDC17760326714)
FinTS warnings:
3905 (global): Es wurde keine Challenge erzeugt.
3091 (wrt seg 5): VOP-Ausführungsauftrag nicht benötigt.
Request segments:
HKVPP:5:1+urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.002.001.10'
HKCSE:3:1+DEXXXXXXXXXXXXXXXXXXXX:SXXXXXXXXXX:9000000::280:60000000+urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.001.001.09+@1719@<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>1762410475</MsgId>
      <CreDtTm>2025-11-06T07:27:55</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <InitgPty>
        <Nm/>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>1762410475</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>10</CtrlSum>
      <PmtTpInf>
        <SvcLvl>
          <Cd>SEPA</Cd>
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>
        <Dt>2025-11-07</Dt>
      </ReqdExctnDt>
      <Dbtr>
        <Nm/>
      </Dbtr>
      <DbtrAcct>
        <Id>
          <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
        </Id>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BICFI>SXXXXXXXXXX</BICFI>
        </FinInstnId>
      </DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>BelegID 221</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">10.00</InstdAmt>
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BICFI>GXXXXXXXXXX</BICFI>
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>X GmbH</Nm>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>DEXXXXXXXXXXXXXXXXXXXX</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>RE-Nr 243234234 Knd-Nr 345</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

@ampaze
Copy link
Contributor

ampaze commented Nov 6, 2025

Im Test für VoP ist auch ein funktionierendes XML Beispiel mit drin:

public const XML_PAYLOAD = (
'<?xml version="1.0" encoding="UTF-8"?>' . "\n"
. '<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09"><CstmrCdtTrfInitn><GrpHdr><MsgId>M1234567890</MsgId><CreDtTm>2025-10-10T12:52:56+02:00</CreDtTm><NbOfTxs>1</NbOfTxs><CtrlSum>10.00</CtrlSum><InitgPty><Nm>PRIVATE__________________</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>P12345678</PmtInfId><PmtMtd>TRF</PmtMtd><NbOfTxs>1</NbOfTxs><CtrlSum>10.00</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>1999-01-01</Dt></ReqdExctnDt><Dbtr><Nm>PRIVATE__________________</Nm></Dbtr><DbtrAcct><Id><IBAN>DE00ABCDEFGH1234567890</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>ABCDEFGHIJK</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">10.00</InstdAmt></Amt><Cdtr><Nm>Empfänger</Nm></Cdtr><CdtrAcct><Id><IBAN>DE00ABCDEFGH1234567890</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Testüberweisung</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>'
);

Ansonsten würde ich vorschlagen die Diskussion zum XML bei https://github.com/nemiah/phpSepaXml weiter zu machen, hier geht es ja um VoP.


9210 (wrt seg 5): Bitte geben Sie ein späteres Ausführungsdatum an. (MDC17760200012)

Bei nicht terminierten Überweisungen am besten immer 1999-01-01 (<ReqdExctnDt><Dt>1999-01-01</Dt></ReqdExctnDt>) eintragen. Bei Terminierten die Vorlaufzeiten beachten.

Philipp91 added a commit to Philipp91/phpFinTS that referenced this pull request Nov 9, 2025
Proposed by ampaze@ in nemiah#513 (comment).

Co-authored-by: ampaze <ampaze@gmail.com>
Co-authored-by: Philipp Keck <git@philippkeck.de>
@wienen-it-dev
Copy link

Im Test für VoP ist auch ein funktionierendes XML Beispiel mit drin:

public const XML_PAYLOAD = (
'<?xml version="1.0" encoding="UTF-8"?>' . "\n"
. '<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09"><CstmrCdtTrfInitn><GrpHdr><MsgId>M1234567890</MsgId><CreDtTm>2025-10-10T12:52:56+02:00</CreDtTm><NbOfTxs>1</NbOfTxs><CtrlSum>10.00</CtrlSum><InitgPty><Nm>PRIVATE__________________</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>P12345678</PmtInfId><PmtMtd>TRF</PmtMtd><NbOfTxs>1</NbOfTxs><CtrlSum>10.00</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt><Dt>1999-01-01</Dt></ReqdExctnDt><Dbtr><Nm>PRIVATE__________________</Nm></Dbtr><DbtrAcct><Id><IBAN>DE00ABCDEFGH1234567890</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BICFI>ABCDEFGHIJK</BICFI></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy="EUR">10.00</InstdAmt></Amt><Cdtr><Nm>Empfänger</Nm></Cdtr><CdtrAcct><Id><IBAN>DE00ABCDEFGH1234567890</IBAN></Id></CdtrAcct><RmtInf><Ustrd>Testüberweisung</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>'
);

Ansonsten würde ich vorschlagen die Diskussion zum XML bei https://github.com/nemiah/phpSepaXml weiter zu machen, hier geht es ja um VoP.

9210 (wrt seg 5): Bitte geben Sie ein späteres Ausführungsdatum an. (MDC17760200012)

Bei nicht terminierten Überweisungen am besten immer 1999-01-01 (<ReqdExctnDt><Dt>1999-01-01</Dt></ReqdExctnDt>) eintragen. Bei Terminierten die Vorlaufzeiten beachten.

@ampaze vielen Dank für Deine Hilfe, anhand des funktionierenden XML Beispiels konnte das XML-Problem gelöst werden.

Werde dies bei https://github.com/nemiah/phpSepaXml einbringen.

Zum Thema VoP jedoch noch hier:

Bei einer Sparkassenfiliale ist die SEPA-Überweisung erfolgreich durchgeführt worden. Hierzu war nur eine Freigabe in der App notwendig (TanMode: SecureGo plus (Direktfreigabe), TanMedium nicht erforderlich).

Bei einer anderen Sparkassenfiliale jedoch nicht erfolgreich, ist dazu eine Anpassung der Anwendung wie in Atruvia/SendTransferVoPTest.php notwendig? Oder sollte das nächste offizielle Release abgewartet werden?

@ampaze
Copy link
Contributor

ampaze commented Nov 10, 2025

Bei einer Sparkassenfiliale ist die SEPA-Überweisung erfolgreich durchgeführt worden. Hierzu war nur eine Freigabe in der App notwendig (TanMode: SecureGo plus (Direktfreigabe), TanMedium nicht erforderlich).

Bei einer anderen Sparkassenfiliale jedoch nicht erfolgreich, ist dazu eine Anpassung der Anwendung wie in Atruvia/SendTransferVoPTest.php notwendig? Oder sollte das nächste offizielle Release abgewartet werden?

Für VoP sind zwingend Änderungen in den Anwendungen erforderlich. Wenn eine Überweisung bei einer Bank noch ohne diesen PR (d.h. also ohne VoP) funktioniert, dann muss das irgendein Sonderfall sein. (Bankinterne Überweisung?)

Philipp91 added a commit to Philipp91/phpFinTS that referenced this pull request Nov 10, 2025
Proposed by ampaze@ in nemiah#513 (comment).

Co-authored-by: ampaze <ampaze@gmail.com>
Co-authored-by: Philipp Keck <git@philippkeck.de>
@Philipp91 Philipp91 marked this pull request as ready for review November 10, 2025 19:50
@Philipp91
Copy link
Contributor Author

Trotz der regen Diskussion (die vielleicht in einem separaten Bug zu XML-Formaten fortgesetzt werden kann) gab es schon länger kein berichtetes Problem mehr mit dem Code hier. Also denke ich, wir können das mergen. Dann noch die Anleitung, vielleicht noch 1-2 Wochen Reifezeit während die Leute es mit dev-master kriegen, und dann kann man es releasen.

@ampaze
Copy link
Contributor

ampaze commented Nov 10, 2025

Bin auch dafür! Läuft jetzt schon einige Zeit ohne Probleme,

@roben
Copy link

roben commented Nov 11, 2025

Ja, das läuft butterweich. Getestet (mindestens) mit Sparkasse und Sparda. Sparda macht das mit dem Polling, das ging auch problemlos.

@timrasche
Copy link

Wäre es nicht auch sinnvoll die Samples auch hier in dem PR anzupassen?

@Philipp91
Copy link
Contributor Author

Philipp91 commented Nov 12, 2025

Wäre es nicht auch sinnvoll die Samples auch hier in dem PR anzupassen?

Ich finde, hier ist schon zu viel los, darum lieber separat.

Kann das entfernt werden?

Ja. Ich schicke einen PR.

Warum kann ich meine Action nicht immer serialisieren?

Die Idee war, dass es nicht nötig ist und dass man die Benutzer der Bibliothek auf typische Fehler hinweisen kann, wie z.B. "du hast vergessen, execute() aufzurufen". Für unsereins mag das offensichtlich sein, aber es gab durchaus Nutzer, die davon ausgegangen sind, dass sowas wie TransferAction::create(...) schon alles ist, was es braucht, um die Aktion auch auszuführen.

Aber dein Anwendungsfall macht Sinn und ist wichtiger.

Philipp91 and others added 6 commits November 12, 2025 20:33
That way, they can be stashed away while the user is still logging in (which requires a separate `DialogInitialization` action).
This initial version only supports confirming VOP requests (not canceling them). And for now we only extract the top-level status code from the VOP response, ignoring all the per-transfer details and additional information (like actual payee name) that the bank delivers.

This is based on the draft implementation of @ampaze in nemiah#499.
Co-authored-by: ampaze <ampaze@gmail.com>
Co-authored-by: Philipp Keck <git@philippkeck.de>
Proposed by ampaze@ in nemiah#513 (comment).

Co-authored-by: ampaze <ampaze@gmail.com>
Co-authored-by: Philipp Keck <git@philippkeck.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants