Neuigkeiten
  • Die modified eCommerce Shopsoftware ist kostenlos, aber nicht umsonst.
  • Damit wir die modified eCommerce Shopsoftware auch zukünftig kostenlos anbieten können:

Autor Thema: PayPal order_status automatisch setzen Problem  (Gelesen 12269 mal)

Offline noRiddle

  • Experte
  • *****
  • Beiträge: 9.945
  • Geschlecht: Männlich
    • Teile Beitrag
    • Webdesign Bonn - Köln
Re: PayPal order_status automatisch setzen Problem
« Antwort #15 am: 21. April 2015, 16:18:09 »
Im Zusammenhang mit dem hier beschriebenen, ja nun behobenen, Bug fiel mir noch folgendes auf:
In der Funktion xtc_cfg_pull_down_order_statuses() die auch auf der PayPal-Config-Seite benutzt wird - (Definition der Funktion befindet sich in /admin/includes/functions/general.php) -
wird folgendes definiert:
Code: PHP  [Auswählen]
$statuses_array = array (array ('id' => '1', 'text' => TEXT_DEFAULT));
Daß heißt der erste Wert im in der Funktion zusammengebauten Pull-Down-Menu hat die ID 1.
Da dann folgend die orders_status_ids aus der DB-Tabelle orders_status in das Pull-Down geladen werden, dürfte die 1 als ID nicht mehr vorkommen. Dies tut sie jedoch, da beim Installieren des Shops die ID 1 ebenfalls vergeben wird:
Code: SQL  [Auswählen]
INSERT INTO orders_status VALUES (1,1,'Pending');
INSERT INTO orders_status VALUES (1,2,'Offen');

Folge:
Wir haben zweimal die ID 1 im Pulldown und folglich auch zwei Möglichkeiten die ID 1 im POST-Array an PHP und somit die DB zu senden.
Das äußert sich insbesondere negativ wenn man den ersten Status in der PayPal-Config für irgendetwas auswählen möchte, denn wenn zwei option-Werte im select-Menu auf selected="selected" stehen, wird das zweite angezeigt, auch wenn man das erste gewählt und gespeichert hat.

Fix:
In der o.g. Funktion die ID auf 0 setzen für TEXT_DEFAULT.
Code: PHP  [Auswählen]
$statuses_array = array (array ('id' => '0', 'text' => TEXT_DEFAULT));

Gruß,
noRiddle

Offline GTB

  • modified Team
  • *****
  • Gravatar
  • Beiträge: 5.271
  • Geschlecht: Männlich
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #16 am: 21. April 2015, 16:29:14 »
Hi,

das mit dem orders_status wurde so gelöst:

Code: PHP  [Auswählen]
$statuses_array = array (array ('id' => DEFAULT_ORDERS_STATUS_ID, 'text' => TEXT_DEFAULT));

Es wird hier ja Standard angezeigt. Somit wird mit der Auswahl standard immer der default Status gesetzt.

Wenn der default Status geändert wird, werden auch diese auf den neuen Status geändert.

Hier der Auszug aus der orders_status.php

Code: PHP  [Auswählen]
        if (isset($_POST['default']) && ($_POST['default'] == 'on')) {
          // update installed payment
          $payment_installed = explode(';', MODULE_PAYMENT_INSTALLED);
          for ($i=0, $n=count($payment_installed); $i<$n; $i++) {
            $class = substr($payment_installed[$i], 0, strrpos($payment_installed[$i], '.'));
            if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $payment_installed[$i])) {
              include(DIR_FS_CATALOG_MODULES . 'payment/' . $payment_installed[$i]);
              $module = new $class();
              if (isset($module->order_status) && $module->order_status == DEFAULT_ORDERS_STATUS_ID) {
                xtc_db_query("UPDATE " . TABLE_CONFIGURATION . "
                                 SET configuration_value = '"
. (int)$orders_status_id . "'
                               WHERE configuration_key = '"
.strtoupper('MODULE_PAYMENT_'.$class.'_ORDER_STATUS_ID')."'");
              }
            }
          }
          xtc_db_query("UPDATE " . TABLE_CONFIGURATION . "
                           SET configuration_value = '"
. xtc_db_input($orders_status_id) . "'
                         WHERE configuration_key = 'DEFAULT_ORDERS_STATUS_ID'"
);
       
        }

Gruss Gerhard

Offline noRiddle

  • Experte
  • *****
  • Beiträge: 9.945
  • Geschlecht: Männlich
    • Teile Beitrag
    • Webdesign Bonn - Köln
Re: PayPal order_status automatisch setzen Problem
« Antwort #17 am: 21. April 2015, 16:31:22 »
Jau, besser, danke.

Gruß,
noRiddle

