Magento_Sales module

Magento_Sales module is responsible for order processing and appearance in system.

Magento_Sales module manages next system entities and flows:

  • order management
  • invoice management
  • shipment management (including track management)
  • credit memos management

Magento_Sales module is required for Magento_Checkout module to perform checkout operations.

System requirements

The Magento_Sales module does not have any specific system requirements.

Depending on how many orders are being placed, there might be consideration for the database size.

Installation

The Magento_Sales module is installed automatically during Magento installation.

InvoiceOrder

The InvoiceOrder service introduces a capability to execute Magento native business flow of the Sales module using API.

With this service you can:

  • create an invoice document (full or partial)
  • capture money placed with order payment
  • notify a customer about document creation
  • change order status and state

Parameters

Name Description Format Example Required / Optional Default value
orderId An identifier of a target order for operation. Integer   Required  
items An array of order items that will be included to invoice. By default, the invoice will contain all order items. Array of items with a format according to \Magento\Sales\Api\Data\InvoiceItemCreationInterface.
      [
          {
              "order_item_id": 1,
              "qty": 2
          },
          {
          "order_item_id": 2,
          "qty": 0.5
          }
          ]
      
Optional (required, when invoice must contain particular order items. []
capture Flag that sets whether the customer’s payment can be captured using an online payments system (for example, PayPal). IMPORTANT: If you created Invoice with the flag set to default value (false), you will not be able to capture money in Magento on the corresponding Invoice. Boolean   Optional false
notify Flag that activates e-mail notification about new invoice for a customer. If true, the service will notify a customer. If false, the service won’t notify a customer. Boolean   Optional false
appendComment Flag that determines whether a comment argument must be included in an e-mail notification. If true, the service adds the comment. Boolean   Optional false
comment The comment to add to an invoice. Specify a comment if appendComment is set to true. A format according to \Magento\Sales\Api\Data\InvoiceCommentCreationInterface.
      {
          "comment": "The first Invoice",
          "is_visible_on_front": true
      }
      
Optional null
arguments Additional arguments. Reserved for use by extension modules. A format according to \Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface.   Optional null

Return values

The service returns an identifier of the created Invoice.

REST

POST Endpoint

http://<magento_host>/rest/<store_code>/V1/<orderId>/invoice

REST declaration

etc/webapi.xml

<route url="/V1/order/:orderId/invoice" method="POST">
    <service class="Magento\Sales\Api\InvoiceOrderInterface" method="execute"/>
    <resources>
        <resource ref="Magento_Sales::sales" />
    </resources>
</route>

SOAP

SOAP Endpoint

http://<magento_host>/soap/<store_code>?wsdl&services=salesInvoiceOrderV1

PHP interface

\Magento\Sales\Api\InvoiceOrderInterface

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Magento\Sales\Api;

/**
 * Class InvoiceOrderInterface
 *
 * @api
 */
interface InvoiceOrderInterface
{
    /**
     * @param int $orderId
     * @param bool|false $capture
     * @param \Magento\Sales\Api\Data\InvoiceItemCreationInterface[] $items
     * @param bool|false $notify
     * @param bool|false $appendComment
     * @param Data\InvoiceCommentCreationInterface|null $comment
     * @param Data\InvoiceCreationArgumentsInterface|null $arguments
     * @return int
     */
    public function execute(
        $orderId,
        $capture = false,
        array $items = [],
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\InvoiceCommentCreationInterface $comment = null,
        \Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface $arguments = null
    );
}

PHP implementation

\Magento\Sales\Model\InvoiceOrder

Click to show/hide included code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Magento\Sales\Model;

use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Api\Data\InvoiceCommentCreationInterface;
use Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface;
use Magento\Sales\Api\InvoiceOrderInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\Order\Config as OrderConfig;
use Magento\Sales\Model\Order\Invoice\InvoiceValidatorInterface;
use Magento\Sales\Model\Order\Invoice\NotifierInterface;
use Magento\Sales\Model\Order\InvoiceDocumentFactory;
use Magento\Sales\Model\Order\InvoiceRepository;
use Magento\Sales\Model\Order\OrderStateResolverInterface;
use Magento\Sales\Model\Order\OrderValidatorInterface;
use Magento\Sales\Model\Order\PaymentAdapterInterface;
use Magento\Sales\Model\Order\Validation\InvoiceOrderInterface as InvoiceOrderValidator;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\ObjectManager;

/**
 * Class InvoiceOrder
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class InvoiceOrder implements InvoiceOrderInterface
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var InvoiceDocumentFactory
     */
    private $invoiceDocumentFactory;

    /**
     * @var PaymentAdapterInterface
     */
    private $paymentAdapter;

    /**
     * @var OrderStateResolverInterface
     */
    private $orderStateResolver;

    /**
     * @var OrderConfig
     */
    private $config;

    /**
     * @var InvoiceRepository
     */
    private $invoiceRepository;

    /**
     * @var InvoiceOrderValidator
     */
    private $invoiceOrderValidator;

    /**
     * @var NotifierInterface
     */
    private $notifierInterface;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * InvoiceOrder constructor.
     * @param ResourceConnection $resourceConnection
     * @param OrderRepositoryInterface $orderRepository
     * @param InvoiceDocumentFactory $invoiceDocumentFactory
     * @param InvoiceValidatorInterface $invoiceValidator
     * @param OrderValidatorInterface $orderValidator
     * @param PaymentAdapterInterface $paymentAdapter
     * @param OrderStateResolverInterface $orderStateResolver
     * @param OrderConfig $config
     * @param InvoiceRepository $invoiceRepository
     * @param NotifierInterface $notifierInterface
     * @param LoggerInterface $logger
     * @param InvoiceOrderValidator|null $invoiceOrderValidator
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        OrderRepositoryInterface $orderRepository,
        InvoiceDocumentFactory $invoiceDocumentFactory,
        InvoiceValidatorInterface $invoiceValidator,
        OrderValidatorInterface $orderValidator,
        PaymentAdapterInterface $paymentAdapter,
        OrderStateResolverInterface $orderStateResolver,
        OrderConfig $config,
        InvoiceRepository $invoiceRepository,
        NotifierInterface $notifierInterface,
        LoggerInterface $logger,
        InvoiceOrderValidator $invoiceOrderValidator = null
    ) {
        $this->resourceConnection = $resourceConnection;
        $this->orderRepository = $orderRepository;
        $this->invoiceDocumentFactory = $invoiceDocumentFactory;
        $this->paymentAdapter = $paymentAdapter;
        $this->orderStateResolver = $orderStateResolver;
        $this->config = $config;
        $this->invoiceRepository = $invoiceRepository;
        $this->notifierInterface = $notifierInterface;
        $this->logger = $logger;
        $this->invoiceOrderValidator = $invoiceOrderValidator ?: ObjectManager::getInstance()->get(
            InvoiceOrderValidator::class
        );
    }

    /**
     * @param int $orderId
     * @param bool $capture
     * @param array $items
     * @param bool $notify
     * @param bool $appendComment
     * @param \Magento\Sales\Api\Data\InvoiceCommentCreationInterface|null $comment
     * @param \Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface|null $arguments
     * @return int
     * @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface
     * @throws \Magento\Sales\Api\Exception\CouldNotInvoiceExceptionInterface
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \DomainException
     */
    public function execute(
        $orderId,
        $capture = false,
        array $items = [],
        $notify = false,
        $appendComment = false,
        InvoiceCommentCreationInterface $comment = null,
        InvoiceCreationArgumentsInterface $arguments = null
    ) {
        $connection = $this->resourceConnection->getConnection('sales');
        $order = $this->orderRepository->get($orderId);
        $invoice = $this->invoiceDocumentFactory->create(
            $order,
            $items,
            $comment,
            ($appendComment && $notify),
            $arguments
        );
        $errorMessages = $this->invoiceOrderValidator->validate(
            $order,
            $invoice,
            $capture,
            $items,
            $notify,
            $appendComment,
            $comment,
            $arguments
        );
        if ($errorMessages->hasMessages()) {
            throw new \Magento\Sales\Exception\DocumentValidationException(
                __("Invoice Document Validation Error(s):\n" . implode("\n", $errorMessages->getMessages()))
            );
        }
        $connection->beginTransaction();
        try {
            $order = $this->paymentAdapter->pay($order, $invoice, $capture);
            $order->setState(
                $this->orderStateResolver->getStateForOrder($order, [OrderStateResolverInterface::IN_PROGRESS])
            );
            $order->setStatus($this->config->getStateDefaultStatus($order->getState()));
            $invoice->setState(\Magento\Sales\Model\Order\Invoice::STATE_PAID);
            $this->invoiceRepository->save($invoice);
            $this->orderRepository->save($order);
            $connection->commit();
        } catch (\Exception $e) {
            $this->logger->critical($e);
            $connection->rollBack();
            throw new \Magento\Sales\Exception\CouldNotInvoiceException(
                __('Could not save an invoice, see error log for details')
            );
        }
        if ($notify) {
            if (!$appendComment) {
                $comment = null;
            }
            $this->notifierInterface->notify($order, $invoice, $comment);
        }
        return $invoice->getEntityId();
    }
}

