OXID eShop 4.6.x auf SEPA umstellen

SEPA ZahlungSEPA IBAN BIC Februar 2014

Bezieht sich auf die Versionen 4.6.0, 4.6.1, 4.6.2, 4.6.3, 4.6.4, 4.6.5, 4.6.6, 4.6.7.

Ab dem 1. Februar 2014 fällt laut Gesetz die Zahlungsmöglichkeit “Lastschrift mit Kontonummer und Bankleitzahl” weg. Anstelle von Kontonummer und Bankleitzahl ist ab Februar 2014 das sogenannte SEPA-Lastschriftverfahren mit IBAN- und BIC-Nummer zu verwenden.

Das SEPA-Lastschriftverfahren ist bereits heute nutzbar.

Eine kleine Besonderheit betrifft die BIC-Nummer:
Während momentan bei SEPA-Zahlungen die BIC immer zwingend angegeben werden muss, so ist die BIC-Nummer ab Februar 2014 zumindest für inländische Zahlungen optional.

Während neuere Versionen des OXID eShops (4.8.0 oder höher) bereits SEPA von Hause aus unterstützen, muss SEPA fürOXID eShop der Version 4.6.x via Hotfix nachgerüstet werden.

Im Folgenden wollen wir näher darauf eingehen, was konkret notwendig ist, um den eigenen eShop auf SEPA umzurüsten:

Den Hotfix gibt es vom Support von OXID.

Diesen gibt es für die verschiedenen Editionen von OXID. In der Community Edition (CE) ist der Hotfix komplett unverschlüsselt. In allen anderen Editionen sind folgende Dateien verschlüsselt:
- core/oxinputvalidator.php
- core/oxpayment.php
- core/oxsepavalidator.php.

Nützlich ist es, die core/oxinputvalidator.php unverschlüsselt zu haben, da es hier die Methode _validateDebitNote gibt, in welcher die SEPA-Daten validiert werden (dazu gleich mehr).

Neben den eben genannten Dateien aus dem core-Verzeichnis besteht der Hotfix aus Sprach-Dateien und Template-Dateien.

Der Hotfix ändert an der Datenstruktur in der Datenbank nichts. Es gibt auch kein Installationsskript.

Was der Hotfix konkret macht ist folgendes:
Beim bisherigen Lastschrift-Formular ändern sich die Titel für das Feld Kontonummer auf “IBAN oder Kontonummer” und bei der Bankleitzahl auf “BIC oder BLZ”. Der Kunde kann nun also wahlweise in ein- und dieselben Felder seine IBAN- und BIC-Nummern eingeben oder seine Kontonummer und Bankleitzahl.

Intern in der Datenbank wird die IBAN auch tatsächlich als Kontonummer gespeichert und die BIC als Bankleitzahl.

Stellt sich die Frage: Woher wissen wir denn nun ob der Kunde seine Kontonummer und Bankleitzahl eingegeben hat oder seine IBAN- und BIC-Nummern? Oder vielleicht hat er sogar eine Kombination aus Kontonummer und BIC oder IBAN und Bankleitzahl angegeben? Und was geschieht ab dem 1. Februar 2014, wenn die BIC optional wird?

Der Hotfix macht dazu folgendes:

Er prüft, ob der Kunde eine korrekte BIC eingegeben hat und wenn ja, so prüft er die IBAN. Ist diese nicht korrekt, erscheint im Formular der Fehler, dass das Feld “IBAN oder Kontonummer” falsch ausgefüllt wurde.
Wurde dagegen keine korrekte BIC-Nummer eingegeben, so werden die Formulardaten als Bankleitzahl und Kontonummer verstanden und entsprechend validiert.

Da BIC-Nummern auch aus Buchstaben bestehen, wird eine falsche BIC-Nummer auch niemals als korrekte Bankleitzahl durchgehen. Der Kunde erhält also in jedem Fall die Rückmeldung, dass er das Feld “BIC oder BLZ” falsch ausgefüllt hat, wenn er eine falsche BIC-Nummer oder Bankleitzahl eingeben hat.

Auch wird eine falsche Kontonummer oder IBAN korrekt erkannt. Kombinationen aus IBAN und Bankleitzahl und BIC und Kontonummer sind ebenfalls unmöglich.

Alleine der Fall, dass keine BIC angegeben wurde, aber eine IBAN (was ja ab Februar 2014 für inländische Zahlungen korrekt ist), wird nicht abgedeckt.

ready for SEPAHier muss nachgeholfen werden, indem die – oben angesprochene – Methode "_validateDebitNote" durch ein eigenes Modul überladen wird.

Hier die Methode im Original:

