Vendure Erweiterung
PunchCommerce unterstützt [Vendure](https://vendure.io) über ein offizielles Community-Plugin im **Gateway Mode**. Das Plugin wurde vom Vendure-Team entwickelt und gemeinsam mit PunchCommerce getestet.
---
## Überblick
| Eigenschaft | Wert |
|---|---|
| **Betriebsmodus** | Gateway Mode |
| **Protokolle** | OCI, cXML, IDS Connect |
| **Plugin** | [`@vendure-community/punchout-gateway-plugin`](https://www.npmjs.com/package/@vendure-community/punchout-gateway-plugin) |
| **Quellcode** | [github.com/vendurehq/community-plugins](https://github.com/vendurehq/community-plugins/tree/main/packages/punchout-gateway-plugin) |
| **Vendure-Dokumentation** | [docs.vendure.io – PunchOutGatewayPlugin](https://docs.vendure.io/current/community-plugins/punch-out-gateway-plugin) |
| **Demo-Storefront** | [github.com/vendurehq/punchcommerce-storefront-demo](https://github.com/vendurehq/punchcommerce-storefront-demo) |
| **Mindestversion Vendure** | 3.x |
---
## Funktionsweise
PunchCommerce fungiert als Protokoll-Gateway zwischen dem Beschaffungssystem des Einkäufers und dem Vendure-Shop. Der Ablauf:
1. Das Beschaffungssystem sendet einen PunchOut-Request (cXML, OCI oder IDS Connect) an PunchCommerce.
2. PunchCommerce verarbeitet den Request und leitet den Einkäufer an die konfigurierte Entry Address des Vendure-Storefronts weiter. Dabei werden die Parameter `sID` (Session-ID) und `uID` (Kunden-Kennung) als Query-Parameter übergeben.
3. Der Einkäufer authentifiziert sich über das Plugin, stöbert im Shop und füllt den Warenkorb.
4. Der Storefront übergibt den Warenkorb per `transferPunchOutCart`-Mutation an PunchCommerce.
5. PunchCommerce übersetzt den Warenkorb in das Zielformat des Beschaffungssystems.
---
## Unterstützte PunchCommerce-Funktionen
### Protokolle
Alle drei PunchCommerce-Protokolle werden unterstützt:
- **OCI** – für SAP-Umgebungen und ERP-Systeme im DACH-Raum
- **cXML** – für SAP Ariba, Coupa, Jaggaer und andere E-Procurement-Netzwerke
- **IDS Connect** – für den deutschen Großhandel (SHK, Elektro) und Handwerkersoftware
Die Protokollwahl erfolgt in der Kundenkonfiguration im PunchCommerce-Dashboard. Das Vendure-Plugin ist protokollunabhängig – die Übersetzung findet vollständig auf PunchCommerce-Seite statt.
### Field-Mapping
Das Field-Mapping im PunchCommerce-Dashboard funktioniert mit der Vendure-Integration wie gewohnt:
- Zuordnung von Shop-Attributen (EAN, SKU, Beschreibungen, Preise) zu PunchOut-Feldern per Drag & Drop
- Transformationen (`AppendTo`, `If`-Bedingungen)
- Fallback-Werte für leere Pflichtfelder
Zusätzlich unterstützt das Vendure-Plugin ein eigenes **Product-Field-Mapping** auf Plugin-Seite. Damit lassen sich PunchOut-spezifische Felder (Mengeneinheit, Verpackungseinheit, Gewicht) auf Vendure-Custom-Fields der `ProductVariant` mappen. Details dazu: [Vendure-Dokumentation – Product Field Mapping](https://docs.vendure.io/current/community-plugins/punch-out-gateway-plugin#product-field-mapping).
### PunchOut-Simulator
Der PunchOut-Simulator in PunchCommerce kann für die Vendure-Integration verwendet werden. Er simuliert eine vollständige Session (Weiterleitung → Authentifizierung → Warenkorb-Transfer) und eignet sich zur Validierung der Konfiguration, bevor die Anbindung mit dem Beschaffungssystem des Kunden getestet wird.
### Parallele Sessions
Das Plugin ordnet Warenkörbe über eine eigene `ActiveOrderStrategy` der jeweiligen PunchOut-Session (`sID`) zu. Mehrere gleichzeitige Sessions desselben Kunden sind möglich – jede mit einem eigenen, isolierten Warenkorb.
### Warenkorb-Mapping
Das Plugin übergibt die Warenkorbpositionen als `multipart/form-data` an den PunchCommerce-Endpunkt `/gateway/v3/return`. Dabei gelten folgende Konventionen:
- Preise: `price` = Bruttopreis, `price_net` = Nettopreis
- Alle Geldbeträge werden von Vendures Integer-Cent-Format in Dezimalwerte umgerechnet (÷ 100)
- Versandkosten werden als separate Position mit `type: 'shipping-costs'` übertragen (konfigurierbar über `shippingCostMode`)
- Produktbeschreibungen: `description` = Plaintext (HTML entfernt), `description_long` = mit HTML
### Order Lifecycle
Nach einem erfolgreichen Warenkorb-Transfer wechselt die Bestellung in Vendure in den Status **`Transferred`**. Die Bestellung wird inaktiv, der Warenkorb bleibt zur Nachverfolgung im Vendure-Admin erhalten.
---
## Derzeit nicht unterstützt
| Funktion | Status |
|---|---|
| **Actions** (`detail`, `search`, `background-search`) | Geplant für ein kommendes Release |
| **Order-Hub** | Nicht unterstützt |
| **Hosted Catalog** | Nicht anwendbar (Vendure stellt den Shop bereit) |
---
## Einrichtung
Die Einrichtung gliedert sich in zwei Bereiche: die Plugin-Installation in Vendure und die Kundenkonfiguration im PunchCommerce-Dashboard.
### Vendure-Seite
Die vollständige Anleitung zur Plugin-Installation, Konfiguration und Storefront-Anpassung finden Sie in der [Vendure-Dokumentation](https://docs.vendure.io/current/community-plugins/punch-out-gateway-plugin). Die wesentlichen Schritte:
**1. Plugin installieren**
```bash
npm install @vendure-community/punchout-gateway-plugin
```
**2. Plugin registrieren**
```typescript
import { PunchOutGatewayPlugin } from '@vendure-community/punchout-gateway-plugin';
export const config: VendureConfig = {
plugins: [
PunchOutGatewayPlugin.init({}),
],
};
```
**3. Kunden-Zuordnung herstellen**
Das Plugin fügt dem Vendure-`Customer`-Objekt ein Custom Field **„PunchOut Customer ID (uID)"** hinzu. Der Wert muss mit der „Customer Identification" im PunchCommerce-Dashboard übereinstimmen.
**4. Storefront anpassen**
Da Vendure headless arbeitet, erfordert der Storefront drei Anpassungen:
- **Landing Page** (`/punchout`): Liest `sID` und `uID` aus der URL, speichert die `sID` in `sessionStorage` und führt die Authentifizierung über die `authenticate`-Mutation mit der `punchout`-Strategie durch.
- **Session-gebundener Warenkorb**: Alle Order-Mutations und -Queries müssen `activeOrderInput: { punchout: { sID } }` übergeben.
- **Warenkorb-Transfer**: Ein Button ruft die Mutation `transferPunchOutCart(sID)` auf und ersetzt den normalen Checkout-Flow.
Eine funktionierende Referenz-Implementierung steht als [Demo-Storefront](https://github.com/vendurehq/punchcommerce-storefront-demo) zur Verfügung.
### PunchCommerce-Seite
**1. Kunden anlegen**
Erstellen Sie im PunchCommerce-Dashboard einen neuen Kunden. Die **„Customer Identification"** muss mit dem Wert im Vendure-Custom-Field `PunchOut Customer ID (uID)` übereinstimmen.
**2. Entry Address konfigurieren**
Tragen Sie die URL der PunchOut-Landing-Page Ihres Vendure-Storefronts ein, z. B.:
```
https://ihr-shop.de/punchout
```
PunchCommerce hängt die Parameter `?sID={UUID}&uID={Kennung}` automatisch an.
**3. Protokoll wählen**
Wählen Sie das Protokoll, das das Beschaffungssystem des Kunden erwartet:
- **cXML** – SAP Ariba, Coupa, Jaggaer
- **OCI** – SAP-Beschaffungssysteme
- **IDS Connect** – Handwerkersoftware, SHK- und Elektro-Großhandel
**4. Field-Mapping konfigurieren**
Ordnen Sie die relevanten Shop-Attribute den PunchOut-Feldern zu. Konfigurieren Sie Fallback-Werte für Pflichtfelder, die im Shop leer sein könnten.
**5. Konfiguration testen**
Nutzen Sie den PunchOut-Simulator, um eine vollständige Session zu simulieren und die korrekte Übertragung von Produktdaten, Preisen und Versandkosten zu prüfen.
---
## iFrame-Modus
Wenn das Beschaffungssystem den Vendure-Storefront in einem iFrame einbettet, sind auf Storefront-Seite zwei zusätzliche Anpassungen erforderlich:
- Session-Cookies auf `SameSite=None; Secure` setzen
- `X-Frame-Options`-Header während PunchOut-Sessions entfernen
Details: [Vendure-Dokumentation – iFrame Support](https://docs.vendure.io/current/community-plugins/punch-out-gateway-plugin#4-iframe-support-if-applicable).
---
## Plugin-Konfigurationsoptionen
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
| `apiUrl` | `string` | `https://www.punchcommerce.de` | Basis-URL der PunchCommerce-Instanz. Nur bei Staging- oder Self-Hosted-Setups ändern. |
| `shippingCostMode` | `'all' \| 'nonZero' \| 'none'` | `'nonZero'` | Steuert, wann Versandkosten als Position übertragen werden: immer, nur bei Betrag > 0, oder nie. |
| `productFieldMapping` | `ProductFieldMappings` | – | Mapping von PunchOut-Produktfeldern auf statische Werte oder Vendure-Custom-Fields. |
Vollständige Referenz: [PunchOutGatewayPluginOptions](https://docs.vendure.io/current/community-plugins/punch-out-gateway-plugin/punch-out-gateway-plugin-options).
---
## Fehlersuche
| Problem | Mögliche Ursache |
|---|---|
| Authentifizierung schlägt fehl (`InvalidCredentialsError`) | `uID` im Vendure-Custom-Field stimmt nicht mit der Customer Identification in PunchCommerce überein. |
| Warenkorb ist leer nach Artikelzugabe | `activeOrderInput` wird nicht an die Order-Mutation übergeben – Artikel landen im regulären Warenkorb statt in der PunchOut-Session. |
| Transfer gibt Fehler zurück | Bestellung wurde bereits transferiert (Status `Transferred`). Pro Session ist nur ein Transfer möglich. |
| Shop wird im iFrame nicht geladen | Session-Cookies sind nicht auf `SameSite=None; Secure` gesetzt oder `X-Frame-Options`-Header blockiert das Embedding. |
| Parallele Sessions überschreiben sich | `sID` wird in einem Cookie statt in `sessionStorage` gespeichert. Cookies sind domainweit, `sessionStorage` ist tab-spezifisch. |