Exceptions

In case of failure, it returns an error object. Example in REST:

{
    "message": "Creditmemo Document Validation Error(s):\nWe can't create creditmemo for the order.\nThe most money available to refund is 0."
}

Extension points

The service implementation contains extension points marked with @api annotation. Extension developers can use APIs to extend service logic.

Extension point Description
\Magento\Sales\Api\OrderRepositoryInterface An interface for saving and retrieving Orders.
\Magento\Sales\Model\Order\OrderStateResolverInterface An interface which provides a correct state of an Order according to performed operation.
\Magento\Sales\Api\InvoiceRepositoryInterface An interface for saving and retrieving Shipments.
\Magento\Sales\Model\Order\InvoiceDocumentFactory A factory for creating an Invoice data object. The factory uses the arguments parameter to process the extension attributes of a new Invoice.
\Magento\Sales\Model\Order\Invoice\NotifierInterface An interface for sending notifications about new Invoice creation.
\Magento\Sales\Model\Order\Validation\InvoiceOrderInterface An interface for validating service parameters and Invoice data object.
\Magento\Sales\Model\Order\PaymentAdapterInterface An interface for a payment according to a selected option (online/offline). It returns Order with modified state, which contains payment specific information.

RefundInvoice

The RefundInvoice service introduces a capability to execute Magento native business flow of the Sales module using API.