/**
* @param $aDebitInformation
*
* @return bool|int
*/
protected function _validateDebitNote( $aDebitInformation )
{
$aDebitInformation = $this->_cleanDebitInformation( $aDebitInformation );

$oSepaValidator = oxNew( “oxSepaValidator” );

$mxValidationResult = true;

// Check BIC / IBAN
if ( $oSepaValidator->isValidBIC( $aDebitInformation[‚lsblz‘] ) ) {
if ( !$oSepaValidator->isValidIBAN( $aDebitInformation[‚lsktonr‘] ) ) {
$mxValidationResult = self::INVALID_ACCOUNT_NUMBER;
}
} else {
$mxValidationResult = $this->_validateOldDebitInfo( $aDebitInformation );
}

return $mxValidationResult;
}

Und hier ein Vorschlag wie man sie umschreiben kann:

/**
* SEPA Handling from february 2014 on
*
* @param $aDebitInformation
* @return bool|int
*/
protected function _validateDebitNote( $aDebitInformation )
{
$aDebitInformation = $this->_cleanDebitInformation( $aDebitInformation );

$oSepaValidator = oxNew( “oxSepaValidator” );

$mxValidationResult = true;

// Check german BIC / IBAN
if($aDebitInformation[‚lsblz‘] == ”) {
if( !$oSepaValidator->isValidIBAN( $aDebitInformation[‚lsktonr‘] ) OR substr(strtoupper(trim($aDebitInformation[‚lsktonr‘])),0,2) != ‘DE’) {
$mxValidationResult = self::INVALID_BANK_CODE;
}

// Check international BIC / IBAN
} else if ( $oSepaValidator->isValidBIC( $aDebitInformation[‚lsblz‘] ) ) {
if ( !$oSepaValidator->isValidIBAN( $aDebitInformation[‚lsktonr‘] ) ) {
$mxValidationResult = self::INVALID_ACCOUNT_NUMBER;
}
} else {
$mxValidationResult = $this->_validateOldDebitInfo( $aDebitInformation );
}

return $mxValidationResult;
}

Wie man sieht, funktioniert nun die Validierung für den Zeitraum ab Februar 2014 zwar korrekt, aber unsere zurückgegebenen Fehler sind nicht aussagekräftig genug.

Um dies zu umgehen kann man eigene Fehlerkonstanten anlegen. Oder einfach direkt entsprechende Zahlenwerte zurückgeben.

Folgende Zahlenwerte benutzt oxinputvalidator bereits:

/** * Invalid account number error code for template. */ const INVALID_ACCOUNT_NUMBER = -5;

/**
* Invalid bank number error code for template.
*/
const INVALID_BANK_CODE = -4;

Weiterführend ist zu beachten:
1) Wenn wir ein eigenes Modul schreiben, das oxinputvalidator überschreibt, wir nicht mit "self" auf dessen Fehlerkonstanten zugreifen können.
2) Da die Bankleitzahl/BIC für innerdeutsche IBAN-Nummern optional wird, darf diese nicht länger ein Pflichtfeld sein für oxinputvalidator.

Hier ein Modulentwurf der alle Änderungen enthält:


/**
* SEPA Handling from february 2014 on
*/
class mymodulename_oxinputvalidator extends mymodulename_oxinputvalidator_parent{

/**
* If the bic is empty the iban has to be german
*/
const INVALID_GERMAN_IBAN_BIC_COMBINATION = -6;

/**
* lsblz is no longer required
*/
protected $_aRequiredDCFields = array( ‘lsbankname’,
‘lsktonr’,
‘lsktoinhaber’
);

/**
* Handle german bic/iban
*
* @param $aDebitInformation
* @return bool|int
*/
protected function _validateDebitNote( $aDebitInformation )
{
$aDebitInformation = $this->_cleanDebitInformation( $aDebitInformation );

$oSepaValidator = oxNew( “oxSepaValidator” );

$mxValidationResult = true;

// Check german BIC / IBAN
if($aDebitInformation[‚lsblz‘] == ”) {
if( !$oSepaValidator->isValidIBAN( $aDebitInformation[‚lsktonr‘] )
OR substr(strtoupper(trim($aDebitInformation[‚lsktonr‘])),0,2) != ‘DE’) {
$mxValidationResult = self::INVALID_GERMAN_IBAN_BIC_COMBINATION;
}

// Check international BIC / IBAN
} else if ( $oSepaValidator->isValidBIC( $aDebitInformation[‚lsblz‘] ) ) {
if ( !$oSepaValidator->isValidIBAN( $aDebitInformation[‚lsktonr‘] ) ) {
$mxValidationResult = oxInputValidator::INVALID_ACCOUNT_NUMBER;
}
} else {
$mxValidationResult = $this->_validateOldDebitInfo( $aDebitInformation );
}

return $mxValidationResult;
}

}

