nemiah / phpFinTS

PHP library to communicate with FinTS/HBCI servers
MIT License
131 stars 40 forks source link

GetStatementOfAccountXML receiving multiple CAMT XML files #370

Closed 2konrad closed 2 years ago

2konrad commented 2 years ago

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?

Philipp91 commented 2 years ago

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:

2konrad commented 2 years ago

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

2konrad commented 2 years ago

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

Philipp91 commented 2 years ago

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.

2konrad commented 2 years ago

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> '