Please note, that current service is available only for invoices created using online payment methods. If you try to apply it to an Invoice created using offline payment method, system will throw a validation error.

With this service you can:

  • create a Credit Memo (complete or partial) for particular Invoice
  • add details about refunded items to an Order
  • change status and state of an Order according to performed actions
  • notify a customer about performed refund operation

Service parameters

Name Description Format Example Required/Optional Default value
invoiceId An identifier of a target Invoice for operation. Integer   Required  
items An array of invoice items included to a Credit Memo. By default, the service will create a Credit Memo for all invoice items. Array of items with a format according to \Magento\Sales\Api\Data\CreditmemoItemCreationInterface.
        [
            {
                 "order_item_id": 1,
                 "qty": 2
            },
            {
            "order_item_id": 2,
            "qty": 0.5
            }
        ]
        
Optional (required, when a Credit Memo must contain particular order items) []
isOnline Flag that determines whether funds should be returned to a customer via online payment system (PayPal for example) or not. Boolean   Optional false
notify Flag that activates e-mail notification about Credit Memo creation. If true, the service notifies a customer; if false, it doesn't. Boolean   Optional false
appendComment Flag that activates addition of a comment argument to the e-mail notification. If true and comment contains data, the service will add the comment to an e-mail notification. Boolean   Optional false
comment A comment to Credit Memo. A format according to the \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface.
        {
            "comment": "The first Credit Memo",
            "is_visible_on_front": true
        }
        
Optional null
arguments Additional arguments for the service. Can be used by extension modules. A format according to \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface.
        {
        "shipping_amount": 10.00,
        "adjustment_positive": 5.00,
        "adjustment_negative": 5.00
        }
        
A parameter shipping_amount behaves like at the Credit Memo creation page in the Admin area. If shipping amount is not specified, then shipping amount from a target Invoice is refunded automatically. To specify a shipping amount, consider shipping tax displays settings.
Optional null

Return values

The service returns an identifier of a created Credit Memo.

REST

POST Endpoint

http://<magento_host>/rest/<store_code>/V1/<invoiceId>/refund

REST Declaration

etc/webapi.xml

<route url="/V1/invoice/:invoiceId/refund" method="POST">
    <service class="Magento\Sales\Api\RefundInvoiceInterface" method="execute"/>
    <resources>
        <resource ref="Magento_Sales::sales" />
    </resources>
</route>

SOAP

SOAP Endpoint

http://<magento_host>/soap/<store_code>?wsdl&services=salesRefundInvoiceV1

PHP interface

\Magento\Sales\Api\RefundInvoiceInterface

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Api;

/**
 * Interface RefundInvoiceInterface
 */
interface RefundInvoiceInterface
{
    /**
     * Create refund for invoice
     *
     * @param int $invoiceId
     * @param \Magento\Sales\Api\Data\CreditmemoItemCreationInterface[] $items
     * @param bool|null $isOnline
     * @param bool|null $notify
     * @param bool|null $appendComment
     * @param \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface|null $comment
     * @param \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface|null $arguments
     * @return int
     */
    public function execute(
        $invoiceId,
        array $items = [],
        $isOnline = false,
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
        \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
    );
}

PHP implementation

\Magento\Sales\Model\RefundInvoice

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Model;

use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Api\CreditmemoRepositoryInterface;
use Magento\Sales\Api\InvoiceRepositoryInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Api\RefundInvoiceInterface;
use Magento\Sales\Model\Order\Config as OrderConfig;
use Magento\Sales\Model\Order\Creditmemo\NotifierInterface;
use Magento\Sales\Model\Order\CreditmemoDocumentFactory;
use Magento\Sales\Model\Order\Validation\RefundInvoiceInterface as RefundInvoiceValidator;
use Magento\Sales\Model\Order\OrderStateResolverInterface;
use Magento\Sales\Model\Order\RefundAdapterInterface;
use Psr\Log\LoggerInterface;

