Zum Inhalt springen
 Magento 2 · 25–35 Min · fortgeschritten

Perfect Day in Magento 2 anbinden.

Magento hat keine eingebaute Webhook-Funktion — du brauchst ein kleines Custom-Modul, das auf das Order-Event lauscht. Diese Anleitung richtet sich an Anbieter mit eigenem Magento-Entwickler oder einer Agentur. Ohne Dev-Hand empfehlen wir unseren Setup-Service.

Vorab nötig: Geh einmal die allgemeine Vorbereitung durch — Coupon anlegen, Anwendungspasswort holen, Webhook-URL bereitlegen. Dauert rund fünf Minuten und gilt für alle Shop-Systeme.

Drei Wege im Überblick

  1. Welcher Weg passt zu dir?

    • Custom-Modul selbst schreiben — rund 2–3 Stunden Magento-Dev. In dieser Anleitung beschrieben.
    • Webhook-Extension aus dem Magento Marketplace nutzen + JSON-Mapping konfigurieren.
    • Hosted-Bridge über Make.com / Zapier — kein eigener Code.

Weg 1 — Custom-Modul (für Magento-Entwickler)

  1. Attribut „pfd_coupon_id" pro Produkt anlegen

    Magento-Admin → Stores → Attribute → Product„Add New Attribute". Attribute Code pfd_coupon_id, Input Type „Text Field", Required „No". Dann unter Stores → Attribute Set das Attribut der passenden Gruppe zuweisen. Pro Coupon-Produkt die ID im Produkt-Editor eintragen.

  2. Modul-Struktur anlegen

    Das Custom-Modul besteht aus wenigen Dateien:

    Verzeichnisstruktur
    app/code/DigElite/PerfectDayConnector/
    ├── etc/
    │   ├── module.xml
    │   └── events.xml
    ├── Observer/
    │   └── OrderPaidObserver.php
    └── registration.php
  3. registration.php + module.xml

    Die Registrierungs- und Modul-Definitionsdateien sind Magento-Standard. registration.php registriert das Modul, etc/module.xml deklariert es mit setup_version 1.0.0.

  4. events.xml — auf das Order-Paid-Event lauschen

    Verknüpft den Observer mit dem Magento-Event sales_order_payment_pay:

    Vollständigen Code anzeigen — XML · etc/events.xml
    XML · etc/events.xml
    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
        <event name="sales_order_payment_pay">
            <observer name="pfd_order_paid"
                      instance="DigElite\PerfectDayConnector\Observer\OrderPaidObserver"/>
        </event>
    </config>
  5. OrderPaidObserver.php — der eigentliche Versand

    Der Observer sammelt die Coupon-IDs aus den Bestellpositionen, baut den Payload und schickt ihn an den Perfect-Day-Webhook. Trag deinen Username und das Anwendungspasswort in die Konstanten ein.

    Vollständigen Code anzeigen — PHP · Observer/OrderPaidObserver.php
    PHP · Observer/OrderPaidObserver.php
    <?php
    namespace DigElite\PerfectDayConnector\Observer;
    
    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\Event\Observer;
    use Magento\Framework\HTTP\Client\Curl;
    
    class OrderPaidObserver implements ObserverInterface
    {
        private const PFD_USER = 'DEIN-USER';
        private const PFD_PWD  = 'xxxx xxxx xxxx xxxx xxxx xxxx';
        private const PFD_URL  = 'https://plattform.deinperfectday.de/wp-json/perfectday/shop/webhook/order';
    
        public function __construct(private Curl $curl) {}
    
        public function execute(Observer $observer): void
        {
            $order = $observer->getEvent()->getPayment()->getOrder();
            if (!$order) return;
    
            $items = [];
            foreach ($order->getAllItems() as $it) {
                $couponId = (int) $it->getProduct()->getData('pfd_coupon_id');
                if ($couponId <= 0) continue;
                $items[] = ['coupon_id' => $couponId, 'count' => (int)$it->getQtyOrdered()];
            }
            if (empty($items)) return;
    
            $payload = [
                'shop_order_id' => (string) $order->getIncrementId(),
                'shop_type'     => 'magento',
                'shop_domain'   => parse_url($order->getStore()->getBaseUrl(), PHP_URL_HOST),
                'customer' => [
                    'email'  => $order->getCustomerEmail(),
                    'name'   => trim($order->getCustomerFirstname() . ' ' . $order->getCustomerLastname()),
                    'locale' => substr($order->getStore()->getLocaleCode() ?: 'de', 0, 2),
                ],
                'items'             => $items,
                'order_total_cents' => (int) round((float) $order->getGrandTotal() * 100),
                'currency'          => $order->getOrderCurrencyCode(),
                'placed_at'         => $order->getCreatedAt(),
            ];
    
            $this->curl->setHeaders([
                'Content-Type'  => 'application/json',
                'Authorization' => 'Basic ' . base64_encode(self::PFD_USER . ':' . self::PFD_PWD),
            ]);
            $this->curl->post(self::PFD_URL, json_encode($payload));
        }
    }
  6. Modul aktivieren

    Per CLI auf dem Server:

    Bash
    bin/magento module:enable DigElite_PerfectDayConnector
    bin/magento setup:upgrade
    bin/magento cache:flush