Offline ChristianRothe

  • Mitglied
  • ***
  • Beiträge: 125
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #18 am: 18. Juli 2015, 23:47:02 »
Hallo Community.
Es gibt in diesem Forum einige Threads wo moniert wird, daß nach Abschluß einer Bestellung per
PayPal Kaufabwicklung (Modul paypal)
oder
PayPal Express (Modul paypalexpress)
und erfolgreicher Zahlung (payment_status in DB-Tabelle paypal 'complete')
der order_status in der DB-Tabelle orders nicht gesetzt wird welcher im Backend unter
Erweiterte Konfiguration => Partner => PayPal
bei "Bestellstatus OK" (Konfigurations-Konstante PAYPAL_ORDER_STATUS_SUCCESS_ID) gesetzt ist.

Eine Lösung des Problems wurde nirgends wirklich gegeben.

In der Funktion write_status_history() gibt es folgendes Konstrukt:
Code: PHP  [Auswählen]
if($ack=="SUCCESS"  || $ack=="SUCCESSWITHWARNING") {
    $o_status = PAYPAL_ORDER_STATUS_PENDING_ID;
} else {
    $o_status = PAYPAL_ORDER_STATUS_REJECTED_ID;
}
Diese Codestelle ist völlig korrekt. Begründung und Auflösung siehe unten.

Dieses müsste, ohne alle Vorgänge und allen Code genauestens analysiert zu haben, nach meiner Meinung so lauten:
Code: PHP  [Auswählen]
if($ack=="SUCCESS"  || $ack=="SUCCESSWITHWARNING") {
    $o_status = PAYPAL_ORDER_STATUS_SUCCESS_ID; //set right status, noRiddle
} else {
    $o_status = PAYPAL_ORDER_STATUS_REJECTED_ID;
}

Zumindest aber müsste weiter unterteilt werden, möchte man z.B. bei $ack=="SUCCESSWITHWARNING" einen anderen Status setzen als bei $ack=="SUCCESS".

Fazit:
Der Status den man im Backend bei "Bestellstatus OK" (s.o.) bestimmt hat kann mit dem bisherigen Code gar nicht korrekt gesetzt werden.

Irre ich ?, übersehe ich etwas ?
Ja, Du übersiehst etwas. Nach dem Ende des Bestellvorgangs im Shop wissen wir noch gar nicht, ob PayPal die Zahlung wirklich ausführen wird. Deshalb ist "Pending" genau der richtige Bestellstatus. PayPal prüft nämlich erst NACH Durchlaufen des Zahlungsvorgangs die Bonität des Käufers und entscheidet sich dann öfter mal im Nachgang, dass es die Zahlung nicht ausführen will. Z.B. wenn bei der vom Käufer verwendeten Kreditkarte das Limit überschritten ist oder wenn PayPal bei früheren Abbuchungen vom Girokonto des Käufers Rücklastschriften hatte und der Kunde wieder per Lastschrift mit PayPal abrechnen will.

Was Du noch übersiehst: Das "echte" Ergebnis des Zahlungsvorgangs meldet PayPal über einen Callback auf /callback/paypal/ipn.php zurück. Der "Rückruf" durch Paypal auf dieses Shopmodul erfolgt in der Regel 10 bis 15 Sekunden nach Abschluss der Zahlung im Shop. Von diesem Modul wird dann bei einer erfolgreichen Zahlung der Success-Status gesetzt (bzw. andere Status bei nicht erfolgreichen Zahlungen).  Deshalb würde ich empfehlen, die oben genannte Code-Stelle genau so lassen, wie sie ursprünglich war.

Offline noRiddle

  • Experte
  • *****
  • Beiträge: 9.945
  • Geschlecht: Männlich
    • Teile Beitrag
    • Webdesign Bonn - Köln
Re: PayPal order_status automatisch setzen Problem
« Antwort #19 am: 19. Juli 2015, 01:33:59 »
Okay, danke für das Feedback.
Habe das jetzt aus Zeitgründen nicht überprüft, aaaber: Warum haben so viele das Problem, daß der Callback nicht funktioniert ?
Du magst Recht haben mit deinen Ausführungen
- wie gesagt habe ich's nicht überprüft -
wie jedoch lautet die Lösung nach deiner Meinung ?

Gruß,
noRiddle

*NACHTRAG*
Und hat es Gambio, wie ich hier eruiert und zitiert habe dann auch verkehrt gemacht ?

Offline ChristianRothe

  • Mitglied
  • ***
  • Beiträge: 125
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #20 am: 19. Juli 2015, 09:37:34 »
Warum der richtige Status bei anderen Leuten nicht gesetzt wird, kann ich Dir nicht sagen. Eigentlich kann es nur bedeuten, dass der IPN-Callback von PayPal nicht korrekt im Shop ankommt bzw. nicht korrekt verarbeitet wird. Dies müsste man anhand von konkreten Einzelfällen prüfen. Z.B. könnte man in der orders_status_history schauen, ob dort entsprechende Einträge mit den PayPal-Zahlungsdaten und der PayPal-Transaktion vorhanden sind (diese werden nämlich auch von dem Callback-Modul geschrieben).

