7

I need to create credit memo and online refund programmatically in magento 2. I referred programmatic creation of credit memo in magento 1.x here. Any help for magento 2?

1

6 Answers 6

13

Finally discovered the solution, to create credit memo with online refund from custom code. Use this code in your custom model and call the function where ever you want.

public __construct( \Magento\Sales\Model\Order $order, \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory, \Magento\Sales\Model\Order\Invoice $invoice, \Magento\Sales\Model\Service\CreditmemoService $creditmemoService, array $data = [] ) { parent::__construct($data); $this->order = $order; $this->creditmemoFactory = $creditmemoFactory; $this->creditmemoService = $creditmemoService; $this->invoice = $invoice; } public function refundCode() { $order = $this->order; $order->load(10); $invoices = $order->getInvoiceCollection(); foreach ($invoices as $invoice) { $invoiceincrementid = $invoice->getIncrementId(); } $invoiceobj = $this->invoice->loadByIncrementId($invoiceincrementid); $creditmemo = $this->creditmemoFactory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditmemo->setInvoice($invoiceobj); $this->creditmemoService->refund($creditmemo); } 
5
  • How to pass here an array of specific items? Commented Mar 21, 2017 at 7:52
  • Hi @zhartaunik do we have combination of your code & zhartaunik's answer in Refund it automatically includes Shipping Fee. How to avoid that? Commented Apr 3, 2017 at 3:23
  • Doesn't work in 2.1.6 and 2.1.7 - throws an error "We don't have enough information to save the parent transaction ID" Commented Jun 16, 2017 at 19:16
  • How to change order status from closed to cancel when credit memo is created? Commented Oct 24, 2018 at 16:11
  • do you know how to return to stock for an item? Commented Jun 29, 2021 at 16:36
5

Here some function which can be helpful to you

Create a creditmemo from an order:

\Magento\Sales\Model\Order\CreditmemoFactory::createByOrder 

Refund a creditmemo:

\Magento\Sales\Model\Service\CreditmemoService::refund 
0
5

Magento 2.1.3

/** * @var \Magento\Sales\Model\Order\CreditmemoFactory */ protected $refundOrder; /** * @var \Magento\Sales\Model\Order\Creditmemo\ItemCreationFactory */ protected $itemCreationFactory; public function __construct( \Magento\Sales\Model\RefundOrder $refundOrder, \Magento\Sales\Model\Order\Creditmemo\ItemCreationFactory $itemCreationFactory ) { $this->refundOrder = $refundOrder; $this->itemCreationFactory = $itemCreationFactory; } public function execute() { $creditmemoItem = $this->itemCreationFactory->create(); $creditmemoItem->setQty(1) ->setOrderItemId(22); $itemIdsToRefund[] = $creditmemoItem; $this->refundOrder->execute( $order->getId(), $itemIdsToRefund ); } 

Runs as clockwork

4
  • Can i get refund related table fields bz i want to create csv template for data migration. Commented Jul 22, 2017 at 13:50
  • How can I pass invoice id for same? Commented Oct 26, 2018 at 10:32
  • can we refund amout to storecredit ? Commented Mar 25, 2021 at 11:05
  • Doesn't seem to be anyway to do an online refund using Magento\Sales\Model\RefundOrder. It will always be offline. Commented May 10, 2021 at 22:37
1

To do a partial credit memo against an invoice, you need to do something like this:

/** @var RefundInvoiceInterface $refundInvoice */ $refundInvoice = $objectManager->get("\Magento\Sales\Api\RefundInvoiceInterface"); $items = []; // If items is empty array, the entire invoice will be refunded. /** @var \Magento\Sales\Model\Order\Invoice\Item $item */ foreach ($invoice->getAllItems() as $item) { // Note that the simple and configurable products are returned in getAllItems(). The function getVisibleItems() does not work, so we need this check: if($item->getOrderItem()->getProductType() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { continue; } $qtyToReturn = 1; // Select out many you want to refund $creditmemoItemCreation = new \Magento\Sales\Model\Order\Creditmemo\ItemCreation(); $items[] = $creditmemoItemCreation->setQty($qtyToReturn)->setOrderItemId($item->getOrderItemId()); } // If you don't want to refund shipping, or to make adjustment refunds, use the CreationArguments (otherwise, you can leave these next two lines out) $creditMemoCreationArguments = new CreationArguments(); $creditMemoCreationArguments->setShippingAmount(0); $refundInvoice->execute($invoice->getId(), $items, true, true, false, null, $creditMemoCreationArguments); 
1
  • Seems to possibly be something missing, where does $invoice get defined? It also seems like the $items array gets overwritten... Commented Jun 21, 2021 at 23:29
0

Try below one

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); /* Instance of object manager */ $incrementId = "100075273"; /*Increment Id */ $collection = $objectManager->create('Magento\Sales\Model\Order'); $order = $collection->loadByIncrementId($incrementId); $invoice = $objectManager->create('Magento\Sales\Model\Order\Invoice'); $creditMemoFacory = $objectManager->create('Magento\Sales\Model\Order\CreditmemoFactory'); $creditmemoService = $objectManager->create('Magento\Sales\Model\Service\CreditmemoService'); try { $invoices = $order->getInvoiceCollection(); foreach ($invoices as $invoice) { $invoiceincrementid = $invoice->getIncrementId(); } if(isset($invoiceincrementid)){ $invoiceobj = $invoice->loadByIncrementId($invoiceincrementid); $creditmemo = $creditMemoFacory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditmemo->setInvoice($invoiceobj); $creditmemoService->refund($creditmemo); echo "CreditMemo Succesfully Created For Order: ".$incrementId; } else { echo "CreditMemo Cannot Be Created For Order: ".$incrementId; /*if order has 0 amount or something wrong happened**/ } } catch (\Exception $e) { echo "Creditmemo Not Created". $e->getMessage(); } 
1
  • How to do a partial refund ? Commented Mar 30, 2021 at 6:37
0

That's how I got it working on Magento 2.3. All you need to pass is just the Order object.

<?php namespace Vender\Package\Model\Order\Processor; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\CreditmemoFactory; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Service\CreditmemoService; class CustomClass { protected $creditMemoFactory; protected $creditMemoService; protected $invoice; public function __construct ( CreditmemoFactory $creditMemoFactory, CreditmemoService $creditMemoService, Invoice $invoice ) { $this->creditMemoFactory = $creditMemoFactory; $this->creditMemoService = $creditMemoService; $this->invoice = $invoice; } /** * @param OrderInterface $order * @throws \Magento\Framework\Exception\LocalizedException */ protected function refund(OrderInterface $order): void { $invoices = $order->getInvoiceCollection(); if (count($invoices) == 0) { throw new \Exception(__('No Invoices found for Refund. Magento_ID: %2', $order->getIncrementId())); } foreach ($invoices as $invoice) { $invoice = $this->invoice->loadByIncrementId($invoice->getIncrementId()); $creditMemo = $this->creditMemoFactory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditMemo->setInvoice($invoice); $creditMemo->setCustomerNote(__('Your Order %1 has been Refunded back in your account', $order->getIncrementId())); $creditMemo->setCustomerNoteNotify(false); $creditMemo->addComment(__('Order has been Refunded')); $order->addCommentToStatusHistory(__('Order has been Refunded Successfully')); $this->creditMemoService->refund($creditMemo); } } } I hope it helps. 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.