/**
 * Class RefundInvoice
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class RefundInvoice implements RefundInvoiceInterface
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var OrderStateResolverInterface
     */
    private $orderStateResolver;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var InvoiceRepositoryInterface
     */
    private $invoiceRepository;

    /**
     * @var CreditmemoRepositoryInterface
     */
    private $creditmemoRepository;

    /**
     * @var RefundAdapterInterface
     */
    private $refundAdapter;

    /**
     * @var CreditmemoDocumentFactory
     */
    private $creditmemoDocumentFactory;

    /**
     * @var NotifierInterface
     */
    private $notifier;

    /**
     * @var OrderConfig
     */
    private $config;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var RefundInvoiceValidator
     */
    private $validator;

    /**
     * RefundInvoice constructor.
     *
     * @param ResourceConnection $resourceConnection
     * @param OrderStateResolverInterface $orderStateResolver
     * @param OrderRepositoryInterface $orderRepository
     * @param InvoiceRepositoryInterface $invoiceRepository
     * @param RefundInvoiceValidator $validator
     * @param CreditmemoRepositoryInterface $creditmemoRepository
     * @param RefundAdapterInterface $refundAdapter
     * @param CreditmemoDocumentFactory $creditmemoDocumentFactory
     * @param NotifierInterface $notifier
     * @param OrderConfig $config
     * @param LoggerInterface $logger
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        OrderStateResolverInterface $orderStateResolver,
        OrderRepositoryInterface $orderRepository,
        InvoiceRepositoryInterface $invoiceRepository,
        RefundInvoiceValidator $validator,
        CreditmemoRepositoryInterface $creditmemoRepository,
        RefundAdapterInterface $refundAdapter,
        CreditmemoDocumentFactory $creditmemoDocumentFactory,
        NotifierInterface $notifier,
        OrderConfig $config,
        LoggerInterface $logger
    ) {
        $this->resourceConnection = $resourceConnection;
        $this->orderStateResolver = $orderStateResolver;
        $this->orderRepository = $orderRepository;
        $this->invoiceRepository = $invoiceRepository;
        $this->validator = $validator;
        $this->creditmemoRepository = $creditmemoRepository;
        $this->refundAdapter = $refundAdapter;
        $this->creditmemoDocumentFactory = $creditmemoDocumentFactory;
        $this->notifier = $notifier;
        $this->config = $config;
        $this->logger = $logger;
    }

    /**
     * @inheritdoc
     */
    public function execute(
        $invoiceId,
        array $items = [],
        $isOnline = false,
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
        \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
    ) {
        $connection = $this->resourceConnection->getConnection('sales');
        $invoice = $this->invoiceRepository->get($invoiceId);
        $order = $this->orderRepository->get($invoice->getOrderId());
        $creditmemo = $this->creditmemoDocumentFactory->createFromInvoice(
            $invoice,
            $items,
            $comment,
            ($appendComment && $notify),
            $arguments
        );

        $validationMessages = $this->validator->validate(
            $invoice,
            $order,
            $creditmemo,
            $items,
            $isOnline,
            $notify,
            $appendComment,
            $comment,
            $arguments
        );
        if ($validationMessages->hasMessages()) {
            throw new \Magento\Sales\Exception\DocumentValidationException(
                __("Creditmemo Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
            );
        }
        $connection->beginTransaction();
        try {
            $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED);
            $order->setCustomerNoteNotify($notify);
            $order = $this->refundAdapter->refund($creditmemo, $order, $isOnline);
            $order->setState(
                $this->orderStateResolver->getStateForOrder($order, [])
            );
            $order->setStatus($this->config->getStateDefaultStatus($order->getState()));
            if (!$isOnline) {
                $invoice->setIsUsedForRefund(true);
                $invoice->setBaseTotalRefunded(
                    $invoice->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal()
                );
            }
            $this->invoiceRepository->save($invoice);
            $order = $this->orderRepository->save($order);
            $creditmemo = $this->creditmemoRepository->save($creditmemo);
            $connection->commit();
        } catch (\Exception $e) {
            $this->logger->critical($e);
            $connection->rollBack();
            throw new \Magento\Sales\Exception\CouldNotRefundException(
                __('Could not save a Creditmemo, see error log for details')
            );
        }
        if ($notify) {
            if (!$appendComment) {
                $comment = null;
            }
            $this->notifier->notify($order, $creditmemo, $comment);
        }

        return $creditmemo->getEntityId();
    }
}

Exceptions

In case of failure, it returns an error object. Example in REST:

{
    "message": "Creditmemo Document Validation Error(s):\nWe can't create creditmemo for the order.\nThe most money available to refund is 0."
}