Mal angenommen, der Callback funktioniert bei manchen Leuten nicht: Die Bestellung gleich im after_process-Schritt auf den Success-Status zu setzen, würde dann auch bedeuten, dass nicht bezahlte Bestellungen als erfolgreich bezahlt markiert würden und auch so blieben. Denn der echte Zahlungsstatus wird von PayPal - wie oben geschrieben - nur über den IPN-Callback mitgeteilt. Deshalb muss man als Nutzer der PayPal-API auf jeden Fall sicherstellen, dass der API-Callback funktioniert. Ansonsten läuft man als Shopbetreiber Gefahr, Bestellungen zu verschicken, für die man niemals Geld sieht. Denn aus der Tatsache, dass jemand bei PayPal den Zahlungsablauf bis zum Ende durchlaufen hat, kann man NICHT zwingend ableiten, dass der Shopbetreiber auch sein Geld erhalten wird.

Warum sich Gambio entschlossen hat, auch gleich den Success-Status zu setzen, weiß ich nicht. Gibt es dort vielleicht ein zweites Statusfeld in der Datenbank für den Zahlungsstatus? So läuft es nämlich in meinen eigenen Shops: Ich habe ein neues Feld für den Zahlungsstatus eingeführt. Vom Kunden erfolgreich übermittelte Bestellungen erhalten bei mir auf jeden Fall immer den Bestellstatus "Offen". In einem weiteren Datenbankfeld wird dann der Bezahlstatus "Erfolgreich bezahlt", "Zahlung in Überprüfung", "Zahlung abgelehnt" etc. geführt. Vielleicht wollen ja die Macher des Modified Shops sowas auch mal einführen??? Eine sinnvolle Hilfe für die tägliche Arbeit wäre die Auftrennung von Bestellststatus und Zahlungsstatus auf jeden Fall.

Offline noRiddle

  • Experte
  • *****
  • Beiträge: 9.945
  • Geschlecht: Männlich
    • Teile Beitrag
    • Webdesign Bonn - Köln
Re: PayPal order_status automatisch setzen Problem
« Antwort #21 am: 19. Juli 2015, 16:50:22 »
Habe mir jetzt mal die Callback-Datei angeschaut (/callback/paypal/ipn.php).
In der Tat wird dort die Funktion callback_process() aus der Klasse aufgerufen und dort wird der korrekte Status gesetzt:

Code: PHP  [Auswählen]
        if(strtoupper($result) == 'VERIFIED' || $result == '1') {
            // Steht auf Warten
            if(strtolower($this->data['payment_status']) == 'completed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            //Set status for Denied, Failed
            } elseif((strtolower($this->data['payment_status']) == 'denied') OR (strtolower($this->data['payment_status']) == 'failed')) {
              $order_status_id = PAYPAL_ORDER_STATUS_REJECTED_ID;
            //Set status for Reversed
            } elseif(strtolower($this->data['payment_status']) == 'reversed') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Canceled-Reversal
            } elseif(strtolower($this->data['payment_status']) == 'canceled-reversal') {
              $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
            //Set status for Refunded
            } elseif(strtolower($this->data['payment_status']) == 'refunded') {
              $order_status_id = DEFAULT_ORDERS_STATUS_ID;
            //Set status for Pendign - eigentlich nicht nötig?
            } elseif(strtolower($this->data['payment_status']) == 'pending') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Processed - wann kommt das ?
            } elseif(strtolower($this->data['payment_status']) == 'processed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            }
          }

Evtl. liegen/lagen die Probleme ja an dem zweiten Problem welches ich in vorliegendem Thread hier gepostet hatte. Hat jemand den Status für PAYPAL_ORDER_STATUS_SUCCESS_ID mit der ID 1 gesetzt kommt es zu Unstimmigkeiten weil die ID 1 zweimal vorkommt/vorkam.

@GTB
In diesem Zusammenhang, GTB, fällt mir auf, daß deine Lösung (hier gepostet) nicht korrekt sein kann.

Begründung:

Mit

Code: PHP  [Auswählen]
    $statuses_array = array (array ('id' => DEFAULT_ORDERS_STATUS_ID, 'text' => TEXT_DEFAULT));

setzt du den Deafult-Wert im Dropdown auf den orders_status welcher als Default, also als Standard in den Bestellstatus eingestellt ist.
Da jedoch in der Funktion xtc_cfg_pull_down_order_statuses() in /admin/includes/functions/general.php alle Status aus der Tabelle orders_status ausgelesen und in das Array für das Dropdown geschrieben werden, auch der orders_status der auf "Standard" gesetzt wurde, kommt trotzdem wieder eine ID zweimal vor.
Richtig ?

Gruß,
noRiddle

Offline GTB

  • modified Team
  • *****
  • Gravatar
  • Beiträge: 5.271
  • Geschlecht: Männlich
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #22 am: 21. Juli 2015, 08:06:11 »
Habe mir jetzt mal die Callback-Datei angeschaut (/callback/paypal/ipn.php).
In der Tat wird dort die Funktion callback_process() aus der Klasse aufgerufen und dort wird der korrekte Status gesetzt:

