everysize / checkout-oscommerce
everysize Checkout – Erweiterung für osCommerce 4
Package info
github.com/everysize/checkout-oscommerce
Type:oscommerce-extension
pkg:composer/everysize/checkout-oscommerce
Requires
- php: >=8.1
- ext-curl: *
- ext-json: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Bindet einen osCommerce-4-Shop an den everysize-Direktkauf an: Bestellungen aus everysize werden importiert (inkl. Gastkonten, Varianten, Bestandsabzug und optionaler Bestellbestätigung), und Bestellnummer, Versand, Sendungsnummern, Storno, Retoure und Auto-Erstattungen werden zurückgemeldet.
Den Quellcode gibt es auch als Composer-Paket everysize/checkout-oscommerce.
Installiert wird das Modul aber nicht per Composer, sondern über das ZIP
(siehe Installation): osCommerce lädt Erweiterungen nur aus
lib/common/extensions/.
Voraussetzungen
- osCommerce 4.14 (getestet mit 4.14.63493)
- PHP ≥ 8.1 mit
curlundjson - Ein Cron, der den Abgleich alle paar Minuten aufruft (siehe unten)
Kein PayPal-Modul nötig: bezahlt wird bei everysize. Erstattet wird über everysize (das Geld geht über das PayPal-Konto zurück, mit dem bezahlt wurde).
Installation
- ZIP (
everysize-checkout-oscommerce-<version>.zip, Download in everysize Business unter „Shop-Integration“ → osCommerce) entpacken und den enthaltenen Ordnerlibin das Shop-Root kopieren (per FTP/SFTP), so dasslib/common/extensions/EverysizeCheckout/distribution.jsonliegt. - Module → Extensions: „everysize Checkout“ → Installieren. Das legt die
Modul-Tabellen an (
everysize_checkout_*, idempotent), registriert Menü, Hooks und den Cron-Endpoint und hält beim Deinstallieren standardmäßig alle Daten (wie die anderen everysize-Plugins). - Werkzeuge → everysize Checkout → Einstellungen: Client-ID und Client-Secret (aus everysize Business, „Shop-Integration“) eintragen und speichern — das Secret wird nie wieder angezeigt, ein leeres Feld behält den gespeicherten Wert.
- Konfiguration: Versand-/Storno-/Retoure-Status, Import-Status, Bestellbestätigung an/aus, „Automatischer Abgleich“.
Update: Neues ZIP entpacken und den Ordner
lib/common/extensions/EverysizeCheckout über den bestehenden kopieren
(Dateien werden ersetzt, Zugangsdaten und Einstellungen bleiben in der
Datenbank); neue oder geänderte Texte übernimmt das Modul beim nächsten
Aufruf des Admin-Bereichs selbst. Steht
eine neue Schema-Version an, wird sie beim nächsten Install-Lauf idempotent
angehoben — das Modul bleibt dabei installiert und aktiv.
Abgleich (Import + Rückmeldung)
- Der Sync läuft über den eigenen Cron-Endpoint:
{SHOP_URL}/everysize-checkout-cron/everysize?token={TOKEN}— die URL steht fertig im Protokoll der Einstellungsseite (der Token wird bei der Installation erzeugt und kann dort neu erzeugt werden). Für externe Cron-Dienste (cron-job.org & Co.) einfach diese URL alle 5 Minuten aufrufen; der Abgleich selbst respektiert den Schalter „Automatischer Abgleich". - Alternativ per CLI im Shop-Root:
php yii.php everysize-checkout/sync(--forceumgeht den Schalter, Exit-Code 1 bei Fehlern). - „Verbindung testen" auf der Einstellungsseite prüft Zugangsdaten und Shop-Zuordnung und zeigt die everysize-Shop-ID.
Was der Import anlegt
orders-Zeile wie der osCommerce-Checkout: Namensspaltencustomers_,delivery_,billing_, komplette Straße mit Hausnummer, Bestellsprache aus der everysize-Sprache, Gastbestellung ohne Konto, Zahlart „everysize (PayPal)".orders_productsmit Netto-Preisen (so rechnet der osCommerce-Admin), Varianten über die echte Artikel-SKU (exakt > Groß-/Kleinschreibung, aktive > inaktive Artikel) undorders_products_attributesaus dem uprid — je Variante eine Attribut-Zeile mit Options- und Wert-ID.orders_totalmit den 6 Klassen des Shops (Subtotal, Shipping, Tax, Total, Paid, Due) in den Währungsformaten des Shops, Steuerzeile je Steuersatz austax_rates/zones_to_geo_zones(mehrstufige Prioritäten wieTax::get_tax_rate).- Bestandsabzug über
inventory(Größen-/Variantenbestand) bzw. den Artikelbestand;STOCK_LIMITEDwird respektiert, negativer Bestand ist eine Warnung, kein Fehler — die Bestellung ist bezahlt. - Vor dem Schreiben liest das Modul je Position den aktuellen Bruttopreis des Artikels und den Bestand. Weicht der Shop-Preis vom bei everysize bezahlten Preis ab oder liegt der Bestand unter der bestellten Menge, steht eine Warnung im Protokoll; die Bestellung wird trotzdem zum bezahlten Preis importiert. Beide Werte werden einmal an everysize gemeldet. Scheitert das Lesen oder Melden, läuft der Import unverändert weiter. Stornierte Bestellungen werden nicht gemeldet.
- Eine REVOKED-Bestellung wird direkt in den konfigurierten Storno-Status gestellt und bucht keinen Bestand ab.
- Alles in einer Transaktion: scheitert der Import, bleibt die Datenbank unverändert (idempotent beim Wiederholungsversuch).
Rückmeldung an everysize
- Versand (Status-Wechsel) + Sendungsnummern (das Tracking-Feld der
Bestellung bzw. die Sendungsverfolgung), Nachmeldung bis 14 Tage.
Sendungsnummern trägt der Händler auf dem Standardweg ein: Bestellung
öffnen → Tracking-Bereich → Sendungsnummer je Position
(
tracking-edit→orders/tracking-save). Die veraltete Routeorders/savetrackingwird von der Oberfläche nicht mehr benutzt. - Storno vor dem Versand (konfigurierter Status) mit Grund
MERCHANT_DECLINE, bei aktivem Schalter mit automatischer Vollerstattung. Die läuft nur, wenn sicher nichts versendet wurde (keine Versandmeldung, keine Sendungsnummer — auch keine von Hand eingetragene —, kein Versandstatus) und keine andere Erstattung existiert: weder im Shop gebucht (Zahlungsgutschrift, Erstattungs-Summe) noch bei everysize/PayPal. Ist die Erstattungsliste nicht lesbar, wird der Lauf übersprungen. Greift eine Sperre, steht der Grund im Bestellverlauf und in der everysize-Box; erstattet wird dann nur von Hand. - Retoure: osCommerce 4 kennt keinen Retoure-Status, und eine versendete
Bestellung lässt sich dort nicht stornieren (der Shop leitet den Status aus
den Positionen ab und setzt „Storniert“ sofort auf „Versendet“ zurück).
Kommt Ware zurück, erstatten Sie wie gewohnt — bei everysize-Bestellungen
in der everysize-Box im Bestelldetail: Häkchen „Ware ist zurückgekommen:
Retoure an everysize melden“ setzen, den zu erstattenden Betrag eintragen
(z. B. ohne Versandkosten) und „Erstatten“. Das Modul meldet zuerst die
Retoure (Grund
RETOUR) und erstattet dann den Betrag. Ist schon alles erstattet, meldet „Retoure melden“ die Retoure allein. - Optional: Wer bereits einen eigenen Status für Retouren nutzt, ordnet ihn in den Einstellungen als Retoure-Status zu — Bestellungen in diesem Status werden ebenfalls als Retoure gemeldet (ohne Erstattung).
- Jede Rückmeldung wird idempotent vermerkt (
everysize_checkout_report) und ist im Protokoll sichtbar (Werkzeuge → everysize Checkout → Protokoll) - Der everysize-Import schreibt die Händler-Bestellnummer NACH dem Commit zurück; eine fehlgeschlagene Rückmeldung wird beim nächsten Lauf geholt.
Storno bei everysize erkennen
Wird eine bereits importierte Bestellung später bei everysize storniert, zeigt die Erweiterung bei jedem Abgleich (nach Import und Rückmeldung) einen Hinweis in der everysize-Box der Bestellung (nur im Admin) und schreibt einen Eintrag ins Protokoll:
- Bestellung noch offen: „Bestellung … wurde bei everysize storniert. Bitte nicht versenden und im Shop stornieren.“
- Bestellung im Shop schon als versendet markiert: „… ist hier aber schon als versendet markiert. Bitte prüfen.“
- Bestellung im Shop schon storniert, zurückgesendet oder vollständig erstattet (eine Teilerstattung zählt nicht): kein Hinweis.
Der Hinweis in der Box steht, bis Sie die Bestellung erledigt haben (storniert, zurückgesendet, vollständig erstattet), der Protokolleintrag einmal je Bestellung, in der Standardsprache des Shops (Deutsch oder Englisch). Er steht nicht im Bestellverlauf, den Kundinnen mit Konto lesen können, es gibt keinen Statuswechsel und keine Mail an die Kundin; genannt wird nur die Bestellnummer, wie der Shop sie zeigt. Die Erweiterung ändert nichts selbst: kein Status, kein Bestand, keine Erstattung; Sie entscheiden. Ein Fehler bei dieser Prüfung erscheint höchstens als Warnung im Protokoll (je Fehlerart einmal am Tag) und stoppt weder Import noch Rückmeldung. Grenzen: Berücksichtigt werden Stornos der letzten 30 Tage (nach Bestelldatum), höchstens 500 Bestellungen je Lauf (bei mehr die jüngsten). Eine Erstattung, die Sie direkt in PayPal ohne Storno bei everysize veranlassen, erkennt die Erweiterung nicht.
Bestellungen im Admin
- Bestelldetail: die everysize-Box im Summen-Bereich — everysize-Nummer, PayPal-Capture, Zahlstände (bezahlt/erstattet/offen), Erstattungen ganz/teilweise mit Idempotency-Key und die Rückmeldungen dieser Bestellung.
- Bestellübersicht: Kennzeichen „everysize (PayPal)“ in der Zeile, Suche nach der everysize-Nummer, Filter „nur everysize-Bestellungen“.
- Erstattungen laufen über everysize an PayPal; jede Erstattung (Box oder automatisch) steht als Kommentar im Bestellverlauf, ohne Statuswechsel.
- Das Betragsfeld der Box ist mit dem offenen Betrag vorbelegt und wird nie geleert; ein leeres Feld erstattet nie. Vor dem Absenden fragt der Browser mit dem Betrag nach.
- Fassung 3 der Regeln (Kurzfassung): Ein 2xx ohne
refundIdist unklar, kein Erfolg. Der Eintrag wird zuerst angelegt, danach wird die PayPal-Liste gelesen und derenrefundIds werden im Eintrag gespeichert; eine alte oder fremde Erstattung gilt nie als Treffer. Ungültige oder nicht lesbare Liste, veralteter Tab: der neue Eintrag wird gelöscht, nichts gesendet. Lehnt der Checkout eine Wiederholung sicher ab, bleibt der Eintrag offen (PayPal prüfen, als geklärt markieren). Die 150 s zählen ab der letzten Sendung; Wiederholen und „Als geklärt markieren“ sind atomar. Erst Schlüssel-/Erstattungsbericht, dann wird der Eintrag gelöscht; ein Fehler danach (Verlauf, Protokoll) sagt nie „fehlgeschlagen“. Die Automatik sendet höchstens einmal. Der Saldo der Box kommt aus der PayPal-Liste (auch direkt in PayPal gemachte Erstattungen), nicht nur aus den Berichten des Shops. Beim Einschalten der Automatik (aus nach an) wird der Stichtag neu gesetzt; Stornos, die die Automatik auslässt (keine Capture-ID, kein Storno-Status, später hinzugefügte Position), stehen einmal im Protokoll. - Ergebnis unklar: Antwortet der Checkout nicht eindeutig (Zeitüberschreitung,
Serverfehler, aber auch 401, 403, 404, 429 oder ein Fehler im Browser), kann
das Geld geflossen sein. Eindeutig abgelehnt ist nur 422 mit
PAYPAL_REFUND_FAILEDoderREFUND_AMOUNT_INVALIDund 400 mitORDER_NOT_PAID_USING_EVERYSIZE_CHECKOUT_PAYMENTS. Jede Erstattung steht vor dem Senden als offener Eintrag in der Datenbank (einer je Bestellung, zwei Admins oder Tabs senden nie gleichzeitig); der Schlüssel steht nicht mehr in der Sitzung. Solange der Eintrag offen ist, geht keine andere Erstattung raus, weder von Hand noch automatisch. Ein Eintrag unter 150 Sekunden gilt als „läuft noch“. Danach: Wiederholen (derselbe Betrag; vorher liest das Modul die PayPal-Liste und schließt den Eintrag als Erfolg ab, wenn dort eine passende, dem Shop noch unbekannte Erstattung steht; ging die erste Anfrage nicht durch, wird der Betrag jetzt ausgezahlt) oder Als geklärt markieren (sendet nichts, schreibt Bericht und Protokolleintrag, die automatische Erstattung bleibt für diese Bestellung gesperrt). Ein anderer Betrag wird abgelehnt. Das Formular sendet die beim Laden bekannte Erstattungssumme (aus der PayPal-Liste) mit: veraltet oder Liste nicht lesbar heißt, es wird nichts gesendet; ohne lesbare Liste gibt es das Formular gar nicht. Ein Fehler im Browser (504 vom Webserver) zeigt „Ergebnis unklar“ und lädt neu, nie „fehlgeschlagen“. Ein doppelter Klick endet nicht mehr in einem SQL-Fehler, sondern wird als Wiederholung behandelt. Alte Berichte „unklar“ früherer Versionen sind keine offenen Einträge, nur Anzeige und Sperre der Automatik. Erstattungsaufrufe warten bis zu 90 Sekunden.
Architektur
src/— Framework-freier Kern (Settings, API-Client, Sync, Import/Export-Logik), unit-getestet (130 Tests, PHP 8.1–8.3).classes/— osCommerce-Anbindung (Db, Settings, OrderImporter, OrderMailer, Protocol).Setup.php— Install/Remove (idempotent, Datenhalt) + Übernahme alter Zugangsdaten ausplatforms_configuration.frontend/controllers/CronController.php— der Cron-Endpoint.
Lizenz
MIT, siehe LICENSE.