PayPal Express Checkout und Unable to Place the order

Ich habe schon einige Probleme mit PayPal und Magento gelöst, aber folgendes war neu. Kunden konnten vom Warenkorb aus über den Check out with PayPal Button ganz normal die Bezahlung vornehmen. Nach erfolgreicher Bezahlung wurde jedoch die Fehlermeldung ” Unable to Place the order ” angezeigt und die Bestellung unterbrochen. Einige Kunden dachten etwas während der Bestellung falsch gemacht zu haben, und versuchten es gleich noch einmal. Nun wurde die Fehlermeldung ” Transaction refused because of an invalid argument. A successful transaction has already been completed for this token. ” angezeigt.

Kurz, beim ersten Versuch wurde das PayPal Konto bzw. die Kreditkarte des Kunden bereits belastet. Darum konnte beim zweiten Versuch die Transaction nicht noch einmal vorgenommen werden. Hinzu kam, dass trotz korrekten IPN Response im Backend keine Bestellung erstellt wurde. Der Grund war folgender:

Bei solchen Fehlermeldungen lohnt es sich immer einen Blick in die EAV tables zu werfen. In meinem Fall wurde aus irgendeinem Grund die increment_last_id vom Typ sales/order_invoice geändert.

Die Länge der ID wird zudem in entity_model festgelegt, was in meinem Fall nicht übereinstimmte.

Da es keinen Grund gab die länge der Rechnungs Nummer zu ändern, habe ich diese wieder “recovered”.

Da ich zu diesem Zeitpunkt nicht wusste, wie viele Bestellungen schon vorgenommen wurden, habe ich ausserdem increment_prefix auf 2 gesetzt, einfach um sicher zu gehen, dass es keine weiteren Konflikte gibt. Vermutlich hätte ich auch die Rechnungsnummer einfach auf 100001000 setzen können, denn so viele Bestellungen sind definitiv nicht eingegangen.

Wie auch immer, das Problem mit den PayPal Express Bezahlungen wurde damit gelöst und funktioniert auch zwei Wochen nach dem Change noch.

Magento und max_input_vars

Es gibt Tage als Magento Entwickler bei denen man einfach nur verzweifelt, und zwar dann, wenn man komplexe Produkte oder Kategorien erstellen möchte. In den letzten zwei Wochen habe ich mich gleich mit zwei solchen Problemen beschäftigt, bei denen leider keine Fehlermeldung (system.log, exception.log etc.) zu sehen war welche zumindest ein bisschen weiterhelfen würde. Konkret geht es um die Standardeinstellung in der php.ini.

Diese Standardeinstellung führt dazu, dass komplexe Formulare im Admin Panel zwar Erfolgreich abgeschickt werden können, jedoch nicht alles vom Server akzeptiert wird. Will man also Kategorien mit mehr als 1000 Produkten speichern oder 100 bis 150 Bundle Items zu einem Bundle Produkt hinzufügen, gibt es hier möglicherweise Probleme.

Das Problem kann gelöst werden indem man den Wert für max_input_vars in der php.ini oder in der .htaccess auf 2000 oder mehr erhöht, aber nicht unbedingt mehr als benötigt.

Das ganze kann man mit LocationMatch auf das Admin Panel beschränken.

Malware in Bilddateien finden

Maleware Inside Image Exif Header

Es ist ein Alptraum. Die Liveumgebung deines Kunden wurde gehackt und du weisst nicht, wie genau und welche Daten gestolen wurden. Schnell muss also untersucht werden, wo die Schwachstelle liegt um solche Angriffe in Zukunft besser abzufangen. Natürlich gibt es verschiedene Wege sich Zugang zu einer Liveumgebung zu verschaffen. In diesem Post möchte ich nur kurz darauf eingehen, wie mittels Bilddateien beliebiger Code eingeschleust werden kann.

Wie auf Snapfast und Sucuri beschrieben, kann beliebiger Code in EXIF von Bilddateien untergebracht werden. Oft genügt schon ein einfaches Script um einen neuen Administrator account zu erstellen. Alles weitere passiert dann im Hintergrund, oft unerkannt.

Leider hilft ein svn status oder git status nicht um geänderte Dateien zu erkennen, denn oft sind Verzeichnisse wie /media/ nicht versioniert.

Hier ein einfacher Befehl wie du solche Bilddateien mit “find” aufspüren kannst.

Sollten Dateien auf dem Produktivsystem infiziert sein, bekommst du folgendes Suchergebnis.

5 praktische Beispiel für die tägliche Arbeit mit Magento

1. Sicherung von media/catalog

So erstellst du eine Sicherung von media/catalog ohne dem /cache/ Verzeichnis.

Das gleiche mit dem aktuellen Datum im Dateinamen.

2. Dateien ohne Berechtigungen für Apache