Code: PHP  [Auswählen]
        if(strtoupper($result) == 'VERIFIED' || $result == '1') {
            // Steht auf Warten
            if(strtolower($this->data['payment_status']) == 'completed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            //Set status for Denied, Failed
            } elseif((strtolower($this->data['payment_status']) == 'denied') OR (strtolower($this->data['payment_status']) == 'failed')) {
              $order_status_id = PAYPAL_ORDER_STATUS_REJECTED_ID;
            //Set status for Reversed
            } elseif(strtolower($this->data['payment_status']) == 'reversed') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Canceled-Reversal
            } elseif(strtolower($this->data['payment_status']) == 'canceled-reversal') {
              $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
            //Set status for Refunded
            } elseif(strtolower($this->data['payment_status']) == 'refunded') {
              $order_status_id = DEFAULT_ORDERS_STATUS_ID;
            //Set status for Pendign - eigentlich nicht nötig?
            } elseif(strtolower($this->data['payment_status']) == 'pending') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Processed - wann kommt das ?
            } elseif(strtolower($this->data['payment_status']) == 'processed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            }
          }

Evtl. liegen/lagen die Probleme ja an dem zweiten Problem welches ich in vorliegendem Thread hier gepostet hatte. Hat jemand den Status für PAYPAL_ORDER_STATUS_SUCCESS_ID mit der ID 1 gesetzt kommt es zu Unstimmigkeiten weil die ID 1 zweimal vorkommt/vorkam.
[...]

Hi,

in der 2.00 sieht die Funktion so aus:

