...

API SOAP e Cron: integrare Magento con servizi esterni

by andrea-de-pirro

on

Report

Category:

Software

Download: 0

Comment: 0

930

views

Comments

Description

Magento offre due funzionalità normalmente trascurate da sviluppatori e commercianti nonostante le loro potenzialità: le API SOAP e il sistema Cron.
Le API SOAP di Magento permettono di gestire i negozi eCommerce e integrarli con servizi esterni, fornendo accesso a risorse quali clienti, categorie, prodotti e ordini. Consentono inoltre la gestione dei carrelli e dell’inventario.
Molto spesso, però, le API offerte non bastano a soddisfare le esigenze di un commerciante. Grazie alla sua estensibilità, Magento permette di ampliare le funzionalità native delle API, ad esempio per restituire più informazioni riguardanti un prodotto, per aggiungere la possibilità di importare un ordine, o addirittura creare nuove operazioni per manipolare le RMA.
Magento, inoltre, offre alcuni task, come l’aggiornamento automatico delle valute e la generazione di report, e soprattutto consente di programmarne a piacere con una configurazione XML, in modo simile al crontab di UNIX.

L’intervento di Andrea De Pirro è volto a spiegare come creare un semplice modulo per estendere le API Magento esistenti e aggiungerne di nuove, sfruttando al tempo stesso il sistema di Cron. Userà esempi reali corredati da consigli utili per sviluppare estensioni per esportare e importare prodotti, ordini e RMA.
Download API SOAP e Cron: integrare Magento con servizi esterni

