I have created one virtual product in my Magento2 website. Now, I want to add it programmatically to the existing customer orders on some occasions with its custom price and name.

Can someone please guide step by step to achieve this?



After some goggling and with the help of some core modules I came up with following solution :

* @var \Magento\Sales\Api\OrderRepositoryInterface
protected $orderRepository;

* @var \Magento\Catalog\Api\ProductRepositoryInterface
protected $productRepository;

* @var \Magento\Quote\Api\Data\CartItemInterfaceFactory
protected $cartItemFactory;

* @var \Magento\Quote\Api\CartRepositoryInterface
protected $quoteRepository;

* @var \Magento\Sales\Model\Order\ItemFactory
protected $orderItemFactory;

 public function __construct(
    \Magento\Backend\App\Action\Context $context,        
    \Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
    \Magento\Quote\Api\Data\CartItemInterfaceFactory $cartItemFactory,
    \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
    \Magento\Sales\Model\Order\ItemFactory $orderItemFactory
) {
    $this->productRepository    = $productRepository;
    $this->orderRepository      = $orderRepository;
    $this->cartItemFactory      = $cartItemFactory;
    $this->quoteRepository      = $quoteRepository;
    $this->orderItemFactory     = $orderItemFactory;

public function execute()
    $postData       = $this->getRequest()->getPostValue();
    $productSku     = 'your-product-sku'; // Static Virtual Product created. You may also use static ID.
    $product        = $this->productRepository->get($productSku);
    $order          = $this->orderRepository->get($postData['order_id']);
    $quote          = $this->quoteRepository->get($order->getQuoteId());

    try {
    /* Add Quote Item Start */
    $quoteItem = $this->cartItemFactory->create();
    /* Add Quote Item End */

    /* Add Order Item Start */
    $orderItem = $this->orderItemFactory->create();
    /* Add Order Item End */

    /* Update relavant order totals Start */
    $order->setBaseGrandTotal($order->getBaseGrandTotal() + $postData['custom_price']);
    $order->setGrandTotal($order->getGrandTotal() + $postData['custom_price']);
    $order->setBaseSubtotal($order->getBaseSubtotal() + $postData['custom_price']);
    $order->setSubtotal($order->getSubtotal() + $postData['custom_price']);
    $order->setBaseSubtotalInclTax($order->getBaseSubtotalInclTax() + $postData['custom_price']);
    $order->setSubtotalInclTax($order->getSubtotalInclTax() + $postData['custom_price']);
    $order->setTotalItemCount($order->getTotalItemCount() + 1);
    $order->setTotalQtyOrdered($order->getTotalQtyOrdered() + 1);
    /* Update relavant order totals End */
  catch (\Exception $e) {
  • This seems to be working fine. However, I stumbled on an error when trying to renew an order with an item added through this process. The error occurs in Magento\Checkout\Model\Cart.php l:280. Our programmatically added item does not have the option 'info_buyRequest'. I managed to fix it by setting $info to an empty array when the option is missing, in a preference. – Badong Oct 30 '20 at 12:14

As per as, Magento you cannot add a new item to an order after that order is placed before. You must have to add your item before it cart has been placed.

  • Hello @Amit, Many a times you will get these type of requirements in which you need to add virtual product to get some kind of additional fee into your order with custom price. I think this can be possible with custom programming. – Pratik Navapara Oct 8 '18 at 9:48
  • every platform has it own limitation,.You have to build your logic of requirement according to it – Amit Bera Oct 8 '18 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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