Code: PHP  [Auswählen]
    function callback_process($data,$charset) {
      // Keine Session da !
      // Stand: 29.06.2011
      global $_GET;
      $this->data = $data;
      //$this->_logTrans($data);
           
      $xtc_order_id=(int)substr($this->data['invoice'],strlen(PAYPAL_INVOICE));
      if(isset($xtc_order_id) && is_numeric($xtc_order_id) && ($xtc_order_id > 0)) {
        // order suchen
        $order_query = xtc_db_query("SELECT currency, currency_value, orders_status
                                    FROM "
. TABLE_ORDERS . "
                                    WHERE orders_id = '"
. xtc_db_prepare_input($xtc_order_id) . "'");
        if(xtc_db_num_rows($order_query) > 0) {
          $orders_status = xtc_db_fetch_array($order_query);
          // order gefunden
          $ipn_charset=xtc_db_prepare_input($this->data['charset']);
          $ipn_data = array();
          $ipn_data['reason_code'] = xtc_db_prepare_input($this->data['reason_code']);
          $ipn_data['xtc_order_id'] = xtc_db_prepare_input($xtc_order_id);
          $ipn_data['payment_type'] = xtc_db_prepare_input($this->data['payment_type']);
          $ipn_data['payment_status'] = xtc_db_prepare_input($this->data['payment_status']);
          $ipn_data['pending_reason'] = xtc_db_prepare_input($this->data['pending_reason']);
          $ipn_data['invoice'] = xtc_db_prepare_input($this->data['invoice']);
          $ipn_data['mc_currency'] = xtc_db_prepare_input($this->data['mc_currency']);
          $ipn_data['first_name'] = xtc_db_prepare_input($this->IPNdecode($this->data['first_name'],$ipn_charset,$charset));
          $ipn_data['last_name'] = xtc_db_prepare_input($this->IPNdecode($this->data['last_name'],$ipn_charset,$charset));
          $ipn_data['address_name'] = xtc_db_prepare_input($this->IPNdecode($this->data['address_name'],$ipn_charset,$charset));
          $ipn_data['address_street'] = xtc_db_prepare_input($this->IPNdecode($this->data['address_street'],$ipn_charset,$charset));
          $ipn_data['address_city'] = xtc_db_prepare_input($this->IPNdecode($this->data['address_city'],$ipn_charset,$charset));
          $ipn_data['address_state'] = xtc_db_prepare_input($this->IPNdecode($this->data['address_state'],$ipn_charset,$charset));
          $ipn_data['address_zip'] = xtc_db_prepare_input($this->data['address_zip']);
          $ipn_data['address_country'] = xtc_db_prepare_input($this->IPNdecode($this->data['address_country'],$ipn_charset,$charset));
          $ipn_data['address_status'] = xtc_db_prepare_input($this->data['address_status']);
          $ipn_data['payer_email'] = xtc_db_prepare_input($this->data['payer_email']);
          $ipn_data['payer_id'] = xtc_db_prepare_input($this->data['payer_id']);
          $ipn_data['payer_status'] = xtc_db_prepare_input($this->data['payer_status']);
          $ipn_data['payment_date'] = xtc_db_prepare_input($this->datetime_to_sql_format($this->data['payment_date']));
          $ipn_data['business'] = xtc_db_prepare_input($this->IPNdecode($this->data['business'],$ipn_charset,$charset));
          $ipn_data['receiver_email'] = xtc_db_prepare_input($this->data['receiver_email']);
          $ipn_data['receiver_id'] = xtc_db_prepare_input($this->data['receiver_id']);
          $ipn_data['txn_id'] = xtc_db_prepare_input($this->data['txn_id']);
          $ipn_data['txn_type']= $this->ipn_determine_txn_type($this->data['txn_type']);
          $ipn_data['parent_txn_id'] = xtc_db_prepare_input($this->data['parent_txn_id']);
          $ipn_data['mc_gross'] = xtc_db_prepare_input($this->data['mc_gross']);
          $ipn_data['mc_fee'] = xtc_db_prepare_input($this->data['mc_fee']);
          $ipn_data['mc_shipping'] = xtc_db_prepare_input($this->data['mc_shipping']);
          $ipn_data['payment_gross'] = xtc_db_prepare_input($this->data['payment_gross']);
          $ipn_data['payment_fee'] = xtc_db_prepare_input($this->data['payment_fee']);
          $ipn_data['notify_version'] = xtc_db_prepare_input($this->data['notify_version']);
          $ipn_data['verify_sign'] = xtc_db_prepare_input($this->data['verify_sign']);
          $ipn_data['num_cart_items'] = xtc_db_prepare_input($this->data['num_cart_items']);
          if($ipn_data['num_cart_items']>1) {
            $verspos=$ipn_data['num_cart_items'];
            for($p=1;$p<=$verspos;$p++) {
              if($this->data['item_name'.$p] == substr(SUB_TITLE_OT_DISCOUNT,0,127) || $this->data['item_name'.$p] == substr(PAYPAL_GS,0,127) || $this->data['item_name'.$p] == "Handling" || $this->data['item_name'.$p] == substr(PAYPAL_TAX,0,127) || $this->data['item_name'.$p] == "Differenz" ) {
                // Artikel Nummer aus den Details f¸r Sonderzeilen
                $ipn_data['num_cart_items']--;
              }
              if($this->data['item_name'.$p] == substr(SHIPPING_COSTS,0,127)) {
                // Versandkosten
                $ipn_data['mc_shipping']=$this->data['mc_gross_'.$p];
                $ipn_data['num_cart_items']--;
              }
            }
          }
          $_transQuery = "SELECT paypal_ipn_id FROM ".TABLE_PAYPAL." WHERE txn_id = '".$ipn_data['txn_id']."'";
          $_transQuery = xtc_db_query($_transQuery);
          $_transQuery = xtc_db_fetch_array($_transQuery);
          if($_transQuery['paypal_ipn_id']!='') {
            $insert_id = $_transQuery['paypal_ipn_id'];
            $sql_data_array = array('payment_status' => $ipn_data['payment_status'],
                          'pending_reason' => $ipn_data['pending_reason'],
                          'payer_email' => $ipn_data['payer_email'],
                          'num_cart_items' => $ipn_data['num_cart_items'],
                          'mc_fee' => $ipn_data['mc_fee'],
                          'mc_shipping' => $ipn_data['mc_shipping'],
                          'address_name' => $ipn_data['address_name'],
                          'address_street' => $ipn_data['address_street'],
                          'address_city' => $ipn_data['address_city'],
                          'address_state' => $ipn_data['address_state'],
                          'address_zip' => $ipn_data['address_zip'],
                          'address_country' => $ipn_data['address_country'],
                          'address_status' => $ipn_data['address_status'],
                          'payer_status' => $ipn_data['payer_status'],
                          'receiver_email' => $ipn_data['receiver_email'],
                          'last_modified ' => 'now()');
            xtc_db_perform(TABLE_PAYPAL, $sql_data_array, 'update', "paypal_ipn_id = '".(int) $insert_id."'");
          } else {
            $ipn_data['date_added']='now()';
            $ipn_data['last_modified']='now()';
            xtc_db_perform(TABLE_PAYPAL,$ipn_data);
            $insert_id = xtc_db_insert_id();
          }
          $paypal_order_history = array('paypal_ipn_id' => $insert_id,
                                        'txn_id' => $ipn_data['txn_id'],
                                        'parent_txn_id' => $ipn_data['parent_txn_id'],
                                        'payment_status' => $ipn_data['payment_status'],
                                        'pending_reason' => $ipn_data['pending_reason'],
                                        'mc_amount' => $ipn_data['mc_gross'],
                                        'date_added' => 'now()');
          xtc_db_perform(TABLE_PAYPAL_STATUS_HISTORY,$paypal_order_history);
          $crlf = "\n";
          $comment_status = xtc_db_prepare_input($this->data['payment_status']) . ' ' . xtc_db_prepare_input($this->data['mc_gross']) . xtc_db_prepare_input($this->data['mc_currency']) . $crlf;
          $comment_status .= ' ' . xtc_db_prepare_input($this->data['first_name']) . ' ' . xtc_db_prepare_input($this->data['last_name']) . ' ' . xtc_db_prepare_input($this->data['payer_email']);
          if(isset($this->data['payer_status'])) {
            $comment_status .= ' is ' . xtc_db_prepare_input($this->data['payer_status']);
          }
          $comment_status .= '.' . $crlf;
          if(isset($this->data['test_ipn']) && is_numeric($this->data['test_ipn']) && ($_POST['test_ipn'] > 0)) {
            $comment_status .='(Sandbox-Test Mode)'.$crlf;
          }
          $comment_status .= 'Total=' . xtc_db_prepare_input($this->data['mc_gross']) . xtc_db_prepare_input($this->data['mc_currency']);
          if(isset($this->data['pending_reason'])) {
            $comment_status .= $crlf . ' Pending Reason=' . xtc_db_prepare_input($this->data['pending_reason']);
          }
          if(isset($this->data['reason_code'])) {
            $comment_status .= $crlf . ' Reason Code=' . xtc_db_prepare_input($this->data['reason_code']);
          }
          $comment_status .= $crlf . ' Payment=' . xtc_db_prepare_input($this->data['payment_type']);
          $comment_status .= $crlf . ' Date=' . xtc_db_prepare_input($this->data['payment_date']);
          if(isset($this->data['parent_txn_id'])) {
            $comment_status .= $crlf . ' ParentID=' . xtc_db_prepare_input($this->data['parent_txn_id']);
          }
          $comment_status .= $crlf . ' ID=' . xtc_db_prepare_input($_POST['txn_id']);
          //Set status for default (Pending)
          $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
          $parameters = 'cmd=_notify-validate';
          foreach($this->data as $key => $value) {
            $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
          }
          //$this->_logTransactions($parameters);
          // 08.01.2008 auch ohne cURL
          $mit_curl=0;
          if(function_exists('curl_init')) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $this->IPN_URL);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            $result = curl_exec($ch);
            if(!curl_errno($ch)) {
              $mit_curl=1;
            }
            curl_close($ch);
          }
          // cURL fehlt oder ist fehlgeschlagen
          if($mit_curl==0) {
            $request_post = array(
                            'http'=>array(
                            'method'=>'POST',
                            'header'=>"Content-type: application/x-www-form-urlencoded\r\n",
                            'content'=>$parameters));
            $request = stream_context_create($request_post);
            $result= file_get_contents($this->IPN_URL, false, $request);
          }
          if(strtoupper($result) == 'VERIFIED' || $result == '1') {
            // Steht auf Warten
            if(strtolower($this->data['payment_status']) == 'completed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            //Set status for Denied, Failed
            } elseif((strtolower($this->data['payment_status']) == 'denied') OR (strtolower($this->data['payment_status']) == 'failed')) {
              $order_status_id = PAYPAL_ORDER_STATUS_REJECTED_ID;
            //Set status for Reversed
            } elseif(strtolower($this->data['payment_status']) == 'reversed') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Canceled-Reversal
            } elseif(strtolower($this->data['payment_status']) == 'canceled-reversal') {
              $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
            //Set status for Refunded
            } elseif(strtolower($this->data['payment_status']) == 'refunded') {
              $order_status_id = $orders_status['orders_status']; // don´t change status
            //Set status for Pendign - eigentlich nicht nˆtig?
            } elseif(strtolower($this->data['payment_status']) == 'pending') {
              $order_status_id = PAYPAL_ORDER_STATUS_PENDING_ID;
            //Set status for Processed - wann kommt das ?
            } elseif(strtolower($this->data['payment_status']) == 'processed') {
              if(PAYPAL_ORDER_STATUS_SUCCESS_ID > 0) {
                $order_status_id = PAYPAL_ORDER_STATUS_SUCCESS_ID;
              }
            }
          } else {
            $order_status_id = PAYPAL_ORDER_STATUS_REJECTED_ID;
            $error_reason = 'Received INVALID responce but invoice and Customer matched.';
          }
          $xtc_order_id=(int)substr($this->data['invoice'],strlen(PAYPAL_INVOICE));
          xtc_db_query("UPDATE " . TABLE_ORDERS . "
                        SET orders_status = '"
. $order_status_id . "', last_modified = now()
                        WHERE orders_id = '"
. xtc_db_prepare_input($xtc_order_id) . "'");
          $sql_data_array = array('orders_id' => xtc_db_prepare_input($xtc_order_id),
                                  'orders_status_id' => $order_status_id,
                                  'date_added' => 'now()',
                                  'customer_notified' => '0',
                                  'comments' => 'PayPal IPN ' . $comment_status . '');
          xtc_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
        } else {
          $error_reason = 'IPN-Fehler: Keine Order Nr.=' . xtc_db_prepare_input($this->data['invoice']) . ' mit Kunden=' . (int) $this->data['custom'] . ' gefunden.';
        }
      } else {
        $error_reason = 'IPN-Fehler: Keine Order gefunden zu den empfangenen Daten.';
      }
      if(xtc_not_null(EMAIL_SUPPORT_ADDRESS) && strlen($error_reason)) {
        $email_body = $error_reason . "\n\n".'<br>';
        $email_body .= $_SERVER['REQUEST_METHOD'] . " - " . $_SERVER['REMOTE_ADDR'] . " - " . $_SERVER['HTTP_REFERER'] . " - " . $_SERVER['HTTP_ACCEPT'] . "\n\n".'<br>';
        $email_body .= '$_POST:' . "\n\n".'<br>';
        foreach($this->data as $key => $value) {
          $email_body .= $key . '=' . $value . "\n".'<br>';
        }
        $email_body .= "\n" . '$_GET:' . "\n\n".'<br>';
        foreach($_GET as $key => $value) {
          $email_body .= $key . '=' . $value . "\n".'<br>';
        }
        xtc_php_mail(EMAIL_BILLING_ADDRESS,
                     EMAIL_BILLING_NAME,
                     EMAIL_SUPPORT_ADDRESS,
                     EMAIL_SUPPORT_ADDRESS,
                     '',
                     EMAIL_BILLING_ADDRESS,
                     EMAIL_BILLING_NAME,
                     '',
                     '',
                     'PayPal IPN Invalid Process',
                     $email_body,
                     $email_body);
      }
    }

