Thursday, December 23, 2010

Create 'Place an Order API' in Magento

12/23/2010

Magento provides a number of web services to ease the life of programmers and users. You will find web services for adding, deleting, listing, editing of products, customers, shipments etc. But Magento lacks a very important web service- Placing Orders. Magento says that it is due to security reasons so that a hacker does not break into your site and place unwanted orders. But no worries, I have found a way out, a simple one. I have developed the web service for placing an order in Magento.



Open the file: app\code\core\Mage\Sales\etc\api.xml
Here search for methods tag inside sales_order parent tag an add the folloeing lines to it
<place translate="title" module="sales">
  <title>Place order</title>
  <acl>sales/order/change</acl>
 </place>
so that the sales_order enclosure looks like:
<config>
    <api>
        <resources>
            <sales_order translate="title" module="sales">
                <model>sales/order_api</model>
                <title>Order API</title>
                <acl>sales/order</acl>
                <methods>
                    <list translate="title" module="sales">
                        <title>Retrieve list of orders by filters</title>
                        <method>items</method>
                        <acl>sales/order/info</acl>
                    </list>
                    <info translate="title" module="sales">
                        <title>Retrieve order information</title>
                        <acl>sales/order/info</acl>
                    </info>
                    <addComment translate="title" module="sales">
                        <title>Add comment to order</title>
                        <acl>sales/order/change</acl>
                    </addComment>
                    <hold translate="title" module="sales">
                        <title>Hold order</title>
                        <acl>sales/order/change</acl>
                    </hold>
                    <unhold translate="title" module="sales">
                        <title>Unhold order</title>
                        <acl>sales/order/change</acl>
                    </unhold>
                    <cancel translate="title" module="sales">
                        <title>Cancel order</title>
                        <acl>sales/order/change</acl>
                    </cancel>
                    <place translate="title" module="sales">
                        <title>Place order</title>
                        <acl>sales/order/change</acl>
                    </place>
                </methods>
    .....
    .....

