nemiah/phpFinTS

GetStatementOfAccountXML receiving multiple CAMT XML files

Closed this issue · 5 comments

GetStatementOfAccountXML woks well if the bank is only sending one XML file.

In case a multiple XML files in arow (e.g each for one days transactions) I get an error.

Uncaught InvalidArgumentException: Expected binary block of length 11215, got 46933
Fhp\Syntax\Parser::parseBinaryBlock('@11215@<?xml ve...')
Fhp\Syntax\Parser::parseSegmentElement('@11215@<?xml ve...', Object(Fhp\Segment\ElementDescriptor))

The problem is, that the binary block has multiple XMLs in it seperated by ":"
@11215@<?xml....>:@22456@<?xml ....>

How can the parser be enhanced to store these XMLs as seperate items?

Looks like a bug in the specification. The relevant phpFinTS line is this. Note how it accepts a single Bin instance. That's because the specification on PDF page 91 specifies "Anzahl: 1" for that element.

But in the specification's own example in section E.7.1 (PDF page 824), we can see multiple instances separated by :, as you describe it too.

I suggest you:

  • Add a unit test ./lib/Tests/Fhp/Segment/HICAZTest.php.
  • Copy the specification example from page 824 (starting from HICAZ:5:1:3+DE06940594210000027227... and then up to </Document>' a few pages onward). They inserted newlines for clarity. You can keep that division, but still join them into the required single-line string like this:
    const EXAMPLE_INPUT = "HICAZ:5:1:3+DE06940594210000027227...." .
        "foo bar ...." .
        "baz bar ....";
    
  • Use it with $hicaz = HICAZv1::parse(static::EXAMPLE_INPUT).
  • When you run this, it should fail with a similar error as you got yourself.
  • To fix it, change the field type to @var Bin[], i.e. make it an array. Maybe you'll also have to add @Max(99) like here.
  • The test case should now succeed and you can add additional assertions to make sure that $hicaz->gebuchteUmsaetze contains the desired (number of) elements.
  • Lastly, you'll have to adjust the readers of $gebuchteUmsaetze to deal with the array.

Thank you for this very structured answer. I am working on in and will give an update here.

I added the test case as described above and also tried the @var Bin[] @Max(99) in line 37 in hicazv1.php.
However the parser does not recognise the XML groups (split by :) inside the segments (split by +)correctly.

It does recognise the segments seperated by +

But: currently both segments go to gebuchteUmsaetze . The first segment should go to gebuchteUmsaetze, the second to nichtGebuchteUmsaetze.

If there are more than one XML per segment, the parser does not recognise this as a group which needs to be split at the : into seperate BINs

currently both segments go to gebuchteUmsaetze . The first segment should go to gebuchteUmsaetze, the second to nichtGebuchteUmsaetze.

Why is that so? What's the distinguishing feature? // EDIT: Sorry, ignore these rhetorical questions and also the ones below, I just didn't have time to properly rewrite this long comment, but I think the code blocks below plus the renaming suggestions are quite plausible, hope they work.

The example on page 824 is titled "E.7.1 HKCAZ ohne Aufsetzpunkt ohne vorgemerkte Umsätze", so clearly they all go to gebuchteUmsaetze. And there's five of them, so your statement "the first goes to gebuchteUmsaetze and the second goes to nichtGebuchteUmsaetze" might be correct for your example, but it can't be the general rule.

Do we first split on + and expect one (gebuchteUmsaetze) or two (gebuchteUmsaetze+nichtGebuchteUmsaetze) outputs, and then independently split each of them on : and expect n outputs?

It sounds like instead of @var Bin[] you'll need @var Bins and:

class Bins extends BaseDeg {
  /** @var Bin[] @Max(99) */
  public $bins;
}

Note that when you wrote "segments" that is what FinTS calls data element groups (I believe) and when you wrote "groups" they call it "data elements". And what they call "segment" is the entire HICAZ thing. So while the terminology in your last post might be misaligned, as long as you agree with my + and : understanding above, my proposal might work.

In fact, looking at the specification on page 91 again, I notice that gebuchteUmsaetze is DEG mandatory and nichtGebuchteUmsaetze is DE optional. So that would be:

/*
 * @var Bins
 */
public $gebuchteUmsaetze;
/*
 * @var Bin|null
 */
public $nichtGebuchteUmsaetze;

And basically what I called Bins above is on the specification page 598 in that tiny table -- maybe we should call the class GebuchteCamtUmsaetze instead of Bins. And notably, clicking on "Nicht gebuchte camt-Umsätze" instead takes you to page 634, where there is no such tiny table, which justifies that $nichtGebuchteUmsaetze won't have its own class but simply a single Bin.

Thanks for your idea regarding Bins vs Bin[]. That was what i was looking for since Bin[] did not work. Will give it a try.

Your explanation regading splitting + and : is correct in my view. I was mixing up the examples E.7.1 and E.7.3.

The structure is ...+ <XML gebuchte Umsätze> : <XML gebuchte Umsätze> ... + <XML nicht gebuchte Umsätze> '