Gruss Gerhard

Offline GTB

  • modified Team
  • *****
  • Gravatar
  • Beiträge: 5.271
  • Geschlecht: Männlich
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #23 am: 21. Juli 2015, 14:57:40 »
[...]
@GTB
In diesem Zusammenhang, GTB, fällt mir auf, daß deine Lösung (hier gepostet) nicht korrekt sein kann.

Begründung:

Mit

Code: PHP  [Auswählen]
    $statuses_array = array (array ('id' => DEFAULT_ORDERS_STATUS_ID, 'text' => TEXT_DEFAULT));

setzt du den Deafult-Wert im Dropdown auf den orders_status welcher als Default, also als Standard in den Bestellstatus eingestellt ist.
Da jedoch in der Funktion xtc_cfg_pull_down_order_statuses() in /admin/includes/functions/general.php alle Status aus der Tabelle orders_status ausgelesen und in das Array für das Dropdown geschrieben werden, auch der orders_status der auf "Standard" gesetzt wurde, kommt trotzdem wieder eine ID zweimal vor.
Richtig ?
[...]

Dass eine ID 2x vorkommt ist mal grundsätzlich nicht falsch. In der von mir geposteten Funktion für PayPal wird der Bestellstatus nicht mehr verändert, wenn eine Rückzahlung an den Kunden erfolgt.