Extension points

The service contains extension points marked with @api annotation. Extension developers can use APIs to extend service logic.

Extension point Description
\Magento\Sales\Api\OrderRepositoryInterface An interface for saving and retrieving Orders.
\Magento\Sales\Model\Order\OrderStateResolverInterface An interface providing a correct state of an Order according to performed operation.
\Magento\Sales\Api\InvoiceRepositoryInterface An interface for saving and retrieving Invoices.
\Magento\Sales\Api\CreditmemoRepositoryInterface An interface for saving and retrieving Credit Memos.
\Magento\Sales\Model\Order\CreditmemoDocumentFactory A factory for creating an Credit Memo data object. The factory uses the arguments parameter to process the extension attributes of a new Credit Memo.
\Magento\Sales\Model\Order\Creditmemo\NotifierInterface An interface for sending notifications about new Credit Memo creation.
\Magento\Sales\Model\Order\Validation\RefundInvoiceInterface An interface for validating service parameters and Credit Memo data object.
\Magento\Sales\Model\Order\RefundAdapterInterface An interface for a payment according to a selected option (online/offline). It returns Order with modified state, which contains payment specific information.

RefundOrder

With the RefundOrder service you can:

  • create a Credit Memo (complete or partial) for a particular Order
  • add details about refunded items to an Order
  • change status and state of an Order according to performed actions
  • notify a customer about performed refund operation

Service parameters

Name Description Format Example Required/Optional Default value
orderId An identifier of a target Order for operation. Integer   Required  
items An array of Order items included to a Credit Memo. By default, the service will create a Credit Memo for all Order items. Array of items with a format according to \Magento\Sales\Api\Data\CreditmemoItemCreationInterface.
        [
            {
                 "order_item_id": 1,
                 "qty": 2
            },
            {
                 "order_item_id": 2,
                 "qty": 0.5
            }
        ]
        
Optional (required, when a Credit Memo must contain particular order items) []
notify Flag that activates e-mail notification about Credit Memo creation. If true, the service notifies a customer; if false, it doesn't. Boolean   Optional false
appendComment Flag that activates addition of a comment argument to the e-mail notification. If true and comment contains data, the service will add the comment to an e-mail notification. Boolean   Optional false
comment A comment to Credit Memo. A format according to the \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface.
        {
            "comment": "The first Credit Memo",
            "is_visible_on_front": true
        }
        
Optional null
arguments Additional arguments for the service. Can be used by extension modules. A format according to \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface.
        {
        "shipping_amount": 10.00,
        "adjustment_positive": 5.00,
        "adjustment_negative": 5.00
        }
        
A parameter shipping_amount behaves like at the Credit Memo creation page in the Admin area. If shipping amount is not specified, then shipping amount from a target Invoice is refunded automatically. To specify a shipping amount, consider shipping tax displays settings.
Optional null

Return values

The service returns an identifier of a created Credit Memo.

REST

POST Endpoint

http://<magento_host>/rest/<store_code>/V1/<orderId>/refund

REST Declaration

etc/webapi.xml

<route url="/V1/order/:orderId/refund" method="POST">
    <service class="Magento\Sales\Api\RefundOrderInterface" method="execute"/>
    <resources>
        <resource ref="Magento_Sales::sales" />
    </resources>
</route>

SOAP

SOAP Endpoint

http://<magento_host>/soap/<store_code>?wsdl&services=salesRefundOrderV1

PHP interface

\Magento\Sales\Api\RefundOrderInterface

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Api;

/**
 * Interface RefundOrderInterface
 */
interface RefundOrderInterface
{
    /**
     * Create offline refund for order
     *
     * @param int $orderId
     * @param \Magento\Sales\Api\Data\CreditmemoItemCreationInterface[] $items
     * @param bool|null $notify
     * @param bool|null $appendComment
     * @param \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface|null $comment
     * @param \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface|null $arguments
     * @return int
     */
    public function execute(
        $orderId,
        array $items = [],
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
        \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
    );
}

PHP implementation

\Magento\Sales\Model\RefundOrder

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Model;

use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Api\CreditmemoRepositoryInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Api\RefundOrderInterface;
use Magento\Sales\Model\Order\Config as OrderConfig;
use Magento\Sales\Model\Order\Creditmemo\NotifierInterface;
use Magento\Sales\Model\Order\CreditmemoDocumentFactory;
use Magento\Sales\Model\Order\OrderStateResolverInterface;
use Magento\Sales\Model\Order\RefundAdapterInterface;
use Magento\Sales\Model\Order\Validation\RefundOrderInterface as RefundOrderValidator;
use Psr\Log\LoggerInterface;

