pimcore Paypal Integration mit direkter Zahlungsbestätigung (IPN)

Lukas [php, Business, Pimcore]

Wenn man Produkte auf seiner Webseite verkaufen will, gibt es viele Möglichkeiten Zahlungen zu bestätigen. Wir starten die Serie mit einer Paypal Integration. Paypal bietet den Dienst der direkten Zahlungbestätigung. Damit ruft Paypal direkt nach der Zahlung eine dem Kunden unbekannte URL auf, mit der die Zahlung verifiziert wird. Somit ist der Kauf bestätigt, wenn der Kunde zurück auf die Webseite kommt.

Das pimcore Plugin

Den zuständigen Controller verpacken wir in einem eigenen Plugin und nennen dieses nambushop. Der Controller heisst treffend Paypal und besitzt zwei actions. Eine die das Formular mit der Weiterleitung zu Paypal erstellt und das zweite für die direkte Zahlungsbestätigung.

Das Paypal Formular Action

Bei der Aufbereitung der Daten gilt es einige Dinge zu beachten:

  • Die paypal_url ist Entweder das Produktsystem oder die Testumgebung. Die URLs dafür lauten wie folgt:
    Testsystem: https://www.sandbox.paypal.com/cgi-bin/webscr
    Produktivsystem: https://www.paypal.com/cgi-bin/webscr
  • return ist die URL, auf die der Kunde nach der Zahlung gelant. Dort wird die Bestellung geladen und sofern die Zahlung geklappt hat dies dem Kunden bestätigt.
  • Der currency_code entspricht der Zielwährung.
  • business ist die E-Mailadresse des Paypal Verkäuferaccounts.
  • item_number ist die ID der Bestellung. Diese wird ebenfalls bei der Verifikation übergeben.
  • item_name ist der Name dees Artikels.
  • quantity wie oft der Artikel gekauft wird.
  • amount entspricht der Gesamtsumme.
class nambushop_PaypalController extends Website_Controller_Action {
     public function formAction() {
        $order = Object_ShopOrder::getById($this->getParam("order_id"));
        $this->view->paypal_url = $this->config->paypal_url;
        $this->view->return = Pimcore_Tool::getHostUrl().$this->config->order_confirmation->getFullPath();
        $this->view->currency_code = $order->getCurrency();
        $this->view->business = $this->config->paypal_seller;
        $this->view->item_name = $order->getName();
        $this->view->item_number = $order->getKey();
        $this->view->quantity = $order->getQuantity();
        $this->view->amount = $order->getAmount();
    }
}

Selbstverständlich müssten die Variabeln item_name, item_number, quanitity und amount je nach Umgebung entsprechend befüllt werden.

Die Paypal Formular View

<form action="<?= $this->paypal_url ?>" method="post">
 
    <input name="cmd" value="_xclick" type="hidden">
    <input name="charset" value="utf-8" type="hidden">
    <input name="return" value="<?= $this->return ?>" type="hidden">
    <input name="currency_code" value="<?= $this->currency_code ?>" type="hidden">
    <input name="business" value="<?= $this->business ?>" type="hidden">
    <input name="item_name" value="<?= $this->item_name ?>" type="hidden">
    <input name="item_number" value="<?= $this->item_number ?>" type="hidden">
    <input name="quantity" value="<?= $this->quantity ?>" type="hidden">
    <input name="amount" value="<?= $this->amount ?>" type="hidden">
 
    <button type="submit" name="submit_paypal" class="btn btn-primary"><i class="glyphicon glyphicon-credit-card"></i> Pay via Paypal</button>
 
</form>

Das Formular wird wie folgt an der gewünschten Stelle auf die eigene Webseite integriert:

echo $this->action("form", "paypal", "nambushop");

Paypal Konfiguration

Auf Paypal muss die URL für die direkt Zahlungsbestätigung IPN eingetragen werden. Dies geschieht nach dem Login unter "Mein Profil" -> "Einstellungen für sofortige Zahlungsbestätigung". Die URL die eingetragen wird lautet:

http://www.nambu.ch/?controller=paypal&action=ipnconfirm&module=nambushop

Empfangen der direkten Zahlungsbestätigung IPN

Paypal sendet mit der Zahlungsbestätigung einige Parameter mit, anhand deren man die korrekte Bestellung findet und diese Bestätigen kann.

class nambushop_PaypalController extends Website_Controller_Action {
 
    /**
     *
     * IPN URL for paypal confirmation:
     * DOMAIN?controller=paypal&action=ipnconfirm&module=nambushop
     *
     */
    public function ipnconfirmAction() {
        //get order
        $order = Object_Abstract::getByPath("/orders/".$this->getParam("item_number"));
        if (!$order instanceof Object_ShopOrder) {
            echo "Invalid item_number";
 
            $paypalPayment = new Object_ShopPaymentPaypal();
            $paypalPayment->setPublished(true);
            $paypalPayment->setParent(Object_Folder::getByPath("/orders"));
            $paypalPayment->setIpnMessage(join("n", $this->getAllParams()));
            $paypalPayment->save();
 
            header('HTTP/1.1 500 Invalid item_number');
            die();
        }
 
        $paypalPayment = new Object_ShopPaymentPaypal();
        $paypalPayment->setKey("paypal_".date("Ymd-His"));
        $paypalPayment->setPublished(true);
        $paypalPayment->setParent($order);
 
        $seller = $this->getParam("receiver_email");
        $payment_status = $this->getParam("payment_status");
        $amount = $this->getParam("mc_gross");
 
        $paypalPayment->setState($payment_status);
 
        $data = array();
        foreach ($this->getRequest()->getPost() as $key => $value) {
            $data[] = "$key=$value";
        }
        $paypalPayment->setIpnMessage(join("n", $data));
        $paypalPayment->setTxn_id($this->getParam("txn_id"));
 
        if ($seller == $this->config->paypal_seller
            && $amount == $order->getTotal()
            && $payment_status == "Completed"
        ) {
            // Build the required acknowledgement message out of the notification just received
            $req = 'cmd=_notify-validate'; // Add 'cmd=_notify-validate' to beginning of the acknowledgement
 
            foreach ($this->getRequest()->getPost() as $key => $value) { // Loop through the notification NV pairs
                $value = urlencode(stripslashes($value)); // Encode these values
                $req .= "&$key=$value"; // Add the NV pairs to the acknowledgement
            }
 
            $url = $this->config->paypal_url."?".$req;
            $paypalPayment->setVerificationUrl($url);
            $paypal_verification = @file_get_contents($url);
 
            if ($paypal_verification == "VERIFIED") {
                $order->setState("payed");
            }
        }
 
        $paypalPayment->save();
 
        $order->save();
        header('HTTP/1.1 200 OK');
        die();
    }
}

Hier geschieht einiges. Als erstes prüfen wir ob wir die Bestellung mit der item_number vom Formular von vorhin finden. Falls dem so ist Vergleichen wir den Totalbetrag der Bestellung, den Verkäuferaccount sowie den Status der Zahlung. Ist das alles in Ordnung wird nocheinmal bei Paypal gegengeprüft ob die Zahlung wirklich gerade bestätigt wurde. Schliesslich könnte jemand mit etwas wissen die IPN Url auch selbst aufrufen.

zurück