OXID eShop 4.6.x (4.6.0 – 4.6.7) auf SEPA umstellen

am 27. Dezember 2013
SEPA Zahlung

SEPA: IBAN & BIC ersetzen alte K-Nr und BLZ

Ab dem 1. Februar 2014 fällt laut Gesetz die Zahlungsmöglichkeit „Lastschrift mit Kontonummer und Bankleitzahl“ weg. Anstelle von Kontonummer und Bankleitzahl ist 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: Noch muss bei SEPA-Zahlungen die BIC immer zwingend angegeben werden, doch ab Februar 2014  ist die BIC-Nummer zumindest für inländische Zahlungen optional.

Während neuere Versionen des OXID eShops (4.8.0 oder höher) SEPA bereits von Hause aus unterstützen, muss das Verfahren für OXID eShops der Versionen 4.6.x via Hotfix nachgerüstet werden. Im Folgenden sehen Sie, was konkret notwendig ist, um den eigenen Oxid Shop auf SEPA umzurüsten.

SEPA-Hotfix und Anpassung

Der Support von OXID stellt den Hotfix. Diesen gibt es für die verschiedenen Editionen der Shopsoftware. 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.

Die core/oxinputvalidator.php unverschlüsselt zu haben, ist nützlich, da hier mit der Methode _validateDebitNote SEPA-Daten validiert werden können (dazu unten mehr).

Neben diesen Dateien aus dem core-Verzeichnis besteht der Hotfix aus Sprach-Dateien und Template-Dateien. Der Hotfix ändert nichts an der Datenstruktur in der Datenbank. 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 entweder 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.

So stellt sich die Frage: Woher weiß man, ob der Kunde  Kontonummer und Bankleitzahl eingegeben hat oder  IBAN- und BIC-Nummern? Vielleicht hat er sogar eine Kombination von alt und neu angegeben – was dann? Und was geschieht ab dem 1. Februar 2014, wenn die BIC optional wird? Der Hotfix schafft hier automatisch Klarheit: Er prüft, ob der Kunde eine korrekte BIC eingegeben hat und wenn ja, so prüft er die IBAN. Wenn nein, so werden die Formulardaten als Bankleitzahl und Kontonummer verstanden und entsprechend validiert. Ist etwas nicht korrekt, erscheint im Formular der Hinweis, dass das Feld „IBAN oder Kontonummer“ falsch ausgefüllt wurde. 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.

Probleme, wenn die BIC fehlt

Alleine der Fall, dass keine BIC angegeben wurde, aber eine IBAN (was ab Februar 2014 für inländische Zahlungen ja durchaus korrekt ist), wird nicht abgedeckt. Hier muss nachgeholfen werden, indem die Methode "_validateDebitNote" durch ein eigenes Modul überladen wird.

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 sie umzuschreiben ist:

/**
* 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;
}

So funktioniert 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;

Dabei sind zwei Dinge zu beachten:

  • Wenn wir ein eigenes Modul schreiben, das oxinputvalidator überschreibt, können wir mit "self" nicht auf dessen Fehlerkonstanten zugreifen.
  • Da die Bankleitzahl/BIC für innerdeutsche IBAN-Nummern optional wird, darf diese für oxinputvalidator kein Pflichtfeld mehr sein.

Die Lösung: 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 noch die entsprechende Template-Datei /out/*meinTemplate*/tpl/page/checkout/payment.tpl anpassen. Dort  gibt es 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}]

Dieser muss wie folgt erweitert werden:

[{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 zunächst zu prüfen, welche Dateien man selbst geä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. Das Skript prüft also, 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, das 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: Sie sollten die Dateien mit einem geeigneten Tool vergleichen.
  • Möglicherweise müssen Sprachdateien angepasst werden.

Keine Kommentare

kommentieren

Du musst angemeldet sein, um einen Kommentar abzugeben.

nach oben