Shopware Knowledgebase

Shopware Labs

Der Bereich Shopware Labs ist die Plattform für alle Entwickler. Hier findet man technische Dokumentationen und zahlreiche Tipps und Tricks rund um das Thema Programmieren. In dieser Rubrik stellen außerdem die Entwickler der shopware AG neue und experimentelle Lösungsansätze vor. Neue Funktionen, die in dieser Rubrik bereitgestellt werden, sind teilweise auch für zukünftige Releases geplant. Die Funktionen können dann ohne Programmierkenntnisse zukünftig direkt im Shopware Backend konfiguriert werden oder werden über Plugins bereitgestellt. Informationen über neue, geplante Funktionen finden Sie in unserer Roadmap.

Bitte beachten Sie, dass die hier bereitgestellten Lösungsansätze nicht offiziell supportet werden und nur eingebaut werden sollten, sofern Sie über das entsprechende, technische Wissen verfügen.

Zahlungsplugins entwickeln

0 Kommentare
ab Version:3.5.4

Beschreibung

In diesem Tutorial beschreiben wir Ihnen, wie Sie eine neue externe Zahlungsart in der Form eines Shopware-Plugins anlegen können. Mit der neuen Shopware-Version 3.5.4 werden Ihnen hierzu einige neue Funktionen bereitgestellt, die Sie dazu verwenden können. Bevor Sie mit diesem Tutorial beginnen, sollten Sie sich zuerst mit der Materie der Shopware-Plugins vertraut machen. Dazu gibt es u.a. ein eigenes Tutorial.

Payment-Plugin anlegen

Zuerst sollten Sie eine neue Plugin-Struktur anlegen. Der Name des Plugins sollte die Form "VendorPaymentProvider" (z.B. "SwagPaymentPayPal") haben. Danach können Sie mit dem Erstellen eines Payment-Plugin beginnen. Nehmen Sie dazu die folgenden beiden Änderungen an der Plugin-Bootstrap vor.

Wichtig: Voraussetzung für das neue Payment-Plugin ist das im Standard enthaltene Plugin "Payment" dieses muss aktiv und installiert sein.

Neuen Zahlungsart-Eintrag erstellen

Die folgende Änderung dient dazu, automatisch einen neuen Zahlungsart-Eintrag bei der Plugin-Installation zu erstellen:

 
/**
 * Install plugin method
 *
 * @return bool
 */
public function install()
{
	...
 
	$this->createPayments();
 
	return true;
}
 
/**
 * Create and save payments
 */
protected function createPayments()
{
	$paymentRow = Shopware()->Payments()->createRow(array(
		'name' => 'paypal',
		'description' => 'PayPal',
		'action' => 'payment_paypal',
		'active' => 1,
		'pluginID' => $this->getId()
	))->save();
	...
}
 

  • name

Als "name" sollten Sie ein eindeutiges Kürzel für die Zahlungsart hinterlegen. Dieses wird u.a. in den Bestell-Exporten zur Zuordnung der Zahlungsarten benötigt. Sie können übrigens auch mehrere Zahlungsarten für ein Payment-Plugin anlegen. Durch diesen Namen können Sie dann die verschiedenen Zahlungsarten im Payment-Controller unterscheiden.

  • description

In das Feld "description" müssen Sie den Namen eingeben, der später im Frontend/Backend für die Zahlungsart ausgegeben werden soll.

  • action

In dem Feld "action" sollten Sie den späteren Namen für die Payment-Action hinterlegen. Dieser sollte sich am Plugin-Namen orientieren. Der Vendor-Name kann hier ausgelassen werden.

Neuen Controller-Eintrag erstellen

Wie Sie einen neuen Controller anlegen, haben Sie bereits im Plugin-Tutorial gelernt. Beachten Sie aber hier, dass Sie den Controller-Namen verwenden sollten, den Sie schon in der "createPayments"-Methode als "action" hinterlegt haben. Trotzdem gibt es im Folgenden noch einmal vollständigerweise die dazu nötigen Änderungen an der Plugin-Bootstrap-Datei:

 
/**
 * Install plugin method
 *
 * @return bool
 */
public function install()
{
	...
 
	$this->createPayments();
	$this->createEvents();
 
	return true;
}
 