Es geht ja darum, dass ich in einem Zahlmodul sage, dass die Bestellung den Standard Bestellstatus bekommt. Wenn ich den aber nun in den Bestellstatus Optionen ändere, dann sollten auch die Zahlmodule geändert werden.

Gruss Gerhard

Offline noRiddle

  • Experte
  • *****
  • Beiträge: 9.945
  • Geschlecht: Männlich
    • Teile Beitrag
    • Webdesign Bonn - Köln
Re: PayPal order_status automatisch setzen Problem
« Antwort #24 am: 22. Juli 2015, 16:22:56 »
...
Dass eine ID 2x vorkommt ist mal grundsätzlich nicht falsch.
...

Naja, doch, weil

Zitat von: noRiddle
Folge:
Wir haben zweimal die ID 1 im Pulldown und folglich auch zwei Möglichkeiten die ID 1 im POST-Array an PHP und somit die DB zu senden.
Das äußert sich insbesondere negativ wenn man den ersten Status in der PayPal-Config für irgendetwas auswählen möchte, denn wenn zwei option-Werte im select-Menu auf selected="selected" stehen, wird das zweite angezeigt, auch wenn man das erste gewählt und gespeichert hat.

Was meinst du mit folgendem ?
"Wenn ich den aber nun in den Bestellstatus Optionen ändere,..."

Ich möchte ja nicht Optionen der Bestellstatus ändern sondern ich möchte, daß keine ID im Dropdown zweimal vorkommt.  Das hat ansonsten keinerlei Einfluß auf alle anderen Zusammenhänge.
Ich meine:
Würde man den Fix machen wie du ihn vorgeschlagen hast müsste man es imho so machen (/admin/includes/functions/general.php):
Code: PHP  [Auswählen]
  function xtc_cfg_pull_down_order_statuses($order_status_id, $key = '') {
    $name = (($key) ? 'configuration['.$key.']' : 'configuration_value');
    //$statuses_array = array (array ('id' => '1', 'text' => TEXT_DEFAULT));
    $statuses_array = array (array ('id' => DEFAULT_ORDERS_STATUS_ID, 'text' => TEXT_DEFAULT));  // Vorschlag GTB
    $statuses_query = xtc_db_query("select orders_status_id, orders_status_name from ".TABLE_ORDERS_STATUS." where language_id = '".(int)$_SESSION['languages_id']."' order by orders_status_name");
    while ($statuses = xtc_db_fetch_array($statuses_query)) {
      unset($statuses[DEFAULT_ORDERS_STATUS_ID]); // Vorschlag noRiddle
      $statuses_array[] = array ('id' => $statuses['orders_status_id'], 'text' => $statuses['orders_status_name']);
    }
    return xtc_draw_pull_down_menu($name, $statuses_array, $order_status_id);
  }