Weg 2 — Marketplace-Extension + Mapping

  1. Webhook-Extension konfigurieren

    Mit einer kommerziellen Webhook-Extension: Trigger auf Order Status Change → Paid setzen, URL https://plattform.deinperfectday.de/wp-json/perfectday/shop/webhook/order, Header Authorization: Basic <base64(user:pwd)>. Im Body-Mapping das JSON-Format nachbauen, im Item-Mapping das Custom-Attribut pfd_coupon_id auf items[*].coupon_id verknüpfen. Die meisten Webhook-Extensions können das ohne weiteren Code.

Test-Bestellung

  1. Bestellung auslösen und prüfen

    Test-Bestellung tätigen, bezahlen, dann im Plattform-Backoffice unter Perfect Day → Shop-Bestellungen den Eintrag mit shop_type=magento prüfen. Kunden-Mailbox auf die Brand-Mail kontrollieren.

Wenn etwas klemmt

Troubleshooting.

Der Observer feuert nicht

Cache nach setup:upgrade nicht geleert? bin/magento cache:flush ausführen.

Custom-Attribut bleibt leer

Das Attribut pfd_coupon_id ist keinem Attribute-Set zugewiesen. Unter Stores → Attribute Set nachholen.

HTTP-Calls hängen / blockieren den Checkout

Der Magento-Cron blockiert. Verschiebe den HTTP-Call in eine Queue mit Magento\Framework\MessageQueue\PublisherInterface, statt ihn synchron im Observer auszuführen.

HTTP 401 / 403 / 400

Gleiche Fehler-Codes wie bei den anderen Shops: 401 = Auth falsch, 403 = Coupon-ID gehört nicht zu deinem Account, 400 = ungültiger JSON-Body (oft fehlende Kunden-E-Mail).

Setup-Service

Lieber von uns einrichten lassen?

Magento ist der aufwändigste der unterstützten Shops. Wenn du keinen Dev-Zugang hast, übernehmen wir die Custom-Modul-Entwicklung — oder wir hosten eine Bridge, bei der du nur den Magento-API-Zugang bereitstellst.

Häufige Fragen

Noch Fragen?

Brauche ich zwingend einen Entwickler?
Für Weg 1 (Custom-Modul) ja — es ist echte Magento-Entwicklung. Weg 3 (Hosted-Bridge über Make.com/Zapier) geht ohne eigenen Code. Oder du nutzt unseren Setup-Service.
Warum nicht einfach ein fertiges Plugin?
Magento-Erweiterungen müssen sehr eng auf die jeweilige Magento-Version und das Theme abgestimmt sein. Ein generisches Plugin wäre fehleranfälliger als ein schlankes Custom-Modul oder eine Bridge. Bei genug Nachfrage prüfen wir ein offizielles Modul.

Shop verbunden — und jetzt?

Sobald der Webhook läuft, erscheinen alle Bestellungen automatisch in deinem Backoffice. Brauchst du eine weitere Anbindung, geht jeder weitere Shop in wenigen Minuten.

Zur Shop-Übersicht