1.9.0.1 CEはプログラムで承認してからキャプチャする


7

承認して、いくつかのサードパーティAPI呼び出しを行う必要があります。それらの呼び出しから何が返されるかに基づいて、承認を取得またはキャンセルします。

現在、authorize.netのみを使用していますが、できるだけ多くの支払いゲートウェイでこれを使用できるようにしたいと考えています。authorize.netをAuthorize Onlyに設定しました。私のオブザーバーはsales_order_payment_place_endイベントを実行します。

これが私のオブザーバーでやっていることです(まだ抽象化されていませんが、まだ概念実証が必要です)。

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());
}

capture()を呼び出すと、支払いが事前承認されたかどうかが確認されます。これは、私たちが達成しようとしていることです。

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()は$ lastTransactionを割り当てようとします:

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は常にfalseを返します。これは、$ payment-> getTransaction()が最終的に_lookupTransaction()を呼び出すためです。

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];
}

現在、このメソッドは2回呼び出されます。1回は認証のため、もう1回はオブザーバーでcapture()を呼び出すときに呼び出されます。承認呼び出しはこの行にスキップします:

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

そして、nullデータを含むトランザクションオブジェクトを返します。なぜこれが起こるのですか?

Mage_Sales_Model_Resource_Order_Payment_TransactionのメソッドloadObjectByTxnId()が$ dataをfalseに割り当てているため:

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は、_lookupTransaction()の$ txnクラスオブジェクトをハイドレートするものです!ご参考までに、これは実際のSQLクエリです。

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

ところで、そのテーブルは常に空です。

ちょっと待って!もっともっと失敗します!

_lookupTransaction()への2番目の呼び出し(キャプチャー呼び出し)で、これが作動した場合:

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

しかし、その値はfalseです。つまり、_isPreauthorizeCapture()がfalseを返し、capture()がエラーをスローして、クレジットカード番号が必要であることを通知します。

回答:


1

私が思いついた解決策は、キャプチャ/ボイドを試みる前に、請求書を作成して登録していないことでした。また、トランザクションと注文状態を処理する必要がありました。

$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();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.