/**
 * Create and subscribe events
 */
protected function createEvents()
{
	...
 
	$event = $this->createEvent(
		'Enlight_Controller_Dispatcher_ControllerPath_Frontend_PaymentPaypal',
		'onGetControllerPathFrontend'
	);
	$this->subscribeEvent($event);
}
 
/**
 * Event listener method
 *
 * @param Enlight_Event_EventArgs $args
 */
public static function onGetControllerPathFrontend(Enlight_Event_EventArgs $args)
{
	Shopware()->Template()->addTemplateDir(dirname(__FILE__).'/Views/');
	return dirname(__FILE__).'/PaymentPaypal.php';
}
 

Payment-Controller anlegen

Ein Payment-Controller kann wie ein normaler Frontend-Controller angelegt werden. Der Controller sollte aber von der Payment-Controller-Klasse "Shopware_Controllers_Frontend_Payment" abgeleitet werden, damit die Payment-Methoden im Controller zur Verfügung stehen.

 
/**
 * Paypal payment controller
 * 
 * @link http://www.shopware.de
 * @copyright Copyright (c) <Jahr>, <Ihre Firma>
 * @author <Ihr Name>
 * @package Shopware
 * @subpackage Controllers
 */
class Shopware_Controllers_Frontend_PaymentPayPal extends Shopware_Controllers_Frontend_Payment
{	
	...
}
 

Auf die richtige Action umleiten

Wenn Sie nun das Plugin mit der vorläufig erstellten Bootstrap installiert haben, wird bei der entsprechenden Auswahl der Zahlungsart beim Bestellabschluss automatisch auf den jeweiligen in der Zahlungsart hinterlegten Controller umgeleitet. Sämtliche Anfragen gehen dann zunächst auf der Index-Action ein. Wenn Sie mehr als eine Zahlungsart mit Ihrem Payment-Plugin anbieten, müssen Sie in der Index-Action eine Umleitung einbauen. Das erreichen Sie mithilfe der Payment-Methode "getPaymentShortName". Diese Methode gibt die aktuell ausgewählte Zahlungsart oder, wenn aktuell keine Zahlung auszuführen ist, "null" zurück. Der entsprechende Code dazu könnte daher folgendermaßen aussehen:

 
/**
 * Index action method
 */
public function indexAction()
{
	switch ($this->getPaymentShortName()) {
		case 'paypal':
			return $this->redirect(array('action' => 'direct', 'forceSecure' => true));
		case 'paypal_gateway':
			return $this->redirect(array('action' => 'gateway', 'forceSecure' => true));
		default:
			return return $this->redirect(array('controller' => 'checkout'));
	}
}
 

Payment-Actions anlegen

Da nun die richtigen Actions aufgerufen werden, können wir diese nun auch umsetzen. Es gibt mindestens zwei verschiedene Arten, auf die man externe Zahlungsarten in den Shop einbinden kann. Auf andere Arten von Einbindung sollten Sie verzichten, da diese meist die Konsequenz haben, dass die Zahlungsdaten mit dem Shop in Berührung kommen. Das ist aber bei vielen Zahlungsdaten (z.B. Kreditkarten-Daten) untersagt oder, wie etwa bei ELV-Daten, zumindest unerwünscht.

Per Gateway in einen iFrame

Diese Funktion ist z.B. bei Kredikarten- oder ELV-Zahlungen gewünscht, bei denen der Kunde nicht den Shop verlassen müssen soll. Um dies zu erreichen, muss man aber zuvor selbst ein ansprechendes Template mit einem iFrame kreieren. Dabei kann man sich z.B. am Template "frontend/checkout/payment.tpl" orientieren. Nach dem Ende des Zahlungsvorgangs sollte der Kunde zum Abschluss der Bestellung wieder auf den Payment-Controller umgeleitet werden:

 
/**
 * Gateway action method
 */
public function gatewayAction()
{
	$returnUrl = $this->Front()->Router()->assemble(array(
		'action' => 'end'
	));
 
	$this->View()->gatewayUrl = 'http://www.payment.com/gateway' . $params;
	$this->View()->returnUrl = $returnUrl;
	...
}
 

Per dirketer Umleitung auf eine externe Seite

