1.9.0.1 CE Programmgesteuert autorisieren, dann erfassen


7

Ich muss die Autorisierung autorisieren, einige API-Aufrufe von Drittanbietern ausführen und basierend auf den Ergebnissen dieser Aufrufe die Autorisierung entweder erfassen oder abbrechen.

Derzeit verwende ich nur authorize.net, aber ich möchte, dass dies für so viele Zahlungsgateways wie möglich möglich ist. Ich habe authorize.net auf Nur autorisieren gesetzt. Mein Beobachter wird für das Ereignis sales_order_payment_place_end ausgeführt.

Folgendes mache ich in meinem Beobachter (noch nicht abstrahiert, brauche noch einen Proof of Concept):

if(/*API calls return ok*/)
{
    $observer->getPayment()->getMethod_instance()->capture($observer->getPayment(),$observer->getPayment()->getAmount());
}
else
{
    Mage::dispatchEvent('Mainstreethost_MicrosOrder_Failure');
    $observer->getPayment()->getMethod_instance()->cancel($observer->getPayment());
}

Wenn ich capture () aufrufe, wird überprüft, ob die Zahlung vorautorisiert wurde. Dies versuchen wir zu erreichen:

public function capture(Varien_Object $payment, $amount)
{
    if ($amount <= 0) {
        Mage::throwException(Mage::helper('paygate')->__('Invalid amount for capture.'));
    }
    $this->_initCardsStorage($payment);
    if ($this->_isPreauthorizeCapture($payment)) {
        $this->_preauthorizeCapture($payment, $amount);
    } else if ($this->isPartialAuthorization($payment)) {
        $this->_partialAuthorization($payment, $amount, self::REQUEST_TYPE_AUTH_CAPTURE);
    } else {
        $this->_place($payment, $amount, self::REQUEST_TYPE_AUTH_CAPTURE);
    }
    $payment->setSkipTransactionCreation(true);
    return $this;
}

_isPreauthorizedCapture () versucht, $ lastTransaction zuzuweisen:

protected function _isPreauthorizeCapture($payment)
{
    if ($this->getCardsStorage()->getCardsCount() <= 0) {
        return false;
    }
    foreach($this->getCardsStorage()->getCards() as $card) {
        $lastTransaction = $payment->getTransaction($card->getLastTransId());
        if (!$lastTransaction
            || $lastTransaction->getTxnType() != Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH
        ) {
            return false;
        }
    }
    return true;
}

$ lastTransaction gibt immer false zurück. Dies liegt daran, dass $ payment-> getTransaction () schließlich _lookupTransaction () aufruft:

protected function _lookupTransaction($txnId, $txnType = false)
{
    if (!$txnId) {
        if ($txnType && $this->getId()) {
            $collection = Mage::getModel('sales/order_payment_transaction')->getCollection()
                ->setOrderFilter($this->getOrder())
                ->addPaymentIdFilter($this->getId())
                ->addTxnTypeFilter($txnType)
                ->setOrder('created_at', Varien_Data_Collection::SORT_ORDER_DESC)
                ->setOrder('transaction_id', Varien_Data_Collection::SORT_ORDER_DESC);
            foreach ($collection as $txn) {
                $txn->setOrderPaymentObject($this);
                $this->_transactionsLookup[$txn->getTxnId()] = $txn;
                return $txn;
            }
        }
        return false;
    }
    if (isset($this->_transactionsLookup[$txnId])) {
        return $this->_transactionsLookup[$txnId];
    }
    $txn = Mage::getModel('sales/order_payment_transaction')
        ->setOrderPaymentObject($this)
        ->loadByTxnId($txnId);
    if ($txn->getId()) {
        $this->_transactionsLookup[$txnId] = $txn;
    } else {
        $this->_transactionsLookup[$txnId] = false;
    }
    return $this->_transactionsLookup[$txnId];
}

Diese Methode wird jetzt zweimal aufgerufen, einmal zur Autorisierung und einmal, wenn ich im Beobachter capture () aufrufe. Der Autorisierungsaufruf springt zu dieser Zeile:

$txn = Mage::getModel('sales/order_payment_transaction')
        ->setOrderPaymentObject($this)
        ->loadByTxnId($txnId);

Und ein Transaktionsobjekt mit Nulldaten zurückgeben. Warum passiert das?

Da die Methode loadObjectByTxnId () in Mage_Sales_Model_Resource_Order_Payment_Transaction $ data false zuweist:

public function loadObjectByTxnId(Mage_Sales_Model_Order_Payment_Transaction $transaction, $orderId, $paymentId, 
    $txnId)
{
    $select = $this->_getLoadByUniqueKeySelect($orderId, $paymentId, $txnId);
    $data   = $this->_getWriteAdapter()->fetchRow($select);
    $transaction->setData($data);
    $this->unserializeFields($transaction);
    $this->_afterLoad($transaction);
}

$ data hydratisiert das $ txn-Klassenobjekt in _lookupTransaction ()! Falls Sie sich fragen, ist dies die eigentliche SQL-Abfrage:

SELECT `sales_payment_transaction`.* FROM `sales_payment_transaction` WHERE (order_id = '38') AND (payment_id = '38') AND (txn_id = '2217720876')

Dieser Tisch ist übrigens immer leer.

Aber warte! Es geht so viel mehr schief!

Beim zweiten Aufruf (Capture-Aufruf) von _lookupTransaction () wird Folgendes ausgelöst:

if (isset($this->_transactionsLookup[$txnId])) {
    return $this->_transactionsLookup[$txnId];
}

Dieser Wert ist jedoch falsch, was bedeutet, dass _isPreauthorizeCapture () false zurückgibt und dann capture () einen Fehler auslöst, der besagt, dass ich die Kreditkartennummer haben muss.

Antworten:


1

Die Lösung, die ich gefunden habe, war, dass ich keine Rechnung erstellt und registriert habe, bevor ich versucht habe, sie zu erfassen / zu stornieren. Ich musste auch die Transaktion und die Auftragszustände abwickeln:

$invoice = Mage::getModel('sales/Service_Order', $this->getOrder())->prepareInvoice();

if($isCapture)
{
    $invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_ONLINE);
    $invoice->register();
}
else
{
    $invoice->void();
}

$transactionSave = Mage::getModel('core/Resource_Transaction')
            ->addObject($invoice)
            ->addObject($invoice->getOrder());
$transactionSave->save();


if ($isCapture)
{
    $order->setStatus(Mage_Sales_Model_Order::STATE_CLOSED);
}
else
{
    $order->setState(Mage_Sales_Model_Order::STATE_CANCELED);
    $order->setStatus(Mage_Sales_Model_Order::STATE_CANCELED);
}

$order->save();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.