Now go to the file: app\code\core\Mage\Sales\Model\Order\Api.php
Here at last add the following function:
public function place()
 {
  $customer = Mage::getModel('customer/customer')->load($customerId);/*$customerId is the id of the customer who is placing the order, it can be passed as an argument to the function place()*/

  $transaction = Mage::getModel('core/resource_transaction');
  $storeId = $customer->getStoreId();
  $reservedOrderId = Mage::getSingleton('eav/config')->getEntityType('order')->fetchNewIncrementId($storeId);

  $order = Mage::getModel('sales/order')
  ->setIncrementId($reservedOrderId)
  ->setStoreId($storeId)
  ->setQuoteId(0)
  ->setGlobal_currency_code('USD')
  ->setBase_currency_code('USD')
  ->setStore_currency_code('USD')
  ->setOrder_currency_code('USD');

  // set Customer data
  $order->setCustomer_email($customer->getEmail())
  ->setCustomerFirstname($customer->getFirstname())
  ->setCustomerLastname($customer->getLastname())
  ->setCustomerGroupId($customer->getGroupId())
  ->setCustomer_is_guest(0)
  ->setCustomer($customer);

  // set Billing Address
  $billing = $customer->getDefaultBillingAddress();
  $billingAddress = Mage::getModel('sales/order_address')
  ->setStoreId($storeId)
  ->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_BILLING)
  ->setCustomerId($customer->getId())
  ->setCustomerAddressId($customer->getDefaultBilling())
  ->setCustomer_address_id($billing->getEntityId())
  ->setPrefix($billing->getPrefix())
  ->setFirstname($billing->getFirstname())
  ->setMiddlename($billing->getMiddlename())
  ->setLastname($billing->getLastname())
  ->setSuffix($billing->getSuffix())
  ->setCompany($billing->getCompany())
  ->setStreet($billing->getStreet())
  ->setCity($billing->getCity())
  ->setCountry_id($billing->getCountryId())
  ->setRegion($billing->getRegion())
  ->setRegion_id($billing->getRegionId())
  ->setPostcode($billing->getPostcode())
  ->setTelephone($billing->getTelephone())
  ->setFax($billing->getFax());
  $order->setBillingAddress($billingAddress);

  $shipping = $customer->getDefaultShippingAddress();
  $shippingAddress = Mage::getModel('sales/order_address')
  ->setStoreId($storeId)
  ->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING)
  ->setCustomerId($customer->getId())
  ->setCustomerAddressId($customer->getDefaultShipping())
  ->setCustomer_address_id($shipping->getEntityId())
  ->setPrefix($shipping->getPrefix())
  ->setFirstname($shipping->getFirstname())
  ->setMiddlename($shipping->getMiddlename())
  ->setLastname($shipping->getLastname())
  ->setSuffix($shipping->getSuffix())
  ->setCompany($shipping->getCompany())
  ->setStreet($shipping->getStreet())
  ->setCity($shipping->getCity())
  ->setCountry_id($shipping->getCountryId())
  ->setRegion($shipping->getRegion())
  ->setRegion_id($shipping->getRegionId())
  ->setPostcode($shipping->getPostcode())
  ->setTelephone($shipping->getTelephone())
  ->setFax($shipping->getFax());

  $order->setShippingAddress($shippingAddress)
  ->setShipping_method('flatrate_flatrate')
  ->setShippingDescription('flatrate');

  $orderPayment = Mage::getModel('sales/order_payment')
  ->setStoreId($storeId)
  ->setCustomerPaymentId(0)
  ->setMethod('purchaseorder')
  ->setPo_number(' - ');
  $order->setPayment($orderPayment);

  // let say, we have 2 products
  $subTotal = 0;
  $products = array('1' => array('qty' => 1),'2'=>array('qty' => 3));
  foreach ($products as $productId=>$product) {
  $_product = Mage::getModel('catalog/product')->load($productId);
  $rowTotal = $_product->getPrice() * $product['qty'];
  $orderItem = Mage::getModel('sales/order_item')
  ->setStoreId($storeId)
  ->setQuoteItemId(0)
  ->setQuoteParentItemId(NULL)
  ->setProductId($productId)
  ->setProductType($_product->getTypeId())
  ->setQtyBackordered(NULL)
  ->setTotalQtyOrdered($product['rqty'])
  ->setQtyOrdered($product['qty'])
  ->setName($_product->getName())
  ->setSku($_product->getSku())
  ->setPrice($_product->getPrice())
  ->setBasePrice($_product->getPrice())
  ->setOriginalPrice($_product->getPrice())
  ->setRowTotal($rowTotal)
  ->setBaseRowTotal($rowTotal);

  $subTotal += $rowTotal;
  $order->addItem($orderItem);
  }

  $order->setSubtotal($subTotal)
  ->setBaseSubtotal($subTotal)
  ->setGrandTotal($subTotal)
  ->setBaseGrandTotal($subTotal);

  $transaction->addObject($order);
  $transaction->addCommitCallback(array($order, 'place'));
  $transaction->addCommitCallback(array($order, 'save'));
  $transaction->save(); 
 }


Now our web service is ready to use. Lets call the service to place an order:
<?php
 define('WSDL_URL', 'http://example.com:/api/soap/?wsdl');
 define('WSDL_USER', 'user');
 define('WSDL_KEY', 'password');

try {
  $proxy = new SoapClient(WSDL_URL);    //call magento API 
  $sessionId = $proxy->login(WSDL_USER, WSDL_KEY);//check Valid API Authentications 
   $proxy->call($sessionId, 'sales_order.place');
  echo "Order Placed Successfully!";
 }
catch (Exception $e) 
 {
  echo 'Error in order invoice web service: '.$e->getMessage();
  exit;
 }
?>

And it is all to place an order through web service!

Written by

Arvind is a web developer, programmer and blogger. He has expertise in PHP, Magento, WordPress, jQuery, JavaScript, HTML5 and CSS3. He loves to develop good looking websites with strong backend.

5 comments :

  1. Thanks for writing this stuff up, but I think you should know that it is not best practice to be editing anything in app/code/core. That is reserved for the application core. Modifying these files breaks your upgrade path as these modules will be overwritten. The correct method is to create your own local module, rewrite the model in the config and extend the original class. See some info on this here: http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-1-introduction-to-magento

    ReplyDelete
  2. Hi,

    I am getting "Invalid api path" error. can you please help me on this?

    -

    Sanket

    ReplyDelete
  3. can i knaow abt how it will show in wsdl file.

    ReplyDelete
  4. Great post. Could you show an exmaple of a complete API call to create an order?

    ReplyDelete
    Replies
    1. please provide complete example how to place order using magento soap api call.as soap api has already a method cart.order but it do not do any thing.justfake

      Delete

We would love to hear from you...

 

© 2014 Web Speaks . All rights resevered. Designed by Templateism