/**
 * Class RefundOrder
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class RefundOrder implements RefundOrderInterface
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var OrderStateResolverInterface
     */
    private $orderStateResolver;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var CreditmemoRepositoryInterface
     */
    private $creditmemoRepository;

    /**
     * @var RefundAdapterInterface
     */
    private $refundAdapter;

    /**
     * @var CreditmemoDocumentFactory
     */
    private $creditmemoDocumentFactory;

    /**
     * @var RefundOrderValidator
     */
    private $validator;

    /**
     * @var NotifierInterface
     */
    private $notifier;

    /**
     * @var OrderConfig
     */
    private $config;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * RefundOrder constructor.
     *
     * @param ResourceConnection $resourceConnection
     * @param OrderStateResolverInterface $orderStateResolver
     * @param OrderRepositoryInterface $orderRepository
     * @param CreditmemoRepositoryInterface $creditmemoRepository
     * @param RefundAdapterInterface $refundAdapter
     * @param CreditmemoDocumentFactory $creditmemoDocumentFactory
     * @param RefundOrderValidator $validator
     * @param NotifierInterface $notifier
     * @param OrderConfig $config
     * @param LoggerInterface $logger
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        OrderStateResolverInterface $orderStateResolver,
        OrderRepositoryInterface $orderRepository,
        CreditmemoRepositoryInterface $creditmemoRepository,
        RefundAdapterInterface $refundAdapter,
        CreditmemoDocumentFactory $creditmemoDocumentFactory,
        RefundOrderValidator $validator,
        NotifierInterface $notifier,
        OrderConfig $config,
        LoggerInterface $logger
    ) {
        $this->resourceConnection = $resourceConnection;
        $this->orderStateResolver = $orderStateResolver;
        $this->orderRepository = $orderRepository;
        $this->creditmemoRepository = $creditmemoRepository;
        $this->refundAdapter = $refundAdapter;
        $this->creditmemoDocumentFactory = $creditmemoDocumentFactory;
        $this->validator = $validator;
        $this->notifier = $notifier;
        $this->config = $config;
        $this->logger = $logger;
    }

    /**
     * @inheritdoc
     */
    public function execute(
        $orderId,
        array $items = [],
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
        \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
    ) {
        $connection = $this->resourceConnection->getConnection('sales');
        $order = $this->orderRepository->get($orderId);
        $creditmemo = $this->creditmemoDocumentFactory->createFromOrder(
            $order,
            $items,
            $comment,
            ($appendComment && $notify),
            $arguments
        );
        $validationMessages = $this->validator->validate(
            $order,
            $creditmemo,
            $items,
            $notify,
            $appendComment,
            $comment,
            $arguments
        );
        if ($validationMessages->hasMessages()) {
            throw new \Magento\Sales\Exception\DocumentValidationException(
                __("Creditmemo Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
            );
        }
        $connection->beginTransaction();
        try {
            $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED);
            $order->setCustomerNoteNotify($notify);
            $order = $this->refundAdapter->refund($creditmemo, $order);
            $order->setState(
                $this->orderStateResolver->getStateForOrder($order, [])
            );
            $order->setStatus($this->config->getStateDefaultStatus($order->getState()));

            $order = $this->orderRepository->save($order);
            $creditmemo = $this->creditmemoRepository->save($creditmemo);
            $connection->commit();
        } catch (\Exception $e) {
            $this->logger->critical($e);
            $connection->rollBack();
            throw new \Magento\Sales\Exception\CouldNotRefundException(
                __('Could not save a Creditmemo, see error log for details')
            );
        }
        if ($notify) {
            if (!$appendComment) {
                $comment = null;
            }
            $this->notifier->notify($order, $creditmemo, $comment);
        }

        return $creditmemo->getEntityId();
    }
}

Exceptions

In case of failure, it returns an error object. Example in REST:

{
    "message": "Creditmemo Document Validation Error(s):\nWe can't create creditmemo for the order.\nThe most money available to refund is 0."
}

Extension points

The service contains extension points marked with @api annotation. Extension developers can use APIs to extend service logic.

Extension point Description
\Magento\Sales\Api\OrderRepositoryInterface An interface for saving and retrieving Orders.
\Magento\Sales\Model\Order\OrderStateResolverInterface An interface providing a correct state of an Order according to performed operation.
\Magento\Sales\Api\CreditmemoRepositoryInterface An interface for saving and retrieving Credit Memos.
\Magento\Sales\Model\Order\CreditmemoDocumentFactory A factory for creating an Credit Memo data object. The factory uses the arguments parameter to process the extension attributes of a new Credit Memo.
\Magento\Sales\Model\Order\Creditmemo\NotifierInterface An interface for sending notifications about new Credit Memo creation.
\Magento\Sales\Model\Order\Validation\RefundOrderInterface An interface for validating service parameters and Credit Memo data object.
\Magento\Sales\Model\Order\RefundAdapterInterface An interface for a payment according to a selected option (online/offline). It returns Order with modified state, which contains payment specific information.