Transcript

  • 1.@akira28 Chi Sono • Co-fondatore di Yameveo • 9 anni sviluppando in PHP • Più di 3 anni di esperienza con Magento • Lead developer di progetti Magento per Privalia, Reckitt Benckiser e Groupalia • Zend Framework Certified Engineer
  • 2. @akira28 Yameveo Fondata nel 2012 a Barcellona, Yameveo è una società giovane, dinamica ed internazionale, specializzata 
 nell’e-commerce e nello sviluppo di applicazioni web. ! ! www.yameveo.com @Yameveo
  • 3. @akira28 Yameveo Store Decine di moduli per Magento e Prestashop store.yameveo.com
  • 4. @akira28 Di cosa parleremo • Intro alle API SOAP di Magento • Estensione delle API Magento • Estensione 3rd party • Creare una nuova chiamata API • Il sistema Cron di Magento
  • 5. @akira28 Magento SOAP “Le API SOAP di Magento offrono la possibilità di gestire i negozi e-commerce, fornendo chiamate per lavorare con risorse quali clienti, categorie, prodotti e ordini. Consentono inoltre di gestire i carrelli e l'inventario.” Documentazione Magento
  • 6. @akira28 Applicazioni • Integrazione con operatori logistici • Integrazione con Warehouse • Integrazione con CRM ed ERP • Integrazione con altri servizi via middleware • App mobile • …
  • 7. @akira28 API Magento Quando viene effettuata una richiesta HTTP il sistema di routing standard di Magento invia la richiesta ad una action del controller del modulo Mage_Api ! Questa action istanzia un oggetto "Server API", lo inizializza con il tipo di API (SOAP, XML-RPC, etc.), ed in seguito chiama il suo metodo “run”
  • 8. @akira28 Come iniziare • Assicurati che l’endpoint sia accessibile:
 www.example.com/api/v2_soap
 www.example.com/api/soap • Definisci Utenti API e le risorse associate:
 System -> Web Services • Dai un’occhiata al WSDL
 www.example.com/api/v2_soap?wsdl=1
 www.example.com/api/soap?wsdl=1
  • 9. @akira28 Magento API flow • Crea un Session ID effettuando una richiesta “login” con username e API key • Salva il Session ID per effettuare altre chiamate • Effettua le altre chiamate passando il Session ID • Termina la sessione con endSession
  • 10. @akira28 Testing API V1 // connect to soap server $client = new SoapClient('http://apimagento.dev/api/soap?wsdl=1', array('cache_wsdl' => WSDL_CACHE_NONE, 'trace' => 1)); ! // log in $session = $client->login('user', ‘password’); ! $info = $client->call($session, 'catalog_product.info', '4'); ! var_export($client->__getLastRequest()); http://www.php.net/manual/en/class.soapclient.php
  • 11. @akira28 Esempio request V1 <?xml version="1.0" encoding="utf-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP- ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:call> <sessionId xsi:type="xsd:string">24eafa404acbd904f3c0978669102496</sessionId> <resourcePath xsi:type="xsd:string">catalog_product.info</resourcePath> <args xsi:type="xsd:int">4</args> </ns1:call> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
  • 12. @akira28 Esempio response V1 array(6) { 'product_id' => string(3) "4" 'sku' => string(3) “sku-1“ 'set' => string(2) "41" 'type' => string(12) "configurable" 'categories' => array(1) { [0] => string(1) "4" } 'websites' => array(1) { [0] => string(1) "1" } }
  • 13. @akira28 Testing API V2 // connect to soap server $client = new SoapClient('http://apimagento.dev/api/v2_soap?wsdl=1', array('cache_wsdl' => WSDL_CACHE_NONE, 'trace' => 1)); ! // log in $session = $client->login('user', ‘password'); ! $complexFilter = array( 'complex_filter' => array( array( 'key' => 'type', 'value' => array('key' => 'eq', 'value' => 'configurable') ) ) ); $list = $client->catalogProductList($session, $complexFilter); ! var_export($client->__getLastRequest());
  • 14. @akira28 Esempio request V2 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http:// schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/ encoding/"> <SOAP-ENV:Body> <ns1:catalogProductList> <sessionId xsi:type="xsd:string">c84d5edf23f22913066f4246d0949908</sessionId> <filters xsi:type="ns1:filters"> <complex_filter SOAP-ENC:arrayType="ns1:complexFilter[1]" xsi:type="ns1:complexFilterArray"> <item xsi:type="ns1:complexFilter"> <key xsi:type="xsd:string">type</key> <value xsi:type="ns1:associativeEntity"> <key xsi:type="xsd:string">eq</key> <value xsi:type="xsd:string">configurable</value> </value> </item> </complex_filter> </filters> <storeView xsi:nil="true" /> </ns1:catalogProductList> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
  • 15. @akira28 Esempio response V2 array(118) { [0] => class stdClass#2 (9) { public $product_id => string(2) "16" public $sku => string(5) "n2610" public $name => string(16) "Nokia 2610 Phone" public $set => string(2) "38" public $type => string(6) "configurable" public $category_ids => array(1) { [0] => string(1) "8" } public $website_ids => array(1) { [0] => string(1) "1" } public $price => double(149.99) public $available_quantity => int(996) } […]
  • 16. @akira28 abstract class Mage_Api_Model_Server_Handler_Abstract { public function startSession(){[…]} ! public function endSession($sessionId){[…]} ! public function login($username, $apiKey){[…]} ! public function call($sessionId, $apiPath, $args = array()){[…]} public function multiCall($sessionId, array $calls = array(), $options = array()){[…]} public function resources($sessionId){[…]} public function globalFaults($sessionId){[…]} public function resourceFaults($sessionId, $resourceName){[…]} ! } ! app/code/core/Mage/Api/Model/Server/Handler/Abstract.php API SOAP Handler
  • 17. @akira28 Differenze API V1 e V2 • V2 è adatta ad applicazioni scritte in linguaggi tipizzati come Java o .NET • Il WSDL V2 è molto più grande • Nella V2 esiste un metodo per ogni chiamata:
 V1 - $client->call($sid, ’catalog_product.info’, …);
 V2 - $client->catalogProductInfo($sid, …);
  • 18. @akira28
  • 19. @akira28 Problemi • Le chiamate native non contengono abbastanza informazioni • Le estensioni di terze parti quasi mai offrono API • Non esistono call per alcune risorse
  • 20. @akira28 Soluzioni • Estensione delle API native • Inclusione delle estensioni di terze parti • Nuove call API
  • 21. Estensione delle API native
  • 22. @akira28 Estensione ProductInfo • Configurazione del modulo • Codice PHP • WSDL
  • 23. @akira28 Estensione ProductInfo - config […] <global> <models> […] <catalog> <rewrite> <product_api>Yameveo_Productinfo_Model_Catalog_Product_Api</product_api> <product_api_v2>Yameveo_Productinfo_Model_Catalog_Product_Api_V2</product_api_v2> </rewrite> </catalog> […] ! Yameveo/Productinfo/etc/config.xml
  • 24. @akira28 class Yameveo_Productinfo_Model_Catalog_Product_Api extends Mage_Catalog_Model_Product_Api { […] public function info($productId, $store = null, $attributes = array(), $identifierType = null) { $product = $this->_getProduct($productId, $store, $identifierType); […] return $this->infoResult($result, $product, $attributes, $store); } […] Yameveo/Productinfo/Model/Catalog/Product/Api.php ProductInfo - codice
  • 25. @akira28 ProductInfo - codice class Yameveo_Productinfo_Model_Catalog_Product_Api extends Mage_Catalog_Model_Product_Api { […] protected function infoResult($result, $product, $attributes, $store) { […] } elseif ($product->isConfigurable()) { $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product); $skus = array(); foreach ($childProducts as $childProduct) { $skus[$childProduct->getId()][‘sku’] = $childProduct->getSku(); […] } $result['configurable_products_data'] = $skus; […] return $result; } } Yameveo/Productinfo/Model/Catalog/Product/Api.php
  • 26. @akira28 Estensione ProductInfo - wsdl […] <complexType name="catalogProductReturnEntity"> <all> […] <element name="configurable_products_data" type="typens:childrenEntityArray" minOccurs="0"/> […] </all> </complexType> ! <complexType name="childrenEntityArray"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:childrenEntity[]"/> </restriction> </complexContent> </complexType>
 <complexType name="childrenEntity"> <all> <element name="sku" type="xsd:string" minOccurs=“0"/> […] </all> </complexType> […] ! Yameveo/Productinfo/etc/wsdl.xml
  • 27. Inclusione delle estensioni di terze parti
  • 28. @akira28 Estensione OrderApi • Configurazione del modulo • Codice PHP • WSDL
  • 29. @akira28 M2E Pro
  • 30. @akira28 Estensione OrderApi - config ! […] <models> <yameveo_orderapi> <class>Yameveo_OrderApi_Model</class> </yameveo_orderapi> <sales> <rewrite> <order_api>Yameveo_OrderApi_Model_Order_Api</order_api> <order_api_v2>Yameveo_OrderApi_Model_Order_Api_V2</order_api_v2> </rewrite> </sales> </models> […] Yameveo/OrderApi/etc/config.xml
  • 31. @akira28 Estensione M2ePro - codice class Yameveo_OrderApi_Model_Order_Api extends Mage_Sales_Model_Order_Api { public function info($orderIncrementId) { $result = parent::info($orderIncrementId); $ebayOrder = Mage::helper('M2ePro/Component_Ebay') ->getCollection('Order') ->addFieldToFilter('magento_order_id', $result['order_id']) ->getFirstItem(); ! if ($ebayOrder->getData('ebay_order_id')) { $result['ebay'] = array(); $result['ebay']['ebay_order_id'] = $ebayOrder->getData('ebay_order_id'); $result['ebay']['selling_manager_record_number'] = $ebayOrder->getData('selling_manager_record_number'); […] foreach ($ebayOrder->getItemsCollection() as $item) { $itemArray = array( […] 'buy_it_now_price' => $item->getData('buy_it_now_price'), […] ); ! $result['ebay']['items'][] = $itemArray; } } return $result; } […] Yameveo/OrderApi/Model/Order/Api.php
  • 32. @akira28 Estensione M2ePro - wsdl […] <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> <complexType name="salesOrderEntity"> <all> <element name="ebay" type="typens:ebayOrder" minOccurs="0" maxOccurs="1"/> </all> </complexType> <complexType name="ebayOrder"> <all> <element name="ebay_order_id" type="xsd:string" minOccurs="0" maxOccurs="1"/> <element name="items" type="typens:ebayOrderItems" minOccurs="0" /> […] </all> </complexType> <complexType name="ebayOrderItems"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:ebayOrderItem[]" /> </restriction> </complexContent> </complexType> <complexType name=“ebayOrderItem"> […] <element name="buy_it_now_price" type="xsd:string" minOccurs="0" maxOccurs=“1"/> […] </complexType> […] Yameveo/OrderApi/etc/wsdl.xml
  • 33. Nuova call API
  • 34. @akira28 Estensione RmaApi • Configurazione del modulo • Codice PHP • WSDL
  • 35. @akira28 RmaApi - config <config> <modules> <Yameveo_RmaApi> <version>1.0</version> </Yameveo_RmaApi> </modules> <global> <models> <rma> <class>Yameveo_RmaApi_Model</class> </rma> </models> <helpers> <rma> <class>Yameveo_RmaApi_Helper</class> </rma> </helpers> </global> </config> Yameveo/RmaApi/etc/config.xml
  • 36. @akira28 RMA API api.xml <config> <api> <resources> <rma translate="title" module="rmaapi"> <model>rma/api</model> <title>Rma Resource</title> <acl>rma</acl> <methods> <info translate="title" module="rmaapi"> <title>Retrieve RMA information</title> <method>info</method> <acl>rma/info</acl> </info> </methods> <faults module="rmaapi"> <invalid_protocol> <code>106</code> <message>This operation available through SOAP v2 only.</message> </invalid_protocol> </faults> </rma> </resources> <resources_alias> <rma>rma</rma> </resources_alias> <v2> <resources_function_prefix> <rma>rma</rma> </resources_function_prefix> </v2> <acl> <resources> <rma translate="title" module="rmaapi"> <info translate="title" module="rmaapi"> <title>Retrieve RMA information</title> </info> </rma> </resources> </acl> </api> </config> Yameveo/RmaApi/etc/api.xml
  • 37. @akira28 RmaApi - codice class Yameveo_RmaApi_Model_Api extends Mage_Api_Model_Resource_Abstract { /** * Info on RMA * * @param string $incrementId * @return info */ public function info($incrementId) { $rma = Mage::getModel('enterprise_rma/rma') ->getCollection() ->addFieldToFilter('increment_id', $incrementId) ->getFirstItem(); $rmaData = $rma->getData(); foreach ($rma->getItemsForDisplay() as $item) { $rmaData['items'][] = $item->getData(); } $comments = Mage::getResourceModel('enterprise_rma/rma_status_history_collection') ->addFilter('rma_entity_id', $rma->getId()); foreach ($comments as $comment) { $rmaData['comments'][] = $comment->getData(); } $rmaData['shipping_label'] = $rma->getShippingLabel()->getData(); ! return $rmaData; } Yameveo/RmaApi/Model/Api.php
  • 38. @akira28 RmaApi - wsdl […] <message name="rmaInfoRequest"> <part name="sessionId" type="xsd:string"/> <part name="rmaIncrementId" type="xsd:string"/> </message> <message name="rmaInfoResponse"> <part name="result" type="typens:rmaExportEntity"/> </message> [...] <portType name="{{var wsdl.handler}}PortType"> <operation name="rmaInfo"> <documentation>Info on RMA</documentation> <input message="typens:rmaInfoRequest"/> <output message="typens:rmaInfoResponse"/> </operation> </portType> <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> <operation name="rmaInfo"> <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> <input> <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding>
  • 39. @akira28 RmaApi - wsdl <complexType name="rmaExportEntity"> <all> [...] <element name="customer_custom_email" type="xsd:string" minOccurs="0" maxOccurs="1"/> <element name="items" type="typens:rmaExportEntityItemsArray" minOccurs="1" maxOccurs="1"/> [...] </all> </complexType> <complexType name="rmaExportEntityItemsArray"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:rmaExportEntityItem[]"/> </restriction> </complexContent> </complexType> <complexType name="rmaExportEntityItem"> <all> [...] <element name="product_sku" type="xsd:string" minOccurs="0"/> [...] </all> </complexType> Yameveo/RmaApi/etc/wsdl.xml
  • 40. @akira28
  • 41. @akira28 Cos’altro si può fare con le API • Esportare ed importare ordini, prodotti, clienti • Checkout via SOAP per applicazioni esterne • Creare promozioni • Gestire il CMS • …. • Le possibilità sono infinite!
  • 42. @akira28 Magento Cron • Cos’è • Come funziona • Come può risultare utile • Come si crea un task
  • 43. @akira28 Magento Cron ! • Il meccanismo Cron di Magento viene attivato periodicamente utilizzando un cronjob del sistema • La chiamata viene avviata nel file di cron.php • Il codice in cron.php invoca Mage_Cron_Model_Observer → dispatch(), che a sua volta provvederà a: • eseguire le operazioni pianificate • generare, se necessario, task da eseguire in futuro • ripulire la history delle operazioni eseguite
  • 44. @akira28 Utilizzi del cron • Export automatico • Report ordini giornaliero • Aggiornamento statistiche • Invio mail per cart abbandonati • …
  • 45. @akira28 Creare un task cron - config […] <crontab> <jobs> <yameveo_export> <schedule> <cron_expr>0 2 * * *</cron_expr> </schedule> <run> <model>yameveo/observer::inventoryExport</model> </run> </yameveo_export> </jobs> </crontab> […] Yameveo/Export/etc/config.xml
  • 46. @akira28 Creare un task cron - codice class Yameveo_Export_Model_Observer extends Mage_Core_Model_Observer { /** * Cron method to export the complete product inventory to the configured ftp server */ public function inventoryExport() { $products = Mage::getModel(‘catalog/product’)->getCollection(); // build data to export foreach ($products as $product) {
 […] } $this->sendToFtp($data); } […] } Yameveo/Export/Model/Observer.php
  • 47. @akira28 Configurare cron da backend […] <settings translate="label" module=“yameveo_export"> […] <fields> <cron_settings translate="label comment" module="yameveo_export"> <label>How often do you want the cron to run?</label> <frontend_type>text</frontend_type> <sort_order>70</sort_order> <comment>Use Crontab Format (Eg. "0 4 * * *" for every day at 4 a.m.)</comment> <show_in_default>1</show_in_default> </cron_settings> </fields> </settings> […] Yameveo/etc/system.xml
  • 48. @akira28 Configurare cron da backend […] <crontab> <jobs> <yameveo_export> <schedule> <config_path>export_config/settings/cron_settings</config_path> </schedule> <run> <model>yameveo_export/observer::inventoryExport</model> </run> </yameveo_export> </jobs> </crontab> […] Yameveo/Export/etc/config.xml
  • 49. Volete vedere altro codice?
  • 50. @akira28
  • 51. @akira28 Risorse • www.yameveo.com • github.com/Yameveo • twitter.com/Yameveo • alanstorm.com • www.magentocommerce.com/api
  • 52. Domande?
  • 53. Grazie! www.yameveo.com ! @akira28 @Yameveo ! http://bit.ly/andreadepirro
  • 54. @akira28 yameveo@yameveo.com STIAMO ASSUMENDO!
  • Fly UP