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?
6 Answers
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);
}
-
-
Hi @zhartaunik do we have combination of your code & zhartaunik's answer in Refund it automatically includes Shipping Fee. How to avoid that?– JacksonApr 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" Jun 16, 2017 at 19:16
-
How to change order status from closed to cancel when credit memo is created? Oct 24, 2018 at 16:11
-
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
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
-
Can i get refund related table fields bz i want to create csv template for data migration. Jul 22, 2017 at 13:50
-
-
-
Doesn't seem to be anyway to do an online refund using Magento\Sales\Model\RefundOrder. It will always be offline. May 10, 2021 at 22:37
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);
-
Seems to possibly be something missing, where does
$invoice
get defined? It also seems like the$items
array gets overwritten...– joeybab3Jun 21, 2021 at 23:29
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();
}
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.