Bei einigen anderen Zahlungsarten muss der Kunde zur Zahlung direkt auf eine externe Seite umgeleitet werden. Auch hierbei sollte der Kunde nach der Zahlung wieder zum Payment-Controller zurückkehren:

 
/**
 * Direct action method
 */
public function directAction()
{
	$returnUrl = $this->Front()->Router()->assemble(array(
		'action' => 'end'
	));
 
	$gatewayUrl = 'http://www.payment.com/gateway';
	$gatewayUrl .= '?return_url='.urlencode($returnUrl);
 
	$this->redirect($gatewayUrl);
}
 

Zahlung durchführen

Die für die Zahlung benötigten Daten können über die Payment-Methoden abgefragt werden. Bei der Übertragung der Daten sollten Sie sicherstellen, dass diese vom Kunden nicht manipuliert wurden. Das kann z.B. durch eine Hash-Überprüfung geschehen. Überdies kann man verhindern, dass der Kunde überhaupt erst mit den Daten in Berührung kommt. Bitte lesen Sie dazu die entsprechende Anweisung aus der Anleitung der einzubindenden Schnittstelle.

 
/**
 * Direct action method
 */
public function directAction()
{
	$returnUrl = $this->Front()->Router()->assemble(array(
		'action' => 'end'
	));
 
	$secret = Shopware()->Config()->myPaymentSecret;
 
	$gatewayUrl = 'http://www.payment.com/gateway';
	$gatewayUrl .= '?return_url='.urlencode($returnUrl);
	$gatewayUrl .= '&amount='.urlencode($this->getAmount());
	$gatewayUrl .= '&currency='.urlencode($this->getCurrencyShortName());
	$gatewayUrl .= '?hash='.md5($secret.'|'.$this->getAmount().'|'.$this->getCurrencyShortName());
 
	$this->redirect($gatewayUrl);
}
 

Bestellung abschließen

Die Bestellung kann über die Payment-Methode "saveOrder" abgeschlossen werden. Wann die Bestellung abgeschlossen wird, ist dem Schnittstellen-Autor selbst überlassen. Es wird aber empfohlen, die Bestellung nur abzuschließen, wenn eine Zahlung erfolgt ist. Da einige Shopbetreiber die Ware direkt beim Bestellabschluss verschicken, sollte auch der Abschluss vor Manipulationen geschützt werden. Es sollte also verhindert werden, dass Bestellungen ohne eine durchgeführte Zahlung abgeschlossen werden können. Wenn es sich nicht verhindern lässt, sollte dies unbedingt in der Plugin-Beschreibung vermerkt werden:

 
/**
 * End action method
 */
public function endAction()
{
	$secret = Shopware()->Config()->myPaymentSecret;
	$transactionId = $this->Request()->getParam('transactionId');
	$status = $this->Request()->getParam('status');
	$hash = $this->Request()->getParam('hash');
 
	if(empty($transactionId) || $status != 'success'
	  || $hash != md5($secret.'|'.$transactionId.'|success')) {
		return $this->forward('error');
	}
 
	$this->saveOrder($transactionId, $hash);
 
	return $this->forward('finish', 'checkout', null, array('sUniqueID' => $hash));
}
 

Zahlungsstatus speichern

Zum Speichern des Zahlungsstatus gibt es im Payment-Controller die Payment-Methode "savePaymentStatus". Neben der Transaction/Unique-ID zum Zuordnen der Zahlung, kann man bei deser Methode eine ZahlungsstatusID und eine Flag zum Senden von Status-eMails übergeben. Damit eine Status-eMail verschickt wird, muss für den entsprechenden Status auch ein eMail-Template angelegt sein. Auch das Ändern des Zahlungsstatus sollte vor einer Manipulation geschützt werden. Das kann, wie beim Bestellabschluss, über ein Secret geschehen, oder, da wahrscheinlich der Aufruf durch den Zahlungsanbieter erfolgt, über eine IP-Überpürfung verhindert werden.

 
/**
 * Notify action method
 */