So würde der Status mit der ID DEFAULT_ORDERS_STATUS_ID nicht zweimal im Dropdown vorkommen.
Übersehe ich etwas ?

Gruß,
noRiddle

Offline web0null

  • Experte
  • *****
  • Beiträge: 1.998
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #25 am: 22. Juli 2015, 17:49:12 »
Ich mische mich mal kurz ein :-D

1. Bin ich auch der Meinung, 2 gleiche ID´s haben in einem Dropdown nichts zu suchen.
2. Wenn ich die Problematik richtig verstanden habe...
...wäre mein Vorschlag,

Code: PHP  [Auswählen]
function xtc_cfg_pull_down_order_statuses($order_status_id, $key = '') {
    $name = (($key) ? 'configuration['.$key.']' : 'configuration_value');
    $statuses_query = xtc_db_query("select orders_status_id, orders_status_name from ".TABLE_ORDERS_STATUS." where language_id = '".(int)$_SESSION['languages_id']."' order by orders_status_name");
    $key = 1;
    while ($statuses = xtc_db_fetch_array($statuses_query)) {
      $default = $statuses['orders_status_id'] == DEFAULT_ORDERS_STATUS_ID ? ' (' . TEXT_DEFAULT . ')' : '';
      $statuses_array[($default ? 0 : $key)] = array('id' => $statuses['orders_status_id'], 'text' => $statuses['orders_status_name'] . $default);
      $key ++;
    }
    ksort($statuses_array);
    return xtc_draw_pull_down_menu($name, $statuses_array, $order_status_id);
  }
 

Wenn ich es nicht richtig verstanden habe, wäre es trotzdem eine Erweiterung für dieses Dropdown.

Gruß

Offline GTB

  • modified Team
  • *****
  • Gravatar
  • Beiträge: 5.271
  • Geschlecht: Männlich
    • Teile Beitrag
Re: PayPal order_status automatisch setzen Problem
« Antwort #26 am: 05. August 2015, 14:00:32 »
Hi,

hier die Funktion wie sie nun im SVN ist:

Code: PHP  [Auswählen]
  /**
   * xtc_cfg_pull_down_order_statuses()
   *
   * @param mixed $order_status_id
   * @param string $key
   * @return
   */

  function xtc_cfg_pull_down_order_statuses($order_status_id, $key = '') {
    $name = (($key) ? 'configuration['.$key.']' : 'configuration_value');
    $statuses_array = array();
    $statuses_query = xtc_db_query("SELECT orders_status_id,
                                           orders_status_name
                                      FROM "
.TABLE_ORDERS_STATUS."
                                     WHERE language_id = '"
.(int)$_SESSION['languages_id']."'
                                  ORDER BY sort_order"
);
    while ($statuses = xtc_db_fetch_array($statuses_query)) {
      $statuses_array[] = array ('id' => $statuses['orders_status_id'], 'text' => $statuses['orders_status_name'] . (($statuses['orders_status_id'] == DEFAULT_ORDERS_STATUS_ID) ? ' ('.TEXT_DEFAULT.')' : ''));
    }
    return xtc_draw_pull_down_menu($name, $statuses_array, $order_status_id);
  }
 

Gruss Gerhard

Offline Fakrae

  • Viel Schreiber
  • *****
  • Beiträge: 997
    • Teile Beitrag
    • Futterkrämerei
Re: PayPal order_status automatisch setzen Problem
« Antwort #27 am: 06. Januar 2016, 19:17:57 »
Von mir eine Anmerkung: Bei mir wurden die Bestellstati ebenfalls nicht geändert, obwohl das Serverlog einen Aufruf der ipn.php vermerkt. Ebenfalls hat die weiter vorne gepostete Variante (mit Errorlogging in einer Datei) der ipn.php keinerlei Dateien erzeugt.
Das Problem lag in meinem Fall am Affiliate-Modul (http://www.modified-shop.org/forum/index.php?topic=3720.0), das ungesetzte Sessionvariablen in der (auch von der ipn.php eingebundenen) /lang/german/german.php verwendet hat.
Für alle weiteren als Hilfe bei der Fehlersuche:
In der ipn.php direkt nach
Code: PHP  [Auswählen]
include('../../includes/application_top_callback.php');
das hier einfügen:
Code: PHP  [Auswählen]
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
und anschließend direkt die /callback/paypal/ipn.php aufrufen. Wahrscheinlich wird dort ein Fehler auftauchen der behoben werden muss.

Den "Hack" von NoRiddle würde ich aus den von ChristianRothe genannten Gründen NICHT implementieren.


Teile per facebook Teile per linkedin Teile per twitter