ShipOrder

With the ShipOrder service you can:

  • create a shipment document (full or partial)
  • add details about shipped items into an order
  • change status and state of an order according to performed actions
  • notify the customer of a new shipment document

Service parameters

Name Description Format Example Required/Optional Default value
orderId An identifier of a target order for operation. Integer   Required  
items An array of order items included to a shipment. By default, the service will create a shipment for all order items. Array of items with a format according to \Magento\Sales\Api\Data\ShipmentItemCreationInterface.
        [
            {
                "order_item_id": 1,
                "qty": 2
            },
            {
                "order_item_id": 2,
                "qty": 0.5
            }
        ]
        
Optional (required, when a shipment document must contain particular order items) []
notify Flag that activates e-mail notification about shipment details. If true, the service notifies a customer; if false, it doesn't. Boolean   Optional false
appendComment Flag that activates addition of a comment argument to the e-mail notification. If true and comment contains data, the service will add the comment to an e-mail notification. Boolean   Optional false
comment A comment about a shipment. A format according to the \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface interface.
      {   
          "comment": "The first Invoice",
          "is_visible_on_front": true
      }
      
Optional null
tracks A list of track numbers attached to a shipment. Array of objects with a format according to \Magento\Sales\Api\Data\ShipmentTrackCreationInterface>.
      [
          {
              "track_number": "132456789",
              "title": "United States Postal Service",
              "carrier_code": "usps"
          }
      ]
      
Optional []
packages A list of packages attached to a shipment. Array of objects with a format according to \Magento\Sales\Api\Data\ShipmentPackageCreationInterface.
      [
          {
              "extension_attributes":
              {
                  "ups":
                      {
                          "weight": 20,
                          "height": 15,
                          "width": 20
                      }
              }
           }
      ]
      
Optional []
arguments Additional arguments for the service. Can be used by extension modules. A format according to the \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface interface.   Optional null

Return values

The service returns the identifier of a created shipment.

REST

POST Endpoint

http://<magento_host>/rest/<store_code>/V1/<orderId>/ship

REST Declaration

etc/webapi.xml

<route url="/V1/order/:orderId/ship" method="POST">
    <service class="Magento\Sales\Api\ShipOrderInterface" method="execute"/>
    <resources>
        <resource ref="Magento_Sales::sales" />
    </resources>
</route>

SOAP

SOAP Endpoint

http://<magento_host>/soap/<store_code>?wsdl&services=salesShipOrderV1

PHP interface

\Magento\Sales\Api\ShipOrderInterface

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Api;

/**
 * Class ShipOrderInterface
 *
 * @api
 */
interface ShipOrderInterface
{
    /**
     * Creates new Shipment for given Order.
     *
     * @param int $orderId
     * @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items
     * @param bool $notify
     * @param bool $appendComment
     * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment
     * @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks
     * @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages
     * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments
     * @return int Id of created Shipment.
     */
    public function execute(
        $orderId,
        array $items = [],
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null,
        array $tracks = [],
        array $packages = [],
        \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null
    );
}

PHP implementation

\Magento\Sales\Model\ShipOrder

Click to show/hide a code
<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Sales\Model;

use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Api\ShipmentRepositoryInterface;
use Magento\Sales\Api\ShipOrderInterface;
use Magento\Sales\Model\Order\Config as OrderConfig;
use Magento\Sales\Model\Order\OrderStateResolverInterface;
use Magento\Sales\Model\Order\OrderValidatorInterface;
use Magento\Sales\Model\Order\ShipmentDocumentFactory;
use Magento\Sales\Model\Order\Shipment\NotifierInterface;
use Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface;
use Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface;
use Magento\Sales\Model\Order\Validation\ShipOrderInterface as ShipOrderValidator;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\ObjectManager;

