nemiah / phpFinTS

PHP library to communicate with FinTS/HBCI servers
MIT License
132 stars 42 forks source link

Instant SEPA support in phpFinTS #349

Closed RubenWaterman closed 4 months ago

RubenWaterman commented 3 years ago

It would be nice if we can add Instant SEPA payments to this package. In the current implementation, I'm unable to read instant SEPA transactions until the next day (UTC time), once these transactions become a regular transaction.

I tried to take a look at it myself but I was unable to find the right place and where modifications should be made to read out HKIPZ messages in the response when asking for StatementOfAccount. If somebody is able to point me in the right direction, I'm happy to put in the time to make a pull request.

The FinTS specification for HKIPZ messages: https://github.com/hbci4j/hbci4java/files/3638616/CR0482_Anl_Unterstuetzung_von_Instant_Payments_in_FinTS_final-version.pdf

In the hbci4java package, they've added Instant SEPA support in this pull request: https://github.com/hbci4j/hbci4java/pull/36/files maybe it helps?

Philipp91 commented 3 years ago

Did you intentionally close this again?

RubenWaterman commented 3 years ago

I was going through other (unrelated) issues of this project and somebody suggested s/he was on a very old version (which was applicable to me too) so after I upgraded to the latest version and did an Instant SEPA transaction, it just appeared so I assume somebody has fixed it in the meantime, although I can't find any code related to it...

EDIT: Actually, now I'm not so sure anymore. It seems like this particular Instant SEPA transaction worked in my old and new version. I may have to wait until the weekend in order to properly test this.

RubenWaterman commented 3 years ago

Correction. I was a bit too optimistic. Apparently until 8PM or so the Instant SEPA transactions come through right away but now (after 8PM) I don't get the Instant SEPA payments in the StatementOfAccount. The issue is thus still relevant.

Philipp91 commented 3 years ago

HKIPZ clearly isn't implemented today: https://github.com/nemiah/phpFinTS/search?q=HKIPZ (It only appears in some test data.)

The FinTS specification for HKIPZ messages: https://github.com/hbci4j/hbci4java/files/3638616/CR0482_Anl_Unterstuetzung_von_Instant_Payments_in_FinTS_final-version.pdf

The HKIPZ and HKIPS messages in this specification seem to be used to send instant payments and to enquire the status of a previously sent instant payment, respectively. Neither of them seems to inform about received payments. Is that what you need?

once these transactions become a regular transaction.

I've never (consciously) used SEPA instant payments, but I know that some transactions show up with Transaction::getBooked()==false first, and later that turns to true. Maybe that's all you need?

RubenWaterman commented 3 years ago

I see! Thanks for the clarification. I presume that by default I only get the "Booked" == true? Can I include something somewhere to ask for the Booked == false as well? If so, where? My file at the moment looks like this:

$getSepaAccounts = \Fhp\Action\GetSEPAAccounts::create();
$fints->execute($getSepaAccounts);
if ($getSepaAccounts->needsTan()) {
    handleTan($getSepaAccounts); // See login.php for the implementation.
}
$oneAccount = $getSepaAccounts->getAccounts()[0];

$from = (new \DateTime())->sub(new DateInterval('P1D'));;
$to = (new \DateTime())->add(new \DateInterval('P1D'));;
$getStatement = \Fhp\Action\GetStatementOfAccount::create($oneAccount, $from, $to);
$fints->execute($getStatement);
if ($getStatement->needsTan()) {
    handleTan($getStatement); // See login.php for the implementation.
}

$soa = $getStatement->getStatement();
$alltransactions = array();
$statementnumber = 0;
foreach ($soa->getStatements() as $statement) {
    foreach ($statement->getTransactions() as $transaction) {
        $statementnumber++;
        $date = $transaction->getValutaDate()->format('Ymd'); # getBookingDate lieferte schon einmal das falsche Jahr, lieber valutadate
        if (!isset($dateCounters[$date])) {
            $dateCounters[$date] = 0;
        }
        $dateCounters[$date]++;
        $uniqId = $date.sprintf('%05d', $statementnumber).sprintf('%05d', $dateCounters[$date]);
        $arr = array(
            "txn" => $uniqId,
            "amount" => ($transaction->getCreditDebit() == \Fhp\Model\StatementOfAccount\Transaction::CD_DEBIT ? '-' : '') . $transaction->getAmount(),
            "name" => $transaction->getName(),
            "purpose" => $transaction->getMainDescription(),
            "account_number" => $transaction->getAccountNumber(),
            "date" => $transaction->getBookingDate()->format('d-m-Y')
        );
        array_push($alltransactions, $arr);
    }
}
echo json_encode($alltransactions);
ampaze commented 3 years ago

Correction. I was a bit too optimistic. Apparently until 8PM or so the Instant SEPA transactions come through right away but now (after 8PM) I don't get the Instant SEPA payments in the StatementOfAccount. The issue is thus still relevant.

I am pretty sure this is just your banks "working hours". Which bank is it btw? Just because it is called "instant" does not mean it really is instant and around the clock.

RubenWaterman commented 3 years ago

I am pretty sure this is just your banks "working hours". Which bank is it btw? Just because it is called "instant" does not mean it really is instant and around the clock.

It's Volksbank Raffeisenbank. The payments do arrive as I can see them in the online banking interface on their own website. Additionally, I use MoneyMoney which also uses this FinTS protocol in the background to retrieve data and in there the Instant SEPA transactions also do show up (albeit as pending and without the payment description visible).

Philipp91 commented 3 years ago

Can I include something somewhere to ask for the Booked == false as well?

I don't think so, because I think they're included by default. That's why my application has to filter them out. There's certainly no bit you could flip in the HKKAZv7 request.

It would be nice if we can add Instant SEPA payments to this package.

How "nice" would it be? Is it important for your application? If you say that there's no payment description, then how useful would it really be?

The reason I filter out un-booked transactions in my application is that crucial details (like the other party's name) can change in subtle ways (Umlauts, ordering of first and last name, whether an address is present, etc.) when the transaction gets booked into the system. I use some kind of hashing to match FinTS-received transactions against the ones already in my database, and due to these changes I would often have duplicate (un-booked and booked) transactions in my database in the end. So: Are you sure you want instant payments before they're booked?

(Side note: If you only use booked transactions, you don't even need any hashing of details or so. You can identify a transaction simply by the date and the "index" in the transaction history of that day.)

I use MoneyMoney which also uses this FinTS protocol in the background to retrieve data and in there the Instant SEPA transactions also do show up

Can you log its FinTS traffic and check which segment type they use for this?

ampaze commented 3 years ago

Btw. I intented to implement sending instant payments, but the process is actually not really well thought out in my opinion:

As not every destination bank supports instant payments, you can initiate the payment and your bank accepts it but that does not mean you are done. You have to check for failure and then resend the payment as non instant. Which makes the whole process more complicated.

For example you can't even really automate the resending as you would need another TAN to authorize it.

nemiah commented 4 months ago

done #441