I am building an extension that adds a number of items into an order once the user presses "place order" (after entering all their details.)

I am using the event observer sales_order_place_before

I'm adding the items to Mage::getModel('sales/quote_item') and Mage::getModel('sales/order_item')

The items appear in the order in the frontend and backend correctly.

However, the payment module I'm using (eWay Rapid) does not see the new items. I confirmed this by turning on the extension debugging where it outputs the items on the order it's processing, my added items ARE NOT there. I also confirmed that my extension DOES add the items BEFORE the payment module takes over.

I don't think it would be this payment module only, I think it's related to how Magento core works with any payment module when it passes the order details.

How can I add the items to the order and have the payment module aware?

  • If I could figure out how to add the products into the shopping cart instead (before pressing place order) I would be open to this. My problem with this method is that I've been unable to find a method of doing the following. 1. Programmatically add a product to the cart (done) 2. Override the SKU (done) 3. Set a non-existant custom option 4. Override the price The last two is what I have only been able to accomplish by editing the order (as mentioned in original post) and not able to do in the shopping cart.
    – Kane Shaw
    Feb 13, 2015 at 0:50
  • In regards to my alternate method (as mentioned in the comment above,) I've now been able to override the price in the cart. Now I just need to be able to set non-existent custom options on a product in the cart.
    – Kane Shaw
    Feb 13, 2015 at 2:34

2 Answers 2


Your problem is likely related to the items being cached in the getAllItems method

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)) {

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

The addItem methods in Magento do not invalidate this cache. So something like $address->unsetData('cached_items_all'); might work after you have added your product.

  • Thanks for your input Fooman. I've just like every method I can think of to clear the caches on the quote, order, quote billing/shipping address, and order billing/shipping address. It made no difference, as a matter of fact, I think your answer is correct but I'm not able to clear the cache. Maybe the cache is stored in the cart, not the quote or order models... which means I can't refresh it as I'm manipulating the quote/order at the end stage - not the cart.
    – Kane Shaw
    Feb 13, 2015 at 5:28
  • Maybe you can share the code you are currently using as this might help to find a solution. Feb 13, 2015 at 9:57

I didn't accomplish adding items to an order (after the checkout stage) and having the payment module aware of them.

As pointed out in Fooman's answer, this was most likely caused by the getAllItems result being cached before I'd added the items to the order.

This was probably a BAD way to go about doing the task anyhow, adding items on to an order after the customer has completed the checkout just seems tacky. I thought it was the only way, but I've managed to add the products to the cart and override their standard pricing and such as I was trying to do.

The trick was to use the observer checkout_cart_product_add_after and set flags on the quote object so I knew what was going on the next time the observer fired.

Here is an example of a way to add product ID 101 with a custom price to the cart when a customer buys product ID 100. I hope this will help someone.

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

    $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.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.