PayPal Plus

Oxid

Das PayPal-Plus Modul für Oxid eShop ist ein Alptraum. Dass sie das über eine/die Paywall gelöst haben, ist nicht sehr schön. Schon allein, weil bestimmte Tags bei jedem Theme vorhanden sein muss und man die Tags in den Einstellungen definieren muss (kann, weil man ja alles so lassen kann). Und das für jedes Theme. Was ist, wenn jemand ein völlig eigenes Theme verwendet (nicht basierend auf best. Theme)? Dann kann man wohl kein PPP verwenden. Zudem ist lt. Installations-PDF nicht garantiert, dass es mit dem Mobile Theme funktioniert. What?? Und das Modul ist wirklich ein ungeheures Dateimonster, weil die gesamten PayPal-REST-API-Dev-Bibliotheken dabei sind.

Laut Internet hat kaum jemand das Modul zum Laufen gebracht. Ich war offenbar einer der wenigen, die es zum Laufen gebracht haben.

Jetzt aber der große Pferdefuß:

Es läuft, jedoch nicht mit meinem (nbservice) Modul. Es liegt offenbar nicht an meinem Modul, weil in Internet viele Leute das selbe Problem haben. Es funktioniert alles bis es zur PayPal-Zahlung selbst kommt. Also: Auswahl von PayPal Plus auf der PayWall und dann klicken auf den Nächsten Schritt (jetzt sollte mittels jQuery die Weiterleitung auf PayPal erfolgen). Dann warten und es kommt eine (allgemeine) Fehlermeldung ('Entschuldigung, PayPal Plus ist momentan nicht verfügbar.<br/>Bitte aktualisieren Sie Ihren Warenkorb und versuchen es erneut oder kontaktieren Sie den Shop-Administrator.').

Sobald mein Modul deaktiviert ist, funktioniert es einwandfrei.

Ich habe mir eventuelle Überscheidungen der beiden Module vorgenommen. Gibt es Klassen, Templates oder Blöcke, die beide Module verwenden/überschreiben? Nein, gibt es nicht. Keine einzige.

Nächster Versuch: die beiden beiden HTML-Quelltexte der PayWall-Seite mit uns ohne meinem Modul vorgeknöpft. Auch nichts. Keinerlei Änderung im Quelltext (nur meine geänderter Text der EU-Cookie-Warnung und natürlich andere Token für den PP-Checkout). Wie kann das sein? Wie kann sich das Verhalten ändern, wenn der Quelltext absolut gleich ist?

Dann: an geänderten HTML-Tags kann es ohnehin nicht liegen, weil das PPP-Modul selbst das Vorhandensein der wichtigen (das sind die in den Einstellungen) Tags prüft. Auch sind alle .js-Dateien bei beiden Themes verfügbar (hätte da ja auch einen Error in der Konsole bekommen).

Dann jQuery auf neueste Version geupdated. Hat nichts gebracht.

Also stürze ich mich auch das PPP-Javascript-File für Oxid. Das liegt hier:

modules/payp/paypalplus/out/src/js/payppaypalpluswall.js

(/var/www/webserver/oxid2/modules/payp/paypalplus/out/src/js/payppaypalpluswall.js)

Also lauter alerts gesetzt, um zu schauen, wo genau der Fehler auftritt.

Rausgefunden (quick and dirty fix): das muss man ändern, dann funktioniert es auch mit meinem Modul: (aber Waruuuuummm?)

ca. Zeile 574

von

