Skip to content

TypeError when reading the minimal SEPA direct debit lead time (version 1 segments, and B2B in version 2) #581

Description

@renky

Environment

  • phpFinTS 4.1.0 (also reproducible on master)
  • PHP 8.3
  • Bank: Postbank/FYRST, but no bank connection is needed to reproduce

What happens

Reading the minimal lead time for a SEPA direct debit throws:

TypeError: Cannot assign null to property
Fhp\Segment\DSE\MinimaleVorlaufzeitSEPALastschrift::$unterstuetzteSEPALastschriftartenCodiert
of type int

MinimaleVorlaufzeitSEPALastschrift::create() accepts the two coded fields as ?int, while the
properties they are assigned to are typed non-nullable int. Three call sites inside the library
omit them, so each one throws:

Call site Affected segments
ParameterTerminierteSEPAEinzellastschriftEinreichenV1::getMinimalLeadTime() HIDSES v1
ParameterTerminierteSEPAFirmenEinzellastschriftEinreichenV1::getMinimalLeadTime() HIBSES v1
MinimaleVorlaufzeitSEPALastschrift::parseCodedB2B() HIBSES/HIBMES v2

HIDMES v1 and HIBMES v1 inherit the same defect through their shared parameter classes. In
effect the lead time is unreadable for version 1 of all four parameter segments, and for B2B in
version 2. Only CORE in version 2 works — presumably why this has gone unnoticed.

Any bank that offers these segments only in version 1 is affected. Postbank is one: the response
already stored in Tests/Unit/Integration/Postbank/PostbankIntegrationTestBase.php reproduces it.

Reproduction

No bank connection required — the segment below is Postbank's own response from the fixtures:

<?php

require __DIR__ . '/vendor/autoload.php';

use Fhp\Segment\DME\HIDMESv1;
use Fhp\Segment\DSE\MinimaleVorlaufzeitSEPALastschrift;

$parameter = HIDMESv1::parse("HIDMES:36:1:3+1+1+0+1:30:1:30:1000:J:J'")->getParameter();

try {
    $parameter->getMinimalLeadTime('RCUR');
    echo "HIDMES v1: ok\n";
} catch (TypeError $e) {
    echo 'HIDMES v1: ' . $e->getMessage() . "\n";
}

try {
    MinimaleVorlaufzeitSEPALastschrift::parseCodedB2B('1;2;120000');
    echo "B2B v2:    ok\n";
} catch (TypeError $e) {
    echo 'B2B v2:    ' . $e->getMessage() . "\n";
}

// For comparison, the one path that works today.
$core = MinimaleVorlaufzeitSEPALastschrift::parseCoded('0;1;2;120000');
echo 'CORE v2:   ok, ' . $core['CORE']['RCUR']->minimaleSEPAVorlaufzeit . " day(s)\n";

Output on 4.1.0:

HIDMES v1: Cannot assign null to property Fhp\Segment\DSE\MinimaleVorlaufzeitSEPALastschrift::$unterstuetzteSEPALastschriftartenCodiert of type int
B2B v2:    Cannot assign null to property Fhp\Segment\DSE\MinimaleVorlaufzeitSEPALastschrift::$unterstuetzteSEPALastschriftartenCodiert of type int
CORE v2:   ok, 2 day(s)

Expected

getMinimalLeadTime() returns the lead time the bank stated — one day for both sequence types in
the segment above.

Suggested fix

Both properties become ?int with a default of null, matching the signature of create().
null is the accurate value rather than a placeholder: version 1 does not transmit the two codes
at all (it states the lead time per sequence type in dedicated fields instead), and the B2B coded
format has no field for the direct debit type — for B2B no valid code even exists, since
UNTERSTUETZTE_SEPA_LASTSCHRIFTARTEN_CODIERT only lists CORE and COR1. Neither property is read
anywhere in src/, Tests/ or Samples/.

PR with the fix and regression tests for all four paths: #580

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions