Zahlungs-Plugins¶
Ein Zahlungs-Plugin definiert über den Knoten <PaymentMethod>
in der info.xml
eine oder mehrere
Zahlungsmethoden, die dann über eine Zuordnung zu Versandarten im Onlineshop für Bezahlvorgänge genutzt werden
können.
Die grundsätzliche XML-Struktur einer Zahlungsmethode finden Sie im Abschnitt Zahlungsmethoden
unter Die info.xml
.
Grundlegendes¶
Jede Zahlungsmethode wird durch eine Payment-Klasse repräsentiert. Der Klassenname und die zugehörige Klassendatei
werden in der info.xml
mit den Knoten <ClassName>
und <ClassFile>
festgelegt. Die Klassendatei muss sich
für eine erfolgreiche Validierung der Zahlungsmethode im Unterverzeichnis paymentmethod
innerhalb des
Plugin-Verzeichnisses befinden. Bezeichner für Klassenname und Klassendatei müssen der PSR-4-Spezifikation
folgen.
Jede Payment-Klasse muss ab Version 5.0 das Interface JTL\Plugin\Payment\MethodInterface
implementieren oder die Klasse
JTL\Plugin\Payment\Method
erweitern.
Über die Methoden der Payment-Klasse wird standardmäßig der komplette Zahlungsvorgang abgedeckt. Die Registrierung
weiterer Hooks für den Zahlungsprozess ist normalerweise nur notwendig, wenn durch die Zahlungsmethode weitergehende
Eingriffe in den Ablauf des Zahlungsvorganges oder des gesamten Bestellprozesses notwendig sind.
Implementation einer Payment-Klasse ab JTL-Shop Version 5.0¶
Hint
Im Weiteren wird von einer Implementation für JTL-Shop Version 5.2.x ausgegangen.
<?php declare(strict_types=1);
namespace Plugin\jtl_example_payment\paymentmethod;
use JTL\Plugin\Payment\Method;
/**
* Class SimplePayment.
*/
class SimplePayment extends Method
{
// ...
}
Die Basis-Payment-Klasse JTL\Plugin\Payment\Method
implementiert das benötigte Interface und stellt alle
grundlegenden Funktionen einer Zahlungsmethode zur Verfügung. Die eigene Payment-Klasse sollte deshalb immer diese
Basis-Klasse erweitern.
Eine einfache Zahlungsmethode, die lediglich Informationen für eine Banküberweisung versendet, muss damit lediglich die
Methode preparePaymentProcess
überschreiben.
<?php declare(strict_types=1);
namespace Plugin\jtl_example_payment\paymentmethod;
use JTL\Checkout\Bestellung;
use JTL\Mail\Mail\Mail;
use JTL\Mail\Mailer;
use JTL\Plugin\Helper as PluginHelper;
use JTL\Plugin\Payment\Method;
use JTL\Plugin\PluginInterface;
use JTL\Plugin\State;
use JTL\Session\Frontend;
use JTL\Shop;
use stdClass;
/**
* Class SimplePayment
* @package Plugin\jtl_example_payment\paymentmethod
*/
final class SimplePayment extends Method
{
private const MAILTEMPLATE_SIMPLEPAYMENT = 'kPlugin_%d_SimplePaymentTransferData';
/** @var PluginInterface|null */
private ?PluginInterface $plugin;
/**
* @inheritDoc
*/
public function init(int $nAgainCheckout = 0): self
{
parent::init($nAgainCheckout);
$this->plugin = PluginHelper::getPluginById('jtl_example_payment');
return $this;
}
/**
* @inheritDoc
*/
public function isValidIntern(array $args_arr = []): bool
{
return parent::isValidIntern($args_arr)
&& $this->plugin !== null
&& $this->plugin->getState() === State::ACTIVATED;
}
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
$obj = new stdClass();
$obj->tkunde = Frontend::getCustomer();
$obj->tbestellung = $order;
$tplKey = \sprintf(self::MAILTEMPLATE_SIMPLEPAYMENT, $this->plugin->getID());
/** @var Mailer $mailer */
$mailer = Shop::Container()->get(Mailer::class);
$mailer->getHydrator()->add('Bestellung', $order);
$mail = new Mail();
try {
$mailer->send($mail->createFromTemplateID($tplKey, $obj));
} catch (\Exception) {
Shop::Container()->getAlertService()->addError(
__('Payment mail for Simple payment cant be send'),
'simplePaymentCantSendMail'
);
}
}
}
Die Methode preparePaymentProcess
wird durch den Bestellabschluss nach Abschluss der Bestellung aufgerufen und
startet den Bezahlvorgang der Zahlungsmethode.
Im Beispiel wird das über die info.xml
definierte E-Mail-Template für die Zahlungsmethode geladen und über den
Mailer-Service von JTL-Shop versendet.
Zahlung vor Bestellabschluss¶
Im Modus "Zahlung vor Bestellabschluss" wird beim Abschluss des Bestellvorganges durch den Kunden, die Bestellung
nicht in der Datenbank gespeichert! Die Bestellung existiert weiterhin nur in der aktuellen Kunden-Session.
Die Zahlungsmethode muss bei erfolgreicher Zahlung über einen Aufruf von /includes/modules/notify.php
dafür sorgen,
dass der Kunde zum Bestellabschluss gelangt und die Bestellung festgeschrieben wird. Dies kann z. B. über eine
URL-Weiterleitung erfolgen. Die dafür notwendige URL kann mittels
getNotificationURL ermittelt werden.
Im Fehlerfall kann der Kunde zurück in den Bestellprozess geleitet werden, um die Bezahlung ggf. zu wiederholen oder
den Checkout mit einer anderen Zahlungsart fortsetzen zu können.
Warning
Bei Zahlungsmethoden, die eine zeitversetzte Bestätigung der Zahlung via Webhook versenden, kann es passieren, dass die Bestellung nicht mehr gespeichert werden kann, da diese aufgrund einer abgelaufenen Kunden-Session bereits verfallen ist. In diesem Fall existiert dann eine Zahlung, zu der es keine Bestellung gibt! Für solche Zahlungsmethoden sollte besser nur der Modus "Zahlung nach Bestellabschluss" gewählt werden.
Die "Zahlung vor Bestellabschluss" kann für die Zahlungsmethode über den XML-Parameter <PreOrder>1</PreOrder>
voreingestellt werden. Dieser Wert lässt sich jedoch in den Einstellungen der Zahlungsmethode vom Betreiber des
Onlineshops nachträglich ändern.
Zahlung nach Bestellabschluss¶
Im Modus "Zahlung nach Bestellabschluss" wird die Bestellung komplett abgeschlossen und in der Datenbank gespeichert, bevor der Bezahlvorgang gestartet wird. Die Zahlungsmethode muss hier dafür sorgen, dass bei erfolgreicher Zahlung die Bestellung per setOrderStatusToPaid auf den Status "bezahlt" gesetzt und mittels addIncomingPayment der Zahlungseingang gespeichert wird. Ein Zahlvorgang, der in diesen Modus läuft, kann normalerweise auch neu gestartet werden, falls Fehler aufgetreten sind. Die Zahlungsmethode sollte dies dann auch entsprechend signalisieren. Siehe hierzu auch canPayAgain Ein Rücksprung in den Bestellvorgang und die Auswahl einer anderen Zahlungsmethode durch den Kunden ist jedoch nicht möglich.
Die "Zahlung nach Bestellabschluss" kann für die Zahlungsmethode über den XML-Parameter <PreOrder>0</PreOrder>
voreingestellt werden. Dieser Wert lässt sich jedoch in den Einstellungen der Zahlungsmethode vom Betreiber des
Onlineshops nachträglich ändern.
Hint
Sollte die Zahlungsmethode nur einen der beiden Modi unterstützen, dann sollte bei geänderter Einstellung über HOOK_PLUGIN_SAVE_OPTIONS ein entsprechender Hinweis ausgegeben und die Zahlungsmethode über isValidIntern als "nicht verfügbar" markiert werden. Ein Beispiel dafür befindet sich in Programmierbeispiele im Zusammenhang mit Zahluns-Plugins.
Zahlung VOR vs. NACH Bestellaschluss¶
Diese Einstellung hat keinerlei Einfluss darauf, wie der Ablauf einer Zahlung im Frontend gestaltet wird. Dies obliegt dem Plugin. Der Shop-Core regelt darüber jedoch die Speicherung der Zahlung in der Datenbank. Jede Variante hat Vor- und Nachteile. Eine Zahlung vor Bestellabschluss kann z.B. abgebrochen und durch den Kunden eine komplett andere Zahlungsart gewählt werden, wenn z.B. beim Bezahlvorgang Fehler auftreten oder eine Zahlung anderweitig nicht möglich ist (z.B. Kreditkarte abgelaufen). Bei der Zahlung nach Bestellabschluss ist dies nicht mehr möglich. Zahlungsvorgänge die sehr lange dauern können (z.B. Ratenzahlung mit entsprechender Risiko- / Bonitätsprüfung) und den endgültigen Status erst per s.g. Webhook an den Shop übermitteln, lassen sich mit "Zahlung nach Bestellabschluss" einfacher implementieren. Hierbei wird zuerst die Bestellung in der DB gespeichert und es muss nicht mehr die Kunden-Session beachtet werden.
Beschreibung der Payment-Klasse JTL\Plugin\Payment\Method
¶
public function init(): self¶
Wird bei jedem Instanziieren der Zahlungsmethode aufgerufen. In der Payment-Basisklasse werden die Properties
caption
und duringCheckout
initialisiert. Als Rückgabewert wird die Klasseninstanz selbst erwartet.
Diese Methode sollte überschrieben werden, wenn eigene Initialisierungen vorgenommen werden müssen. Z.B. können hier
die notwendigen Sprachdateien des Plugins geladen werden, um eine saubere Trennung von Code und
Sprache zu ermöglichen.
/**
* @inheritDoc
*/
public function init(int $nAgainCheckout = 0): self
{
parent::init($nAgainCheckout);
$pluginID = PluginHelper::getIDByModuleID($this->moduleID);
$this->plugin = PluginHelper::getLoaderByPluginID($pluginID)->init($pluginID);
Shop::Container()->getGetText()->loadPluginLocale(
'simple_payment',
$this->plugin
);
Shop::Smarty()->assign('pluginLocale', $this->plugin->getLocalization());
return $this;
}
public function getOrderHash(): ?string¶
Der Shop-Core generiert beim Speichern einer Bestellung eine Unique ID und ordnet diese eindeutig einer Bestellung zu.
Mittels der Methode getOrderHash
kann diese Unique ID für eine bestehende Bestellung ermittelt werden.
Diese Methode muss normalerweise nicht überschrieben werden.
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
SimplePaymentAPI::Call('CapturePayment', $this->getOrderHash($order));
}
Hint
Bei der Übergabe von Referenzen auf eine Shop-Bestellung (z.B. mittels API-Call oder URL-Parameter) sollte immer diese Unique ID anstelle eines direkten Datenbank-Schlüssels verwendet werden, um Angreifern nicht die Möglichkeit zu bieten, durch z.B. einfaches Hochzählen die Kennung einer Bestellung zu "erraten".
public function getReturnURL(): string¶
Die Methode getReturnURL
liefert eine absolute URL für die Abschlussseite der Bestellung bei erfolgreicher Zahlung
und muss normalerweise nicht überschrieben werden.
Dies ist standardmäßig eine Route auf /bestellabschluss?i=<OrderHash>
oder (je nach Einstellung des Parameters
"Abschluss-Seite nach externer Bezahlung") /status.php?uid==<cUID>
. Für die Erzeugung des
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
$result = SimplePaymentAPI::Call('CapturePayment', $this->getOrderHash($order));
if ($result === 'OK') {
header('Location: ' . $this->getReturnURL($order), true, 303);
exit();
}
}
public function getNotificationURL(): string¶
Mittels getNotificationURL
kann die URL zum Shop ermittelt werden, die bspw. bei einer externen Weiterleitung
zu einem Zahlungsanbieter als Return-URL übergeben wird. Diese URL sollte in einem "Zahlung vor Bestellabschluss"-Szenario
als Return-URL verwendet werden. Der übergebene Parameter für den Session-Hash kann dabei über
generateHash ermittelt werden. Diese Methode sollte überschrieben werden,
wenn für die Rückkehr vom Zahlungsanbieter ein eigener Einstiegspunkt vom Plugin verwendet wird.
Diese URL ist immer eine absolute Shop-URL.
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
SimplePaymentAPI::Call('InitPayment', (object)[
'PaymentAction' => 'Sale',
'ButtonSource' => 'Cart',
'ItemTotal' => $order->fGesamtsumme,
'ReturnURL' => $this->getNotificationURL($this->generateHash($order))
]);
}
public function updateNotificationID(): self¶
Diese Methode kann verwendet werden, um die Notify-ID einer Zahlungssession für eine bestehende Bestellung mit einem eigenen Wert zu überschreiben. Dies ist normalerweise nicht notwendig. Diese Funktion wird nicht vom Shop-Core aufgerufen und muss normalerweise nicht überschrieben werden.
public function getShopTitle(): string¶
Liefert den Namen des Onlineshops, der ggf. an einen Payment-Provider übergeben wird. In der Payment-Basisklasse wird hier der Name des Onlineshops aus der Konfiguration ermittelt. Diese Methode muss normalerweise nicht überschrieben werden.
public function preparePaymentProcess(): void¶
Die Methode preparePaymentProcess
wird durch den Bestellabschluss nach Finalisierung der Bestellung aufgerufen und
startet den Bezahlvorgang der Zahlungsmethode.
Je nachdem, ob die Zahlungsmethode im Modus "Zahlung vor Bestellabschluss" oder "Zahlung nach Bestellabschluss"
ausgeführt wird, ist zum Zeitpunkt des Aufrufs die zugrundeliegende Bestellung bereits in der Tabelle tbestellung
persistiert oder sie existiert nur innerhalb der aktiven Kunden-Session.
Hint
Im Modus "Zahlung vor Bestellabschluss" muss diese Methode dafür sorgen, dass mittels Aufruf von
/includes/modules/notify.php
der Bestellabschluss ausgeführt und damit die Bestellung festgeschrieben wird.
Die URL für diesen Aufruf kann über getNotificationURL ermittelt werden.
Die Payment-Basisklasse definiert diese Methode ohne Funktionalität, so dass diese in jedem Fall überschrieben werden muss!
Beispiel für eine Implementation im Modus "Zahlung nach Bestellabschluss".
/**
* @inheritDoc
*/
public function preparePaymentProcess($order): void
{
parent::preparePaymentProcess($order);
$credentials = Frontend::get(self::USERCREDENTIALS, []);
$serviceProvider = new ServiceProvider($this->getSetting('prepaid_card_provider_url'));
try {
$payValue = $order->fGesamtsumme;
if ($payValue <= 0) {
$this->setOrderStatusToPaid($order);
return;
}
$hash = $this->generateHash($order);
$payment = $serviceProvider->payPrepaidTransaction(
'PrepaidPayment: '.$hash,
$this->getSetting('prepaid_card_merchant_login'),
$this->getSetting('prepaid_card_merchant_secret'),
$credentials['token'],
'',
$payValue
);
$payStatus = $payment->paymentValue >= $payValue
? self::PAYSTATUS_SUCCESS
: self::PAYSTATUS_PARTIAL;
$this->deletePaymentHash($hash);
$this->addIncomingPayment($order, (object)[
'fBetrag' => $payment->payment_value,
'cZahler' => $credentials['name'],
'cHinweis' => $payment->payment_key,
]);
if ($payStatus === self::PAYSTATUS_SUCCESS) {
$this->setOrderStatusToPaid($order);
}
} catch (ServiceProviderException $e) {
Shop::Container()->getAlertService()->addError(
$e->getMessage(),
'paymentFailed'
);
}
}
public function sendErrorMail(): self¶
Diese Methode ist eine Debug-Funktion und kann verwendet werden, um im Falle eines Fehlers eine E-Mail direkt an den Shop-Betreiber zu versenden. Diese Funktion wird nicht vom Shop-Core aufgerufen und muss normalerweise nicht überschrieben werden.
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
$result = SimplePaymentAPI::Call('CapturePayment', $this->getOrderHash($order));
if ($result === 'OK') {
header('Location: ' . $this->getReturnURL($order), true, 303);
} elseif ($result === 'API CALL DENIED') {
$this->sendErrorMail('API CALL DENIED: ' . SimplePaymentAPI::getAPIState());
}
}
public function generateHash(): string¶
Die Methode generateHash
erzeugt zu einer Bestellung eine Unique ID. Je nach Szenario (Zahlung vor / nach Bestellabschluss)
ist der erzeugte Hash unterschiedlich zu interpretieren.
- Ist die übergebene Bestellung eine persistierte Bestellung (kBestellung > 0), wird die dieser Bestellung zugeordnete Unique ID zurückgeliefert (siehe: public function getOrderHash(): ?string).
- Ist die übergebene Bestellung noch nicht in der Datenbank gespeichert (kein Primärschlüssel gesetzt), so wird eine neue Unique ID erzeugt und diese an die aktuelle Kunden-Session gebunden.
Zur Unterscheidung zwischen Bestellung- und Session-Key, wird der Session-Key mit einem führenden Unterstrich (_) versehen. Diese Methode kann für die Verwendung eines eigenen Key-Handlings überschrieben werden.
public function deletePaymentHash(): self¶
Mit Hilfe dieser Methode wird die Zuordnung einer Bestellung zu einer Unique ID (siehe: public function getOrderHash(): ?string) gelöscht. Diese Methode wird nicht vom Shop-Core aufgerufen und muss normalerweise nicht überschrieben werden. Ein Aufruf dieser Methode ist z.B. dann sinnvoll, wenn die Verbindung einer gespeicherten Bestellung zu einer Unique ID, die für API-Calls oder URLs verwendet wurde, aus Sicherheitsgründen dauerhaft zu löschen.
Warning
Eine gelöschte Beziehung einer Bestellung zu einer Unique ID kann nicht rückgängig gemacht werden.
public function addIncomingPayment(): self¶
Über addIncomingPayment
wird ein Zahlungseingang angelegt. Die Methode der Payment-Basisklasse legt dazu in der
Tabelle tzahlungseingang
einen entsprechenden Eintrag an. Diese Methode muss normalerweise nicht überschrieben
werden.
public function setOrderStatusToPaid(): self¶
Mit setOrderStatusToPaid
wird die übergebene Bestellung in den Status "bezahlt" versetzt. Die Methode der
Payment-Basisklasse führt dazu ein Update der Tabelle tbestellung
durch. Diese Methode muss normalerweise nicht
überschrieben werden.
public function sendConfirmationMail(): self¶
Ein Aufruf von sendConfirmationMail
der Payment-Basisklasse versendet über die Methode
sendMail die Standard-E-Mail für "Bestellung bezahlt". Diese Methode
muss normalerweise nicht überschrieben werden.
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
$payment = SimplePaymentAPI::Call('CapturePayment', $this->getOrderHash($order));
if ($payment->result === 'OK') {
$this->addIncomingPayment($order, (object)[
'fBetrag' => $payment->amount,
'fZahlungsgebuehr' => $payment->fee,
'cHinweis' => $payment->additionalText,
]);
$this->setOrderStatusToPaid($order);
$this->sendConfirmationMail($order);
header('Location: ' . $this->getReturnURL($order), true, 303);
}
}
public function handleNotification(): void¶
Die Methode handleNotification
wird aufgerufen, wenn /includes/modules/notify.php
über
die Notification-URL (siehe public function getNotificationURL(): string) ausgeführt wird. In einem
"Zahlung vor Bestellabschluss"-Szenario erfolgt der Aufruf, nachdem der Shop die Bestellung angelegt hat.
Über den Parameter $args
besteht hiermit die Möglichkeit für die Zahlungsart auf Rückgaben des Zahlungs-Providers
zu reagieren.
/**
* @inheritDoc
*/
public function handleNotification(Bestellung $order, string $hash, array $args): void
{
parent::handleNotification($order, $hash, $args);
if (isset($args['additionalPaymentInformation'])) {
$this->sendMail(
$order->kBestellung,
'kPlugin_' . $this->plugin->getID() . '_paymentinformation',
$args['additionalPaymentInformation']
);
}
}
public function finalizeOrder(): bool¶
Diese Methode wird aufgerufen, unmittelbar bevor in einem "Zahlung vor Bestellabschluss"-Szenario die Bestellung durch den Shop
angelegt wurde. Der Zahlungsart wird dadurch die Möglichkeit gegeben abschließende Prüfungen vorzunehmen und über den
Rückgabewert der Funktion Einfluss auf die Persistierung der Bestellung zu nehmen.
Die Basis-Klasse implementiert diese Funktion mit einem Rückgabewert false
, so dass diese Methode für eine "Zahlung vor Bestellabschluss"
überschrieben werden muss. In einem "Zahlung nach Bestellabschluss"-Szenario wird diese Funktion nicht verwendet,
/**
* @inheritDoc
*/
public function finalizeOrder(Bestellung $order, string $hash, array $args): bool
{
if (isset($args['paymentresult']) && $args['paymentresult'] === 'DECLINED') {
// do something to inform customer
...
return false;
}
return true;
}
public function redirectOnCancel(): bool¶
Diese Methode wird nur in einem "Zahlung vor Bestellabschluss"-Szenario verwendet und muss entsprechend überschrieben werden.
redirectOnCancel
wird aufgerufen, wenn public function finalizeOrder(): bool false
zurückliefert
und dadurch die Bestellung nicht gespeichert wurde.
Um eine korrekte Funktionalität und vor allem Anzeige zu gewährleisten, muss diese Funktion entweder
true
zurückgeben, dann wird automatisch auf die Zahlungsart-Auswahlseite weitergeleitetfalse
zurückgeben und das über dieinfo.xml
defnierte Template initialisieren (Smarty-Variablen befüllen)- oder selbst einen passenden Redirect ausführen.
public function redirectOnPaymentSuccess(): bool¶
Diese Methode wird nur in einem "Zahlung vor Bestellabschluss"-Szenario verwendet und muss entsprechend überschrieben werden.
redirectOnPaymentSuccess
wird aufgerufen, wenn public function finalizeOrder(): bool true
zurückgeliefert hat
und die Bestellung vom Shop gespeichert wurde.
Um eine korrekte Funktionalität und vor allem Anzeige zu gewährleisten, muss diese Funktion entweder
true
zurückgeben, dann wird automatisch auf die von public function getReturnURL(): string zurückgelieferte URL weitergeleitetfalse
zurückgeben und das über dieinfo.xml
defnierte Template initialisieren (Smarty-Variablen befüllen)- selbst einen passenden Redirect ausführen.
public function doLog(): self¶
Die Methode doLog
schreibt einen Eintrag ins Zahlungslog der Zahlungsart.
/**
* @inheritDoc
*/
public function preparePaymentProcess(Bestellung $order): void
{
parent::preparePaymentProcess($order);
...
$payment = SimplePaymentAPI::Call('CapturePayment', $this->getOrderHash($order));
if ($payment->result === 'OK') {
...
} else {
$this->doLog('API error: ' . $payment->result, \LOGLEVEL_ERROR);
}
}
public function getCustomerOrderCount(): int¶
Mit dieser Methode der Payment-Basisklasse wird zu einem bestehenden Kunden die Anzahl an Bestellungen ermittelt, die "in Bearbeitung", "bezahlt" oder "versandt" sind. Diese Methode muss normalerweise nicht überschrieben werden.
public function loadSettings(): self¶
Diese Methode initialisiert die Eigenschaft $this->paymentConfig
mit der aktuellen Konfiguration der Standard-Zahlungsarten.
loadSettings
muss explizit einmalig (z.B. in public function init(): self aufgerufen werden, wenn über
$this->paymentConfig
auf die Konfiguration der Standard-Zahlungsarten zugegriffen werden soll. $this->paymentConfig
enthält nach dem Aufruf
ein Array in der Form:
array (
'zahlungsart_nachnahme_min_bestellungen' => 0,
'zahlungsart_nachnahme_min' => '0',
'zahlungsart_nachnahme_max' => '0',
'zahlungsart_lastschrift_min_bestellungen' => 0,
'zahlungsart_lastschrift_min' => '0',
'zahlungsart_lastschrift_max' => '0',
'zahlungsart_lastschrift_bic_abfrage' => 'O',
'zahlungsart_lastschrift_kontoinhaber_abfrage' => 'Y',
'zahlungsart_lastschrift_kreditinstitut_abfrage' => 'O',
'zahlungsart_rechnung_min_bestellungen' => 0,
'zahlungsart_rechnung_min' => '10',
'zahlungsart_rechnung_max' => '0',
'zahlungsart_ueberweisung_min_bestellungen' => 0,
'zahlungsart_ueberweisung_min' => '0',
'zahlungsart_ueberweisung_max' => '0',
'zahlungsart_barzahlung_min_bestellungen' => 0,
'zahlungsart_barzahlung_min' => '0',
'zahlungsart_barzahlung_max' => '0',
)
Die Methode muss normalerweise nicht überschrieben werden.
/**
* @inheritDoc
*/
public function init(int $nAgainCheckout = 0): self
{
parent::init($nAgainCheckout);
...
$this->loadSettings();
return $this;
}
public function getSetting(): mixed¶
Mit Hilfe von getSetting
kann eine gespeicherte Einstellung zur Zahlungsart ermittelt werden. Diese Methode kann
für den Zugriff auf eine eigene Konfiguration überschrieben werden.
/**
* @inheritDoc
*/
public function isValid(object $customer, Cart $cart): bool
{
return (int)$this->getSetting('min_bestellungen') >= $this->getCustomerOrderCount($customer->kKunde);
}
public function isValid(): bool¶
Diese Methode gibt die Validität der Zahlungsmethode im aktuellen Zahlvorgang - also abhängig von Kunde und / oder
Warenkorb - an.
Bei Rückgabe von false
wird die Zahlungsmethode im Bestellprozess nicht angeboten bzw. als ungültig
zurückgewiesen. Der Rückgabewert true
zeigt dagegen an, dass die Zahlungsart verwendet werden kann.
In der Payment-Basisklasse wird hier das Ergebnis von isValidIntern
und zusätzlich die Erfüllung der Bedingungen für die Mindestanzahl an Bestellungen durch den Kunden sowie der
Mindestbestellwert im aktuellen Warenkorb geprüft.
Diese Methode muss nur überschrieben werden, wenn eigene kunden- und warenkorbabhängige Bedingungen geprüft werden
müssen.
/**
* @inheritDoc
*/
public function isValid(object $customer, Cart $cart): bool
{
return parent::isValid($customer, $cart) && !$this->isBlacklisted($customer->cMail);
}
public function isValidIntern(): bool¶
Mit dieser Methode wird die grundsätzliche (interne) Validität der Zahlungsmethode geprüft.
Ein Rückgabewert true
signalisiert hierbei, dass die Zahlungsmethode gültig ist und verwendet werden kann.
Bei Rückgabe von false
wird die Zahlungsmethode als ungültig angesehen und im Bestellprozess nicht zur Auswahl
angezeigt.
Im Gegensatz zu isValid erfolgt die Prüfung unabhängig vom
aktuellen Zahlvorgang. Die Implementation der Payment-Basisklasse liefert immer true
. Diese Methode muss also
überschrieben werden, wenn die Zahlungsmethode aufgrund "interner" Gründe wie fehlender oder fehlerhafter
Konfiguration nicht verfügbar ist.
/**
* @inheritDoc
*/
public function isValidIntern($args_arr = []): bool
{
if (empty($this->getSetting('postpaid_card_provider_url'))
|| empty($this->getSetting('postpaid_card_login_url'))
|| empty($this->getSetting('postpaid_card_merchant_login'))
|| empty($this->getSetting('postpaid_card_merchant_secret'))
) {
$this->state = self::STATE_NOT_CONFIGURED;
return false;
}
return parent::isValidIntern($args_arr);
}
public function isSelectable(): bool¶
Mit isSelectable
steht eine Möglichkeit zur Verfügung, die Zahlungsmethode im Bestellprozess auszublenden.
Im Unterschied zu isValid und
isValidIntern wird diese Methode für reine Frontend-Bedingungen
genutzt.
Dies ist z. B. dann der Fall, wenn eine grundsätzlich zulässige Zahlungsmethode nicht in der Liste zur Auswahl der
Versand- und Zahlungsart aufgeführt werden soll, weil diese nur für einen Expresskauf-Button oder für ein direktes
Bezahlen am Artikel oder aus dem Warenkorb heraus genutzt wird.
In der Payment-Basisklasse liefert diese Methode immer das Ergebnis von
isValid.
/**
* @inheritDoc
*/
public function isSelectable(): bool
{
return parent::isSelectable() && !$this->isExpressPaymentOnly();
}
Note
Die Methoden isValidIntern()
, isValid()
und isSelectable()
bedingen einander. Dabei hat
isValidIntern()
die höchste und isSelectable()
die geringste Wertigkeit. Eine Zahlungsmethode, die über
isValidIntern()
false
liefert, ist auch nicht valide und auch nicht auswählbar. Eine nicht auswählbare
Zahlungsmethode kann aber durchaus valide sein. Durch den Aufruf der geerbten Methoden aus der
Payment-Basisklasse kann diese Abhängigkeit einfach sichergestellt werden.
public function handleAdditional(): bool¶
Wird im Bestellprozess aufgerufen, um zu prüfen, ob der Zusatzschritt im Bestellprozess angezeigt werden soll.
Ist der Zwischenschritt aus Plugin-Sicht notwendig, muss false
zurückgegeben werden.
Dies kann z. B. genutzt werden, um zusätzliche, für die Zahlungsart relevante Daten wie Kreditkartendaten vom Kunden
abzufragen. Sind diese Daten z. B. bereits in der Kunden-Session vorhanden, kann der Schritt mit Rückgabe von true
übersprungen werden.
In der Payment-Basisklasse liefert diese Methode immer true
und muss deshalb nur überschrieben werden, wenn ein
eigener Zwischenschritt (siehe:
/**
* @inheritDoc
*/
public function handleAdditional($post): bool
{
$credentials = Frontend::get(self::USERCREDENTIALS, []);
if (empty($credentials['name']) || empty($credentials['token'])) {
Shop::Smarty()
->assign('credentials_loginName', empty($credentials['name'])
? Frontend::getCustomer()->cMail
: $credentials['name'])
->assign('credentials_secret', '')
->assign('additionalNeeded', true);
return false;
}
return parent::handleAdditional($post);
}
public function validateAdditional(): bool¶
Diese Methode wird im Bestellprozess aufgerufen und entscheidet im Zusammenspiel mit
handleAdditional, ob das Zusatzschritt-Template
(siehe: false
zurückgegeben,
ansonsten true
.
/**
* @inheritDoc
*/
public function validateAdditional(): bool
{
$credentials = Frontend::get(self::USERCREDENTIALS, []);
$postCredentials = Request::postVar('credentials', []);
if (Request::getInt('editZahlungsart') > 0 || Request::getInt('editVersandart') > 0) {
$this->resetToken();
return false;
}
if (isset($postCredentials['post'])) {
if (!Form::validateToken()) {
Shop::Container()->getAlertService()->addAlert(
Alert::TYPE_ERROR,
Shop::Lang()->get('invalidToken'),
'invalidToken'
);
return false;
}
$secret = StringHandler::filterXSS($postCredentials['secret']);
$credentials['name'] = StringHandler::filterXSS($postCredentials['loginName']);
$credentials['token'] = $this->validateCredentials($credentials['name'], $secret);
Frontend::set(self::USERCREDENTIALS, $credentials);
return !empty($credentials['token']);
}
if (!empty($credentials['token'])) {
return parent::validateAdditional();
}
return false;
}
public function addCache(): self¶
Mit addCache
wird ein Key-Value-Pair zwischengespeichert. Die Payment-Basisklasse benutzt für die Methoden
addCache, unsetCache
und getCache die aktuelle Kunden-Session als Zwischenspeicher.
Diese Methode muss überschrieben werden, wenn eine andere Cache-Methode verwendet werden soll.
public function unsetCache(): self¶
Mit unsetCache
wird ein Key-Value-Pair aus dem Zwischenspeicher entfernt. Die Payment-Basisklasse benutzt für die
Methoden addCache,
unsetCache und getCache
die aktuelle Kunden-Session als Zwischenspeicher.
Diese Methode muss überschrieben werden, wenn eine andere Cache-Methode verwendet werden soll.
public function getCache(): mixed¶
Mit getCache
wird ein Key-Value-Pair aus dem Zwischenspeicher gelesen. Die Payment-Basisklasse benutzt für die
Methoden addCache,
unsetCache und getCache
die aktuelle Kunden-Session als Zwischenspeicher.
Diese Methode muss überschrieben werden, wenn eine andere Cache-Methode verwendet werden soll.
public function createInvoice(): object¶
Die Methode createInvoice
wird beim Abgleich mit JTL-Wawi aufgerufen, wenn für eine Bestellung eine Rechnung erzeugt wird.
Über den Rückgabewert kann die Zahlungsart hier Informationen bereitstellen, die als zusätzlicher Text auf der Rechnung
ausgegeben werden. Diese Methode muss überschrieben werden, wenn Rechnungsdaten an die Wawi übergeben werden sollen.
Zurückgegeben werden muss ein Objekt mit den Eigenschaften nType
und cInfo
. nType
ist ein Integer mit den
möglichen Werten:
- 0 - Funktion nicht unterstützt
- 1 - Rechnungstext vorhanden
In cInfo
wird die zusätzliche Rechnungsinformation als String übergeben.
/**
* @inheritDoc
*/
public function createInvoice(int $orderID, int $languageID): object
{
$result = parent::createInvoice($orderID, $languageID);
$additionInfo = $this->getAdditionalOrderInfo($orderID);
if ($additionInfo !== null) {
$result->nType = 1;
$result->cInfo = $additionInfo;
}
return $result;
}
public function reactivateOrder(): self¶
Die Methode createInvoice
wird beim Abgleich mit JTL-Wawi aufgerufen, wenn eine Bestellung reaktiviert (Storno rückgängig) wird.
Die Zahlungsart hat hiermit die Möglichkeit, Änderungen an der Zahlung vorzunehmen oder eigene Status anzupassen.
Die Methode der Basis-Klasse versendet über sendMail die "Bestellung reaktiviert"-E-Mail
und setzt den Status der Bestellung wieder auf "In Bearbeitung".
Für weitergehnde Funktionen muss die Methode überschrieben werden. Das kann z.B. die Reaktivierung / Neuauslösung
der Zahlung beim Payment-Provider sein.
/**
* @inheritDoc
*/
public function reactivateOrder(int $orderID): self
{
parent::reactivateOrder($orderID);
SimplePaymentAPI::Call('RecoverPayment', $this->getOrderHash(new Bestellung($orderID)));
return $this;
}
public function cancelOrder(): self¶
Diese Methode wird vom JTL-Shop-Core bei der Synchronisation mit JTL-Wawi aufgerufen, wenn eine Bestellung storniert wurde. Die Payment-Basisklasse setzt den Status der zugeordneten Bestellung auf "storniert" und versendet über sendMail die "Bestellung storniert"-E-Mail. Diese Methode muss überschrieben werden, wenn weitergehende Operationen notwendig sind. Das kann z. B. die Stornierung der Zahlung beim Payment-Provider sein.
/**
* @inheritDoc
*/
public function cancelOrder(int $orderID, bool $delete = false): self
{
parent::cancelOrder($orderID, $delete);
SimplePaymentAPI::Call('CancelPayment', $this->getOrderHash(new Bestellung($orderID)));
return $this;
}
public function canPayAgain(): bool¶
Hier wird festgelegt, ob die Bezahlung über das Plugin erneut gestartet werden kann. Gibt diese Methode true
zurück, dann wird bei einer unbezahlten Bestellung im Kundenaccount ein "Jetzt bezahlen"-Link angezeigt. Wird dieser
Link angeklickt, dann wird der Bezahlvorgang neu gestartet. Die Init-Methode
für die Zahlungsmethode wird dann mit dem Parameter $nAgainCheckout = 1
aufgerufen.
Die Methode der Payment-Basisklasse liefert immer false
und muss überschrieben werden, wenn die Zahlungsmethode
einen erneuten Zahlungsvorgang unterstützt.
public function sendMail(): self¶
Die sendMail
-Methode der Payment-Basisklasse unterstützt die E-Mail-Templates für "Bestellbestätigung",
"Bestellung teilversandt", "Bestellung aktualisiert", "Bestellung versandt", "Bestellung bezahlt",
"Bestellung storniert" und "Bestellung reaktiviert" mit dem $type
-Parameter. Für die unterstützten Templates
werden die notwendigen Daten ermittelt und die jeweilige E-Mail versendet.
Diese Methode muss überschrieben werden, wenn weitere oder eigene E-Mail-Templates unterstützt werden sollen.
/**
* @inheritDoc
*/
public function sendMail(int $orderID, string $type, $additional = null): self
{
if (\str_starts_with($type, 'kPlugin_' . $this->plugin->getID())) {
$order = new Bestellung($orderID);
$order->fuelleBestellung(false);
$data = (object)[
'tkunde' => new Customer($order->kKunde),
'tbestellung' => $order,
];
$mailer = Shop::Container()->get(Mailer::class);
$mail = new Mail();
$mailer->send($mail->createFromTemplateID($type, $data));
return $this;
}
return parent::sendMail($orderID, $type, $additional);
}