Добавляйте товары в заказ программно, чтобы модуль оплаты их видел


Я создаю расширение, которое добавляет ряд товаров в заказ, как только пользователь нажимает "оформить заказ" (после ввода всех их деталей).

Я использую наблюдателя событий sales_order_place_before

Я добавляю элементы в Mage::getModel ('продажи/quote_item') и Mage::getModel('продажи/заказ_item')

Элементы отображаются в правильном порядке во внешнем и внутреннем интерфейсе.

Однако платежный модуль Я использую (eWay Rapid), не вижу новых предметов. Я подтвердил это, включив отладку расширения, где оно выводит элементы в обрабатываемом заказе, моих добавленных элементов ТАМ НЕТ. Я также подтвердил, что мое расширение добавляет товары ДО того, как платежный модуль вступит во владение.

Я не думаю, что это будет только этот платежный модуль, я думаю, что это связано с тем, как ядро Magento работает с любым платежным модулем, когда он передает детали заказа.

Как я могу добавить элементы в заказ и имейте в виду платежный модуль?

Author: Kane Shaw, 2015-02-13

2 answers

Ваша проблема, вероятно, связана с элементами, кэшируемыми в методе getAllItems

public function getAllItems()
{
    // We calculate item list once and cache it in three arrays - all items, nominal, non-nominal
    $cachedItems = $this->_nominalOnly ? 'nominal' : ($this->_nominalOnly === false ? 'nonnominal' : 'all');
    $key = 'cached_items_' . $cachedItems;
    if (!$this->hasData($key)) {

См. https://github.com/OpenMage/magento-mirror/blob/magento-1.9/app/code/core/Mage/Sales/Model/Quote/Address.php#L447

Методы добавления в Magento не делают этот кэш недействительным. Поэтому что-то вроде $address->unsetData('cached_items_all'); может сработать после того, как вы добавите свой продукт.

 1
Author: Kristof at Fooman, 2015-02-13 04:01:33

Я не выполнил добавление товаров в заказ (после этапа оформления заказа) и не уведомил о них платежный модуль.

Как указано в ответе Фумана, это, скорее всего, было вызвано тем, что результат getAllItems был кэширован до того, как я добавил элементы в заказ.

Вероятно, это был ПЛОХОЙ способ выполнить задачу в любом случае, добавление товаров в заказ после того, как клиент завершил оформление заказа, просто кажется безвкусным. Я думал, что это единственный выход, но мне удалось чтобы добавить товары в корзину и переопределить их стандартные цены, как я пытался сделать.

Хитрость заключалась в том, чтобы использовать наблюдателя checkout_cart_product_add_after и установить флаги на объекте цитаты, чтобы я знал, что происходит в следующий раз, когда наблюдатель выстрелит.

Вот пример способа добавления идентификатора продукта 101 с пользовательской ценой в корзину, когда клиент покупает идентификатор продукта 100. Я надеюсь, что это кому-то поможет.

public function checkout_cart_product_add_after(Varien_Event_Observer $observer) {
    $this->log('Observer: checkout_cart_product_add_after');
    $cart = Mage::getModel('checkout/cart');
    $cart->init();

    $quoteItem = $observer->getQuoteItem();
    $quote = $quoteItem->getQuote();

    $my_flag = $quote->getMyFlag(); // Grab the flag, if it's been set yet

    if($my_flag == "adding bonus") {

        // If we're here we know that this time the observer was fired after we added our bonus product to the cart

        $my_price = $quote->getMyPrice(); // Get the price that was set last time the observer fired
        $quoteItem->setIsSuperMode(true); // You need to set this to override a product price
        $quoteItem->setCustomPrice($my_price); // Set your override price here
        $quoteItem->setOriginalCustomPrice($my_price); // And here
        $quoteItem->save(); // Save the item so the new price will stick in the cart

    } else {
        // If we're here we are processing/observing a normal "add to cart"

        if($quoteItem->getProduct()->getId() == "100") { // Check if the product being added is the ID we want to add a bonus for
            $quote->setMyFlag("adding bonus"); // This is how we'll know the next time the observer fires that we need to override the price
            $quote->setMyBonusPrice(5.00); // Here is a way you can store the price you want to override it to (we'll grab this value next time the observer fires)

            $bonusItem = Mage::getModel('catalog/product')->load("101"); // load the bonus product

            $params = array(
                'product' => "101",
                'qty' => "1"
            );
            $cartItem = $cart->addProduct($bonusItem,$params); //Add it to the cart - this will fire the observer again... but this time with the flags we set earlier.

            $cart->save();
            Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
        }
    }
}
 1
Author: Kane Shaw, 2015-02-17 08:34:20