if (sTextStatus == 'success' ) && mData == _this.options.varToken) {

in

if (sTextStatus == 'success' ){ //&& mData == _this.options.varToken) {

Dann funktioniert es

Offenbar wird als variable mData nicht nur der Token, sondern eine ganze Menge HTML-Text (die ganze PayWall??? Jedenfalls nicht die komplette Seite, aber zumindest ein Teil davon) übergeben. Warum kommt da die Seite raus? Bei der Seite OHNE Modul kommt als mData nur der Teoken (z.B. 43b313cd4063405a5d06a073db35e0bf).

Die jQuery.ajax-Dokumentation 1) sagt dazu:

success
Type: Function( Anything data, String textStatus, jqXHR jqXHR )
A function to be called if the request succeeds. The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter or the dataFilter callback function, if specified; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the success setting can accept an array of functions. 

Meine Nachforschungen haben ergeben: per Ajax wird nicht etwa PayPal aufgerufen, sonder der Shop selbst. Mit der Form der Seite als POST (console.log(„Request: “ + form.serializeArray().toSource() ); sagt: [{name:„stoken“, value:„73EED611“}, {name:„lang“, value:„0“}, {name:„actcontrol“, value:„payment“}, {name:„cl“, value:„payment“}, {name:„fnc“, value:„validatepayment“}, {name:„paymentid“, value:„payppaypalplus“}]). Als Ergebnis wir der Inhalt des Tokens erwartet (oder eine Fehlermeldung). Das ist offenbar so eine Art Sicherheitsvorkehrung, um den Token, der ja im Quelltext der Seite steht zu verifinzieren. Erst wenn der Token der Selbe ist, wird die Zahlung initiiert.

Mein Modul fängt auf POST-Request ab, weil ja die Leute die NB-Nummer eingeben müssen. Daher kommt offenbar auf den Ajax-Request (fnc: validatepayment) nicht nur der Token, sondern die Seite ohne diese spezielle Funktion. Offenbar beisst sich da was mit meinem Modul. Uff! Übrigens: Diese Sicherheitsvorkehrung halte ich für fraglich, denn wenn sich jemand die Mühe macht, den Toklen im DOM zu ändern, dann kann er sich auch die Mühe machen, den Ajax-Request im DOM zu ändern auf eine Seite, die dann genau den geänderten Token zurück gibt. Augenwischerei?

Mein Verdacht lt. metadata.php (PayPal): 'payment' ⇒ 'payp/paypalplus/controllers/payppaypalpluspayment',

OK, der Ajax-Request hat offenbar nicht (nur) Sicherheitsaspekte. Die überlagernde Mathode validatePayment() in der 'payp/paypalplus/controllers/payppaypalpluspayment.php' updated anscheinend das PayPal-Payment.Offenbar wird die Methode nicht ausgeführt, wenn mein Modul geladen ist.

OK, das ist es auch nicht. /payppaypalpluspayment.php wird ausgeführt. Bei der Funktion _updatePayment() (ca. Z. 374) fibt es eine IF-Abfrage:

        $oShop = paypPayPalPlusShop::getShop();
        if ($oShop->getValidator()->isPaymentCreated() and $oShop->getRequestParameter('ajax')) {

Der 1. Teil der Abfrage (isPaymentCreated()) ist nicht 1. Daher gibt es einen Fehler. Bin ein Stück weiter.

Jetzt weiter: im File core/payppaypalplusvalidator.php die Methode isPaymentCreated($oPayment = null) (ca. Z. 135). Der Aufruf '$mPayment = $this→getShop()→getPayPalPlusSession()→getPayment();' fibt ein (bool)false zurück, obwohl $this→getShop()→getPayPalPlusSession() bis dahin ein Objekt ist. Dann geht das folgende if ($mPayment instanceof PayPal\Api\Payment) { schief.

Hängt es vielleicht doch damit zusammen, dass ich vor die Bestellnummer stets noch ein 'NB' setze??? Nachrecherchiert: ne, ich ändere die Bestellnummer nicht intern, sondern nur in der Repräsentation. Kann es also auch nicht sein. Versuche, bei PayPal noch ein NB davorzisetzen, wenn nötig, scheitern auch.

Also: in der _updatePayment() kommt die InvoiceNumer MIT NB an. Wenn ich $oShop→getValidator()→isPaymentCreated(„ajax“) im IF unschädlich mache, gibt es Fehlermeldung, weil das Update $oPayPalPaymentHandler→update($oPayPalSession→getApiContext()); kein Objekt übergeben bekommt. ABER: Wenn ich $this→_ajaxResponseSuccess(); nach oben setze, dann kommt der korrekte Token so wie er soll und und die ganze Chose funktioniert! Es liegt also tatsächlich daran, dass $oShop→getValidator()→isPaymentCreated() false ist. Offenbar kann er die (PayPal)Session nicht korrekt auslesen ($mPayment = $this→getShop()→getPayPalPlusSession()→getPayment(); in …validator.php) . Oh. Oder die Session wird gar nicht korrekt gespeichert.