public function notifyAction()
{
	if(!in_array($this->Request()->getClientIp(false), array('127.0.0.1', '127.0.0.2'))) {
		return;
	}
 
	$secret = Shopware()->Config()->myPaymentSecret;
	$transactionId = $this->Request()->getParam('transactionId');
	$status = $this->Request()->getParam('status');
	$hash = $this->Request()->getParam('hash');
	$uniqueId = md5($secret.'|'.$transactionId.'|success');
 
	if(empty($transactionId)
	  || $hash != md5($secret.'|'.$transactionId.'|'.$status)) {
		return $this->forward('error');
	}
 
	switch ($status) {
		case 1:
			$paymentStatus = 18;
			break;
		case 2:
			$paymentStatus = 12;
			break;
		default:
			break;
	}
 
	if(!empty($paymentStatus)) {
		$this->savePaymentStatus(
			$transactionId,
			$uniqueId,
			$paymentStatus,
			Shopware()->Config()->myPaymentStatusMail
		);
	}
}
 

Payment-Variablen

Unique-ID

Die Unique-ID wird zum internen Zuordnen einer Zahlung verwendet. Für den Shop-Kunden sollte diese ID bis zum Bestellabschluss unsichtbar sein. Bei einer verdeckten Übermittlung der Zahlungsdaten kann diese ID mit der Methode "createPaymentUniqueId" erstellt werden. Bei einer offenen Übermittlung kann man die ID z.B. aus dem Hash eines "Secret"-Keys und der "Transaction-ID" erstellen.

Transaction-ID

Die Transaction-ID wird von der Schnittstelle des Zahlungsanbieters erstellt. Diese dient zum externen Zuordnen der Zahlungen. Man kann nicht davon ausgehen, dass diese geheim ist. Die ID sollte daher nicht von Ihnen als z.B. "Secret" verwendet werden.

Secret(-Key)

Ein Secret wird in Verbindung mit einer Hash-Überprüfung zum Absichern einer offenen Schnittstelle verwendet, bei der die Zahlungsdaten über den Kunden an den Zahlungsanbieter gehen. Wie das Secret erstellt wird und wie es verwendet werden muss, wird meist vom Zahlungsanbieter vorgeschrieben. Wenn man dazu eigene Methoden schreibt, sollte man sicherstellen, dass der Kunde keine Möglichkeit hat, diese zu fälschen.

Auflistung der Payment-Methoden

getPaymentShortName

Gibt den Kürzel, der beim Anlegen der Zahlungsart hinterlegt wurde, der aktuell ausgewählten Zahlungsart zurück. Wenn z.Z. keine Bestellung abzuschließen ist, gibt die Methode "null" zurück.

getCurrencyShortName

Gibt die dreistellige Währungs-Abkürzung (z.B. EUR) für die aktuell ausgewählte Währung zurück.

getAmount

Gibt den zu zahlenden Betrag als Float-Wert für die aktuelle Bestellung zurück.

getUser

Gibt das passende User-Objekt für die aktuelle Bestellung zurück.

getBasket

Gibt das aktuelle Warenkorb-Objekt für die aktuelle Bestellung zurück.

createPaymentUniqueId

Erzeugt einen zufälligen Wert für eine Unique-ID und gibt diesen zurück.

saveOrder

saveOrder( string $transactionId, string $paymentUniqueId [, int $paymentStatusId = null [, bool $sendStatusMail = false ] ] )

Schließt die aktuelle Bestellung ab und speichert die dazu passende Transaction-ID / Unique-ID in der Bestellung.

savePaymentStatus

savePaymentStatus( string $transactionId, string $paymentUniqueId [, int $paymentStatusId = null [, bool $sendStatusMail = false ] ] )

Ändert den Zahlstatus auf den Zahlstatus der übergeben wurde. Die Bestellung wird anhand der Transaction-ID und der Unique-ID ausgelesen. An den 4. Parameter kann ein Flag zum Versenden einer Status-Mail übergeben werden.

Artikel-PDF erstellen

Artikel bewerten

Waren diese Informationen hilfreich? Ja Nein


Kommentare:

Artikel kommentieren


Die mit einem * markierten Felder sind Pflichtfelder.

Weitere interessante Artikel:

Bezeichnung:
Rating:
Klicks:
Datum:

Bestell-Nr.: SW1568

Lieferzeit ca. 5 Tage

€ 1,00

Preise inkl. gesetzlicher
MwSt. zzgl. Versandkosten*

€ 1,00

Preise inkl. gesetzlicher
MwSt. + Versandkosten*

Kategorien: