magentomagento2magento-rest-api

Order status updates via rest api in magento 2


I'm working on magento 2.3.3. I've stuck in one place while was doing method that receives callbacks from custom payment gateway via magento web api. The main idea is to redirect customer to my custom gateway (that I've done) and after paying order this custom gateway has to send callback to magento's web api and update the order status. The webapi.xml:

<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/orders/:id/statuses" method="POST">
          <service class="TarlanPay\TarlanPay\Api\Setorderstatus"
          method="status"/>  
    <resources>
        <resource ref="anonymous"/>
    </resources>
     <data>
        <parameter name="orderId" force="true">%reference_id%</parameter>
    </data>
</route>    

The main idea is to redirect customer to my custom gateway (that I've done) and after paying order this custom gateway has to send callback to magento's web api and update the order status. For now I've set web api and wrote the appropriate method to receive callbacks from gateway.

namespace TarlanPay\TarlanPay\Api;
Interface Setorderstatus{
/**
* @api
* @param int $id
* @return string
*/
 public function status($id);
} 

The code above shows my interface that I've set in webapi.xml. The code below shows the class that implements this interface and has method that has to update order status.

namespace TarlanPay\TarlanPay\Model;
use TarlanPay\TarlanPay\Api\Setorderstatus;
use \Magento\Sales\Model\Order;
use \Magento\Sales\Api\OrderRepositoryInterface;
/**
* @api
*/
Class SetorderstatusModel implements Setorderstatus, OrderRepositoryInterface{
    public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria){}
    public function get($id){}
    public function delete(\Magento\Sales\Api\Data\OrderInterface $entity){}
    public function save(\Magento\Sales\Api\Data\OrderInterface $entity){}
    /**
    * @return Model\SetorderstatusModel
    */
public function status($id){
    $tarlanResponse = file_get_contents('php://input');
    $tarlanData = json_decode($tarlanResponse, true);
    if(!empty($tarlanResponse)){
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $order = $objectManager->create('Magento\Sales\Api\Data\OrderInterface')->load($id);
        switch($tarlanData['status']){
            case 0:
            $order->setState(\Magento\Sales\Model\Order::STATE_PENDING)->setStatus(\Magento\Sales\Model\Order::STATE_PENDING);
            $order->save();
            break;
            case 1:
            $order->setState(\Magento\Sales\Model\Order::STATE_COMPLETE)->setStatus(\Magento\Sales\Model\Order::STATE_COMPLETE);
            $order->save();
            break;
            case 3:
            $order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)->setStatus(\Magento\Sales\Model\Order::STATE_PROCESSING);
            $this->_orderRepository->save($order);
            break;
            case 4:
            $order->setState(\Magento\Sales\Model\Order::STATE_CANCEL)->setStatus(\Magento\Sales\Model\Order::STATE_CANCEL);
            $this->_orderRepository->save($order);
            break;
            case 5:
            $order->setState(\Magento\Sales\Model\Order::STATE_CLOSED)->setStatus(\Magento\Sales\Model\Order::STATE_CLOSED);
            $this->_orderRepository->save($order);
            break;
            case 6:
            $order->setState(\Magento\Sales\Model\Order::STATE_FAIL)->setStatus(\Magento\Sales\Model\Order::STATE_FAIL);
            $this->_orderRepository->save($order);
            break;
            default:
            echo 'something';
            break;
        }
    }
    return true;
}
} 

The problem is, when I try to send some status through the postman, it returns me "400 Bad Request" and "message": "Please provide payment for the order.". Any help will be apreciated.here is Postman's request


Solution

  • I still have no idead why it asked me to provide payment for the order. But now it's gone. And also I've faced another issue. When I tried to update status to complete it didn't work. Now I solved this one as well. It was because magento didn't register my order as invoiced order, thus it couldn't be as completed order. This is final code:

    namespace TarlanPay\TarlanPay\Model;
     use TarlanPay\TarlanPay\Api\Setorderstatus;
     use \Magento\Sales\Model\Order;
     use \Magento\Sales\Api\OrderRepositoryInterface;
     use \Magento\Checkout\Model\Session;
     use \Magento\Sales\Model\Service\InvoiceService;
    
    /**
    * @api
    */
    
    Class SetorderstatusModel implements Setorderstatus, OrderRepositoryInterface{
    
    public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria){}
    public function get($id){}
    public function delete(\Magento\Sales\Api\Data\OrderInterface $entity){}
    public function save(\Magento\Sales\Api\Data\OrderInterface $entity){}
      /**
      * @return Model\SetorderstatusModel
      */
    public function status($id){
    $tarlanResponse = file_get_contents('php://input');
    $tarlanData = json_decode($tarlanResponse, true);
    if(!empty($tarlanResponse)){
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $invoice = $objectManager->create('\Magento\Sales\Model\Service\InvoiceService');
        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($id); // This is to correctly pass an argument that has been set in web api's url. For example my url looks like this - magento2/rest/V1/orders/12/statuses. Where 12 is order entity id.
        $invoice = $invoice->prepareInvoice($order); //this invoice is to update your status to complete
        $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); //this invoice is to update your status to complete
        $invoice->register(); //this invoice is to update your status to complete
        switch($tarlanData['status']){
            case 0:
            $orderState = Order::STATE_PENDING_PAYMENT;
            $order->setState($orderState)->setStatus(Order::STATE_PENDING_PAYMENT);
            $order->save();
            break;
            case 1:
            $orderState = Order::STATE_COMPLETE;
            $order->setState($orderState)->setStatus(Order::STATE_COMPLETE);
            $order->save();
            break;
            case 2:
            $orderState = Order::STATE_PROCESSING;
            $order->setState($orderState)->setStatus(Order::STATE_PROCESSING);
            $order->save();
            break;
            case 3:
            $orderState = Order::STATE_PROCESSING;
            $order->setState($orderState)->setStatus(Order::STATE_PROCESSING);
            $order->save();
            break;
            case 4:
            $orderState = Order::STATE_CANCELED;
            $order->setState($orderState)->setStatus(Order::STATE_CANCELED);
            $order->save();
            break;
            case 5:
            $orderState = Order::STATE_CLOSED;
            $order->setState($orderState)->setStatus(Order::STATE_CLOSED);
            $this->_orderRepository->save($order);
            break;
            case 6:
            $orderState = Order::STATE_CANCELED;
            $order->setState($orderState)->setStatus(Order::STATE_CANCELED);
            $order->save();
            break;
            default:
            echo 'something';
            break;
        }
    }
      return true;
     }
     }