Damit unsere neue Fehlerkonstante INVALID_GERMAN_IBAN_BIC_COMBINATION mit ihrem Wert "-6" auch im Template entsprechend beachtet wird, müssen wir nun die entsprechende Template-Datei abändern:

/out/*meinTemplate*/tpl/page/checkout/payment.tpl

Und zwar gibt es dort den folgenden Template-Block:

[{block name="checkout_payment_errors"}]
[{assign var="iPayError" value=$oView->getPaymentError() }]
[{ if $iPayError == 1}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_COMLETEALLFIELDS" }]<div>
[{ elseif $iPayError == 2}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_AUTHORIZATIONFAILED" }]<div>
[{ elseif $iPayError == 4 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLESHIPPING" }]<div>
[{ elseif $iPayError == 5 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLEPAYMENT" }]<div>
[{ elseif $iPayError == 6 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLETSPROTECTION" }]<div>
[{ elseif $iPayError > 6 }]

<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLEPAYMENT" }]<div>
[{ elseif $iPayError == -1}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_ERRUNAVAILABLEPAYMENT" }] "[{ $oView->getPaymentErrorText() }]").<div>
[{ elseif $iPayError == -2}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_NOSHIPPINGFOUND" }]<div>
[{ elseif $iPayError == -3}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_SELECTANOTHERPAYMENT" }]<div>
[{ elseif $iPayError == -4}]
<div class="status error">[{ oxmultilang ident="MESSAGE_PAYMENT_BANK_CODE_INVALID" }]<div>
[{ elseif $iPayError == -5}]
<div class="status error">[{ oxmultilang ident="MESSAGE_PAYMENT_ACCOUNT_NUMBER_INVALID" }]<div>
[{/if}]
[{/block}]

der wie folgt erweitert werden darf:

[{block name="checkout_payment_errors"}]
[{assign var="iPayError" value=$oView->getPaymentError() }]
[{ if $iPayError == 1}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_COMLETEALLFIELDS" }]<div>
[{ elseif $iPayError == 2}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_AUTHORIZATIONFAILED" }]<div>
[{ elseif $iPayError == 4 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLESHIPPING" }]<div>
[{ elseif $iPayError == 5 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLEPAYMENT" }]<div>
[{ elseif $iPayError == 6 }]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLETSPROTECTION" }]<div>
[{ elseif $iPayError > 6 }]

<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_UNAVAILABLEPAYMENT" }]<div>
[{ elseif $iPayError == -1}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_ERRUNAVAILABLEPAYMENT" }] "[{ $oView->getPaymentErrorText() }]").<div>
[{ elseif $iPayError == -2}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_NOSHIPPINGFOUND" }]<div>
[{ elseif $iPayError == -3}]
<div class="status error">[{ oxmultilang ident="PAGE_CHECKOUT_PAYMENT_SELECTANOTHERPAYMENT" }]<div>
[{ elseif $iPayError == -4}]
<div class="status error">[{ oxmultilang ident="MESSAGE_PAYMENT_BANK_CODE_INVALID" }]<div>
[{ elseif $iPayError == -5}]
<div class="status error">[{ oxmultilang ident="MESSAGE_PAYMENT_ACCOUNT_NUMBER_INVALID" }]<div>
[{ elseif $iPayError == -6}]
<div class="status error">Sie haben keine BIC-Nummer angegeben. Dies ist nur für inländische IBAN-Nummern zulässig. Die von Ihnen eingegeben IBAN-Nummer ist jedoch keine deutsche IBAN-Nummer.<div>
[{/if}]
[{/block}]

Alternativ können hier natürlich auch wieder Sprachkonstanten verwendet werden.

Tipps, Tricks und Hinweise:

– In jedem Fall ein Backup anlegen bevor der Hotfix eingespielt wird.

– Damit der Hotfix nicht eigene Änderungen an der Original-Installation des Onlineshops überschreibt, lohnt es sich zuerst einmal zu überprüfen, welche Dateien man selbst abgeändert hat. Hierfür bietet OXID gratis eine Datei/Script namens oxchkversion.php an. Diese Datei legt man im Wurzelverzeichnis des Onlineshops ab und ruft es im Browser auf. Dieses Skript prüft, welche Dateien man gegenüber der Original-Installation selber geändert hat. Auf diese Weise sieht man bei welchen Dateien Vorsicht geboten ist.

– Vorsicht bei eigenen Template-Ordnern:
Der Hotfix überschreibt nur Template-Dateien des Azure und Basic Templates. Wenn Sie ein eigenes Template haben, dass möglicherweise genau die Dateien aus Azure ersetzt, die der Hotfix überschreibt, so laufen die Änderungen des Hotfixes ins Leere. In diesem Fall ist Handarbeit gefragt (Dateien mit einem geeigneten Tool vergleichen).

– Möglicherweise müssen Sprachdateien angepasst werden.



0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.