/**
 * Class ShipOrder
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class ShipOrder implements ShipOrderInterface
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var ShipmentDocumentFactory
     */
    private $shipmentDocumentFactory;

    /**
     * @var OrderStateResolverInterface
     */
    private $orderStateResolver;

    /**
     * @var OrderConfig
     */
    private $config;

    /**
     * @var ShipmentRepositoryInterface
     */
    private $shipmentRepository;

    /**
     * @var ShipOrderValidator
     */
    private $shipOrderValidator;

    /**
     * @var NotifierInterface
     */
    private $notifierInterface;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var OrderRegistrarInterface
     */
    private $orderRegistrar;

    /**
     * @param ResourceConnection $resourceConnection
     * @param OrderRepositoryInterface $orderRepository
     * @param ShipmentDocumentFactory $shipmentDocumentFactory
     * @param ShipmentValidatorInterface $shipmentValidator
     * @param OrderValidatorInterface $orderValidator
     * @param OrderStateResolverInterface $orderStateResolver
     * @param OrderConfig $config
     * @param ShipmentRepositoryInterface $shipmentRepository
     * @param NotifierInterface $notifierInterface
     * @param OrderRegistrarInterface $orderRegistrar
     * @param LoggerInterface $logger
     * @param ShipOrderValidator|null $shipOrderValidator
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        OrderRepositoryInterface $orderRepository,
        ShipmentDocumentFactory $shipmentDocumentFactory,
        ShipmentValidatorInterface $shipmentValidator,
        OrderValidatorInterface $orderValidator,
        OrderStateResolverInterface $orderStateResolver,
        OrderConfig $config,
        ShipmentRepositoryInterface $shipmentRepository,
        NotifierInterface $notifierInterface,
        OrderRegistrarInterface $orderRegistrar,
        LoggerInterface $logger,
        ShipOrderValidator $shipOrderValidator = null
    ) {
        $this->resourceConnection = $resourceConnection;
        $this->orderRepository = $orderRepository;
        $this->shipmentDocumentFactory = $shipmentDocumentFactory;
        $this->orderStateResolver = $orderStateResolver;
        $this->config = $config;
        $this->shipmentRepository = $shipmentRepository;
        $this->notifierInterface = $notifierInterface;
        $this->logger = $logger;
        $this->orderRegistrar = $orderRegistrar;
        $this->shipOrderValidator = $shipOrderValidator ?: ObjectManager::getInstance()->get(
            ShipOrderValidator::class
        );
    }

    /**
     * @param int $orderId
     * @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items
     * @param bool $notify
     * @param bool $appendComment
     * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment
     * @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks
     * @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages
     * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments
     * @return int
     * @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface
     * @throws \Magento\Sales\Api\Exception\CouldNotShipExceptionInterface
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \DomainException
     */
    public function execute(
        $orderId,
        array $items = [],
        $notify = false,
        $appendComment = false,
        \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null,
        array $tracks = [],
        array $packages = [],
        \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null
    ) {
        $connection = $this->resourceConnection->getConnection('sales');
        $order = $this->orderRepository->get($orderId);
        $shipment = $this->shipmentDocumentFactory->create(
            $order,
            $items,
            $tracks,
            $comment,
            ($appendComment && $notify),
            $packages,
            $arguments
        );
        $validationMessages = $this->shipOrderValidator->validate(
            $order,
            $shipment,
            $items,
            $notify,
            $appendComment,
            $comment,
            $tracks,
            $packages
        );
        if ($validationMessages->hasMessages()) {
            throw new \Magento\Sales\Exception\DocumentValidationException(
                __("Shipment Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
            );
        }
        $connection->beginTransaction();
        try {
            $this->orderRegistrar->register($order, $shipment);
            $order->setState(
                $this->orderStateResolver->getStateForOrder($order, [OrderStateResolverInterface::IN_PROGRESS])
            );
            $order->setStatus($this->config->getStateDefaultStatus($order->getState()));
            $this->shipmentRepository->save($shipment);
            $this->orderRepository->save($order);
            $connection->commit();
        } catch (\Exception $e) {
            $this->logger->critical($e);
            $connection->rollBack();
            throw new \Magento\Sales\Exception\CouldNotShipException(
                __('Could not save a shipment, see error log for details')
            );
        }
        if ($notify) {
            if (!$appendComment) {
                $comment = null;
            }
            $this->notifierInterface->notify($order, $shipment, $comment);
        }
        return $shipment->getEntityId();
    }
}

Exceptions

In case of failure, it returns an error object. Example in REST:

{
    "message": "Creditmemo Document Validation Error(s):\nWe can't create creditmemo for the order.\nThe most money available to refund is 0."
}

Extension points

The service contains extension points marked with @api annotation. Extension developers can use APIs to extend service logic.

Extension point Description
\Magento\Sales\Api\OrderRepositoryInterface An interface for saving and retrieving Orders.
\Magento\Sales\Model\Order\OrderStateResolverInterface An interface providing a correct state of an Order according to performed operation.
\Magento\Sales\Api\ShipmentRepositoryInterface An interface for saving and retrieving Shipments.
\Magento\Sales\Model\Order\ShipmentDocumentFactory A factory creating a Shipment data object. The factory uses the arguments parameter to process the extension attributes of a new shipment document.
\Magento\Sales\Model\Order\Shipment\NotifierInterface An interface for sending notifications about new Shipment creation.
\Magento\Sales\Model\Order\Validation\ShipOrderInterface An interface for validating the service parameters and created Shipment data object.
\Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface An interface for registering a Shipment in Order to update amount of shipped items in a given Order according to Shipment. The execute method returns an updated Order.