at the moment I have a function which will refund the invoice on an order. However the shipping is currently also being refunded, which I don't want. Is there a way to set the shipping to zero on an invoice refund?

My code is currently this:

private function createCreditMemoItem($item)
    $creditmemoItem = $this->creditmemoItemFactory->create();

    return $creditmemoItem;

private function refundItems($order,$items) {
        $refundItems = $items;
        $items = [];

        foreach ($order->getAllVisibleItems() as $item) {
            if (!in_array($item->getId(), $refundItems)) {

            // create creditmemo item and add to array
            $creditmemoItem = $this->createCreditmemoItem($item);
            $items[] = $creditmemoItem;
        // get the invoice id

        $invoiceId = null;

        foreach ($order->getInvoiceCollection() as $invoice) {
            // this will always point to the latest invoice id
            $invoiceId = $invoice->getId();

        // refund the invoice
            true, // false = offline / true = online
            true // notify customer

the refundInvoice uses the Magento\Sales\Api\RefundInvoiceInterface class.

So just to re-iterate, the partial refund works fine in the sense that, the individual items chosen are refunded but like I say, the shipping amount is also being refunded, which I don't want to happen :)

Any help would be appreciated.


  • Hello, I am making a return module as well and following your example it returns this error Exception #0 (Magento\Sales\Exception\DocumentValidationException): Creditmemo Document Validation Error(s): We can't create creditmemo for the invoice., This if I don't use the $ this-> createCreditmemoItem ($ item); part, but if I include it, the createCreditmemoItem function gives me an error, where does this function come from? How do I add it to my controller? Dec 7, 2021 at 15:11
  • Hi @EdwinAquino I have updated the question code above to show the missing createCreditmemoItem() method at the top. To use that method, you will also need to DI an instance of \Magento\Sales\Model\Order\CreditmemoFactory into your class.
    – SNAFU
    Dec 8, 2021 at 12:49
  • This error returns Fatal error: Uncaught Error: Call to undefined method Magento\Sales\Model\Order\CreditmemoFactory::create() It is as if the create method does not exist in the class that I import Dec 8, 2021 at 14:38
  • Very strange. Do you have any of your code I can look at to see if I can identify the issue for you?
    – SNAFU
    Dec 8, 2021 at 16:36
  • I could already find how using this class Magento\Sales\Model\Order\Creditmemo\ItemCreation;, But now I have another problem, the return is created well, but if I do not return the shipping amount, the order still does not go to the closed state, and if I manually set the state with $order->setState(\Magento\Sales\Model\Order::STATE_CLOSED)->setStatus(\Magento\Sales\Model\Order::STATE_CLOSED);, Changes the status to closed, but does not return the order Dec 8, 2021 at 16:47

1 Answer 1


Ok, I figured this one out :D So basically when we run the `execute` method on the refundInvoice object, we need to send some arguments with it also.

We can set those arguments using the Magento\Sales\Model\Order\Creditmemo\CreationArgumentsFactory model.

If we assign the model to a $creationArguments property We can then set the shipping amount in the following way:

$arguments = $this->creationArguments->create();
$arguments->setShippingAmount(0); // don't refund the shipping when creating the credit memo

 // refund the invoice
    true, // false = offline / true = online
    true, // notify customer
    false, // append comment
    null, // CreditmemoCommentCreationInterface

I hope this helps someone else out who hit the same problem as I did :)

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.