So findest du Dateien welche nicht die nötigen Berechtigungen für Apache besitzen. Das macht Sinn wenn du Berechtigungsprobleme früh erkennen möchtest. Zum Beispiel Schreib- oder Leseberechtigungen bei Dateien oder Verzeichnissen für diverse Upload Funktionen.

3. SQL / CSV Dateien im Projektverzeichnis

Manchmal ist es keine gute Idee Datenbank Sicherungen oder andere exportierte Dateien mit sensiblen Informationen im Projektverzeichnis abzulegen. Je nach Sicherheitseinstellungen können solche Dateien von dritte heruntergeladen werden. Um mögliche Sicherungen auf dem Produktivsystem auffinden zu können, brauchst du nur ein einfachen ” find ” Befehl mit der Option ” iregex “.

4. Report Dateien der letzten 24 Stunden

Hier sind weitere Optionen fuer ” -ctime “.

5. Logdateien leeren

Schnell wachsende Logdateien wie system.log oder exception.log können eine Ursache für einen Serverausfall sein. Mit Hilfe von ” truncate ” kannst du log Dateien ohne Risiko auf deinem Produktivsystem leeren.

Wenn du nicht alles entfernen möchtest, kannst du auch einen Teil für die Fehlersuche behalten.

Praktische Beispiele für deine Magento Logdatei Analyse

Verbessere deine wöchentliche Logdatei Analyse mit ein paar einfachen ” grep ” Befehlen. Verwende diese vor jedem Rollout um sicher zu gehen, dass dein Code einwandfrei funktioniert und keine Fehlermeldungen generiert. Um bei grösseren Logdateien die Übersicht zu behalten, kannst du mit ” tail ” die letzten 1000 Zeilen überprüfen, oder zunächst einfach mit ” wc -l ” schauen wie hoch die Anzahl an Fehlermeldungen überhaupt ist.

Zähle die Resultate mit ” wc -l ” am Ende.

Zeige die letzten 1000 Zeilen von system.log mit ” tail -n 1000 ” an.

1. System.log

1.1 Zugriffe auf ein Array mit einem Key welcher nicht existiert

1.2 Zugriff auf eine Variable welche nicht definiert ist

1.3 Debug Ausgaben mit Mage::log() generiert

1.4 Diverse fehlgeschlagene Versuche eine Datei oder ein Verzeichnis zu erstellen oder manipulieren

1.5 Falsch definierte oder nicht existierende Template Dateien

1.6 Fehler bei Zugriff auf ein Objekt

1.7 Parameter an eine Funktion nicht korrekt übergeben

1.8 Ungültige Variable an eine Schleife übergeben

Alles mit einmal finden:

2. Exception.log

2.1 Generelle Probleme mit XML Dateien

2.2 Spezifische Probleme mit dem Authorize.net Gateway

2.3 Spezifische Probleme mit dem PayPal Gateway

2.4 Generelle Probleme mit CURL

Alle mit einmal finden:

3. Reports

Report Dateien auf der Konsole zu überprüfen ist mühsam. Mit den folgenden Befehlen kannst du schnell die neusten 10 Reports mit einmal durchsuchen.

3.1 MySQL Verbindungen

3.2 Invalid config field

3.3 Unable to read response

3.4 External urls redirect

Alle mit einmal finden:

4. Apache error logs

4.1 Fehlende Dateien im Projektverzeichnis

Geplante Tasks für Apache Benutzer einrichten

Geplante Tasks (Cron jobs) für PHP Applikationen sollten einem spezifischen Benutzer ohne root Berechtigungen zuordnet werden, also zum Beispiel www-data. So verhinderst du unter anderem, dass bei einem System Update die geplanten Tasks für root überschrieben werden.

1. Apache user suchen

Den Benutzer welcher von Apache verwendet wird, kannst du aus der Prozessliste entnehmen.

2. Tab editieren

Editiere den crontab mit der Option -u und dem Benutzer welcher von Apache verwendet wird. Dieser Befehlt erstellt eine Benutzerspezifische Datei in /var/spool/cron/crontabs/.

Füge deinen Cronjob ein und speichere alle Änderungen mit CTRL-O.

3. Syslog überprüfen

Anschliessend kannst du schauen ob dein Cronjob korrekt ausgeführt wird.

Table is marked as crashed and should be repaired

Nicht gleich verzweifeln. Die folgende Fehlermeldung kannst du wie in diesem Artikel beschrieben recht schnell beheben.

Es gibt verschiedene Ursachen für eine beschädigte MySQL Tabelle. Die häufigsten sind:

  • Im schlimmsten Fall defekte Hardware
  • Plötzlicher Server Neustart ( Stromausfall )
  • Reset (ACPI shutdown)

In den meisten Fällen kann eine defekte MySQL Tabelle in der Konsole wieder repariert werden.

Das sieht ziemlich einfach aus, trotzdem solltest du dir 5 Minuten Zeit nehmen und deine Datenbank vorher sichern, denn möglicherweise sind noch andere Tabellen betroffen.