Ich habe festgestellt, dass Paypal-Bestellungen auf meiner Website nach dem Zufallsprinzip storniert werden, obwohl der Kunde die Transaktion bezahlt und abgeschlossen hat. Zahlungsinformationen werden ausgefüllt und ich kann auch die IPN-registrierte Nachricht sehen.
- 2 Apr 2017 09: 24: 21 | Abgebrochen
- Kundenbenachrichtigung Nicht zutreffend
- 2. April 2017 08: 44: 17 | Ausstehend
- Kundenbenachrichtigung Nicht zutreffend
- IPN "Abgeschlossen". Registrierte Benachrichtigung über den erfassten Betrag von £ 30,95. Transaktions-ID: ############# 2 Apr 2017 08: 43: 23 | Ausstehende Zahlung
- Kunde nicht benachrichtigt
Dieser Auszug aus dem Kommentarverlauf zeigt 08:43, dass sich die Bestellung im Status "Ausstehende Zahlung" befand. Dann bestätigte 8,44 ipn die Erfassung der Zahlung. Die Bestellung steht noch aus. Ich habe Code geschrieben, um die automatische Rechnung zu stoppen.
Aber 40 Minuten später wurde abgesagt. Der Kunde hat nichts storniert. Die Zahlung erfolgt in Paypal. Wir auch nicht. Warum sollte das System dies tun?
Aktualisieren:
Hier ist ein weiteres Beispiel, bei dem es 2 Minuten und 52 Sekunden später abgebrochen wurde.
8 Dec 2017 00: 00: 51 | Abgebrochene Kundenbenachrichtigung nicht anwendbar 7 Dec 2017 23: 57: 59 | Ausstehende Kundenbenachrichtigung nicht anwendbar IPN "Abgeschlossen". Registrierte Benachrichtigung über den erfassten Betrag von £ xx.xx. Transaktions-ID: "xxxxxxxxxxx". 7. Dezember 2017 23: 57: 59 | Ausstehender Kunde benachrichtigt Benachrichtigter Kunde 7. Dezember 2017 23: 56: 56 | Ausstehende Zahlung Kunde nicht benachrichtigt
Mein Code zum Stoppen der automatischen Rechnungsstellung lautet wie folgt:
config.xml:
<?xml version="1.0"?>
<config>
<modules>
<Wfh_DisableAutoInvoice>
<version>0.1.0</version>
</Wfh_DisableAutoInvoice>
</modules>
<global>
<models>
<disableautoinvoice>
<class>Wfh_DisableAutoInvoice_Model</class>
<resourceModel>disableautoinvoice_mysql4</resourceModel>
</disableautoinvoice>
<sales>
<rewrite>
<order_payment>Wfh_DisableAutoInvoice_Model_Sales_Order_Payment</order_payment>
</rewrite>
</sales>
</models>
</global>
</config>
Meine Zahlung.php
<?php
class Wfh_DisableAutoInvoice_Model_Sales_Order_Payment extends Mage_Sales_Model_Order_Payment
{
/**
* Authorize or authorize and capture payment on gateway, if applicable
* This method is supposed to be called only when order is placed
*
* @return Mage_Sales_Model_Order_Payment
*/
public function place()
{
Mage::dispatchEvent('sales_order_payment_place_start', array('payment' => $this));
$order = $this->getOrder();
$this->setAmountOrdered($order->getTotalDue());
$this->setBaseAmountOrdered($order->getBaseTotalDue());
$this->setShippingAmount($order->getShippingAmount());
$this->setBaseShippingAmount($order->getBaseShippingAmount());
$methodInstance = $this->getMethodInstance();
$methodInstance->setStore($order->getStoreId());
$orderState = Mage_Sales_Model_Order::STATE_NEW;
$stateObject = new Varien_Object();
/**
* Do order payment validation on payment method level
*/
$methodInstance->validate();
$action = $methodInstance->getConfigPaymentAction();
if ($action) {
if ($methodInstance->isInitializeNeeded()) {
/**
* For method initialization we have to use original config value for payment action
*/
$methodInstance->initialize($methodInstance->getConfigData('payment_action'), $stateObject);
} else {
$orderState = Mage_Sales_Model_Order::STATE_NEW;
switch ($action) {
case Mage_Payment_Model_Method_Abstract::ACTION_ORDER:
$this->_order($order->getBaseTotalDue());
break;
case Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE:
$this->_authorize(true, $order->getBaseTotalDue()); // base amount will be set inside
$this->setAmountAuthorized($order->getTotalDue());
break;
case Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE:
$this->setAmountAuthorized($order->getTotalDue());
$this->setBaseAmountAuthorized($order->getBaseTotalDue());
$this->capture(null);
break;
default:
break;
}
}
}
$this->_createBillingAgreement();
$orderIsNotified = null;
if ($stateObject->getState() && $stateObject->getStatus()) {
$orderState = $stateObject->getState();
$orderStatus = $stateObject->getStatus();
$orderIsNotified = $stateObject->getIsNotified();
} else {
$orderStatus = $methodInstance->getConfigData('order_status');
if (!$orderStatus) {
$orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
} else {
// check if $orderStatus has assigned a state
$states = $order->getConfig()->getStatusStates($orderStatus);
if (count($states) == 0) {
$orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
}
}
}
$isCustomerNotified = (null !== $orderIsNotified) ? $orderIsNotified : $order->getCustomerNoteNotify();
$message = $order->getCustomerNote();
// add message if order was put into review during authorization or capture
if ($order->getState() == Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW) {
if ($message) {
$order->addStatusToHistory($order->getStatus(), $message, $isCustomerNotified);
}
} elseif ($order->getState() && ($orderStatus !== $order->getStatus() || $message)) {
// add message to history if order state already declared
$order->setState($orderState, $orderStatus, $message, $isCustomerNotified);
} elseif (($order->getState() != $orderState) || ($order->getStatus() != $orderStatus) || $message) {
// set order state
$order->setState($orderState, $orderStatus, $message, $isCustomerNotified);
}
Mage::dispatchEvent('sales_order_payment_place_end', array('payment' => $this));
return $this;
}
/**
* Capture the payment online
* Does not create invoice automatically for order
* Updates transactions hierarchy, if required
* Updates payment totals, updates order status and adds proper comments
*
* TODO: eliminate logic duplication with registerCaptureNotification()
*
* @return Mage_Sales_Model_Order_Payment
* @throws Mage_Core_Exception
*/
public function capture($invoice)
{
$invoice = null;
$order = $this->getOrder();
$amountToCapture = $this->_formatAmount($order->getBaseGrandTotal());
$paidWorkaround = (float)$amountToCapture;
$this->_isCaptureFinal($paidWorkaround);
$this->_generateTransactionId(
Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
$this->getAuthorizationTransaction()
);
Mage::dispatchEvent('sales_order_payment_capture', array('payment' => $this, 'invoice' => $invoice));
$status = true;
if (!$this->getIsTransactionPending()) {
// attempt to capture: this can trigger "is_transaction_pending"
$this->getMethodInstance()->setStore($order->getStoreId())->capture($this, $amountToCapture);
$transaction = $this->_addTransaction(
Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
$invoice,
true
);
if ($this->getIsTransactionPending()) {
$message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amountToCapture));
$state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
if ($this->getIsFraudDetected()) {
$status = Mage_Sales_Model_Order::STATUS_FRAUD;
}
} else { // normal online capture: invoice is marked as "paid"
$message = Mage::helper('sales')->__('Captured amount of %s online.', $this->_formatPrice($amountToCapture));
$state = Mage_Sales_Model_Order::STATE_NEW;
$this->_updateTotals(array('base_amount_paid_online' => $amountToCapture));
}
if ($order->isNominal()) {
$message = $this->_prependMessage(Mage::helper('sales')->__('Nominal order registered.'));
} else {
$message = $this->_prependMessage($message);
$message = $this->_appendTransactionToMessage($transaction, $message);
}
$order->setState($state, $status, $message);
return $this;
}
Mage::throwException(
Mage::helper('sales')->__('The transaction "%s" cannot be captured yet.', $amountToCapture)
);
}
/**
* Process a capture notification from a payment gateway for specified amount
* Does not create an invoice automatically if the amount if the amount covers the order base grand total completely
* Updates transactions hierarchy, if required
* Prevents transaction double processing
* Updates payment totals, updates order status and adds proper comments
*
* TODO: eliminate logic duplication with capture()
*
* @param float $amount
* @param bool $skipFraudDetection
* @return Mage_Sales_Model_Order_Payment
*/
public function registerCaptureNotification($amount, $skipFraudDetection = false)
{
$this->_generateTransactionId(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE,
$this->getAuthorizationTransaction()
);
$order = $this->getOrder();
$amount = (float)$amount;
$invoice = null;
// register new capture
if (!$invoice) {
$isSameCurrency = $this->_isSameCurrency();
if (!$isSameCurrency && !$this->_isCaptureFinal($amount)) {
if (!$skipFraudDetection || !$isSameCurrency) {
$this->setIsFraudDetected(true);
}
$this->_updateTotals(array('base_amount_paid_online' => $amount));
}
}
$status = true;
$letsEmail = false;
if ($this->getIsTransactionPending()) {
$message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
$state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
$letsEmail = true;
if ($this->getIsFraudDetected()) {
$message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
$status = Mage_Sales_Model_Order::STATUS_FRAUD;
$letsEmail = false;
}
} else {
$message = Mage::helper('sales')->__('Registered notification about captured amount of %s.', $this->_formatPrice($amount));
$state = Mage_Sales_Model_Order::STATE_NEW;
$letsEmail = true;
if ($this->getIsFraudDetected()) {
$state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
$message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount, $this->getCurrencyCode()));
$status = Mage_Sales_Model_Order::STATUS_FRAUD;
$letsEmail = false;
}
}
$transaction = $this->_addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE, $invoice, true);
$message = $this->_prependMessage($message);
$message = $this->_appendTransactionToMessage($transaction, $message);
$order->setState($state, $status, $message);
if ($letsEmail === true && !$order->getEmailSent()){
$order->queueNewOrderEmail()->addStatusHistoryComment(
Mage::helper('paypal')->__('Notified Customer')
)
->setIsCustomerNotified(true)
->save();
}
return $this;
}
}
?>
quelle
Antworten:
Wir haben dieses Problem gelegentlich auftreten
Nachdem ich die Paypal-Abbruchaktion mit einem Debug-Trace versehen habe, habe ich die folgenden Informationen erhalten:
Dies zeigt deutlich, dass die Abbruchaktion über das aufgerufen wurde
Mage_Paypal_StandardController
Dies ist also ein externer Anruf, um die Bestellung zu stornieren.
Wenn ich die eigentlichen Webserver-Protokolle finde, kann ich sehen, dass der Anruf tatsächlich von extern kam (Paypal).
Das Interessante daran ist, dass es sich um eine 302 (Weiterleitung) handelte.
Wenn ich diese Referrer-URL lade, wird eine Paypal-Anzeige angezeigt, für die die Sitzung abgelaufen ist.
Ich konnte auch feststellen, dass dies von einem iPad war. Ich habe nicht genug davon, um andere Geräte zu bestimmen, also könnte das Kniebeugen bedeuten.
Aus meiner Sicht gehe ich davon aus, dass diese Abbruchaktion von Paypal aus initiiert wird, wenn / wenn die Benutzersitzung auf der Paypal-Seite eine Zeitüberschreitung aufweist oder Probleme beim Aufrechterhalten der Sitzung während des Transaktionszeitraums aufgetreten sind.
Paypal handelt dann eine Stornierungsanfrage?
UPDATE: Trace festlegen:
Laut Kommentaranforderung habe ich hier die Ablaufverfolgung platziert. Wenn die Bestellung storniert wird, wird ein Kommentar in die Bestellhistorie / Kommentare zu dieser Stornierung eingefügt. Hier habe ich meinen Trace-Code eingefügt und so den Code-Pfad zurückverfolgt, bis ich diese Kommentareinfügung erreicht habe.
Es kann genauso gut in eine Protokolldatei verschoben werden.
Ich habe dafür ein kleines Modul erstellt:
Ich habe einfach das Kernmodul für Kundenaufträge neu geschrieben (beachten Sie, dass ein Umschreibungskonflikt entsteht, wenn ein anderes Modul eines Drittanbieters diese Klasse ebenfalls neu schreibt. In meinem Fall war dies kein Problem:
Im Modul config.xml
und dann in der Modellklasse:
quelle
Es könnte mit Paypal Express zusammenhängen, haben Sie das überprüft? Weitere Informationen finden Sie hier: /programming/4563732/paypal-orders-cancelling-automatically-in-magento
quelle
Durch die Integration von Magento in PayPal Express (nicht PayPal-Standard) können Benutzer die Produkte unseres Shops kaufen.
Es gibt jedoch zwei verschiedene Situationen: 1) Wenn der Kunde ein Paypal-Konto hat, kann er den Kaufvorgang ohne Probleme abschließen. 2) Wenn der Kunde jedoch kein Paypal-Konto hat oder es nicht verwenden möchte und die Produkte lieber mit seiner Kreditkarte ohne Verwendung der PayPal-Anmeldeinformationen kaufen möchte, wird der Vorgang wie folgt abgeschlossen Fehler: "Diese Zahlung kann derzeit nicht über Ihr Paypal-Konto verarbeitet werden."
Das Problem ist, dass der Verkäufer das Geld erhält, der Kunde jedoch genau das Gegenteil denkt.
Dieses Problem wurde vom PayPal-Supportteam behoben und bestätigt.
Das eigentliche Problem ist, dass während des Kaufvorgangs die Funktion DoExpressCheckoutPayment PayPal aufgerufen wird. Wenn der Kaufvorgang jedoch mit diesem Fehler abgeschlossen ist, wird ein Parameter namens successpageredirectrequested auf true gesetzt . Dieses Flag zeigt an, ob Sie den Kunden nach Abschluss der Transaktion zu PayPal umleiten müssen. Dies ist jedoch ein veraltetes PayPal-Verhalten und sollte nicht verwendet werden.
Da Magento die Funktion dieses Parameters verwendet, gibt PayPal diesen Fehler zurück , wenn er versucht, erneut zu PayPal umzuleiten (dies ist der Vorgang , bei dem successpageredirectrequested auf true gesetzt ist).
Wir können das Problem beheben, indem wir den Quellcode von Magento unter ändern
Einfach die Funktion ändern
public function placeOrderAction()
. Suchen Sie in dieser Funktion nach folgendem Code:// umleiten, wenn PayPal eine URL angegeben hat (z. B. zur Giropay Bank)
Wir müssen nur das "Wenn" kommentieren, einfach so:
Das reicht aus, um das Problem zu beheben. Dies ist jedoch kein aktueller Fix, und dies sollte von den Programmierern von Magento überprüft werden, um ihn in den neuen Versionen von Magento zu beheben.
quelle