Creating or updating products with Magento SOAP v2 API - a very challenging adventure

piaoling  2011-06-16 16:30:54

In one of our current projects we have to set up a Magento shop for a customer. This project includes the development of an import / export interface to his ERP system. First, I had to make the decision which of the offered Magento Core API's I'll use: XML-RPC, SOAP or SOAP v2. I personally dislike XML-RPC webservices, so I had a closer look at the older SOAP API and the newer v2 one.

Deciding between the two SOAP alternatives - or "start the fight with the SOAP v2 API"

The biggest advantage of the older version is that is far better documented than the v2 interface - which grade of documentation goes closely to zero. But nevertheless I don't like the architecture of the older SOAP interface. v2 is more document-oriented and better to use. But again: in fact it isn't documented at all. The only thing you can rely on, is the WSDL itself. And if you encounter a problem, you can either try to find a solution with Google's help in some forums or - if your problem still remains - take the trial & error approach and try to find a solution on your own. As there aren't too many search results on Magento Soap v2 problems, you'll might get into the same situation like me, where you have to find a solution on your own. This can be very frustrating, especially if you're used to call and create Webservices with Java and now are facing an undocumented SOAP Webservice with PHP the first time.

How to add the manufacturer or other additional attributes to a product creation or update call

After solving some basic problems, I was very soon able to create and update products and their basic attributes like sku, price, description, status, etc. But when I tried to set the manufacturer of the product, I began to struggle with this simple-looking demand. Every time I tried to update the product, the manufacturer wasn't set. When I logged the request I had sent, I saw, that the SoapClient didn't send the manufacturer information. That means, I didn't set the right types and I violated the WSDL, so the SoapClient wasn't able to translate it and stripped it out of the request.

The difference between basic and additional attributes of a Magento product

Why did the SoapClient strip out the manufacturer info? First, we should know, that a Magento product has some basic attributes, which can be directly set (like sku, name, price, description, etc) and additional attributes. All the self-defined attributes logically go there. The "manufacturer" attribute is pre-defined by Magento, but not included in the attribute set by default. If you include it, it is also part of the additional attributes of the product. Let's now have a short look at the WSDL and examine the "catalogProductCreateEntity" type, which is needed both for creations and upates of products:

<complexType name="catalogProductCreateEntity">
    <all>
        <element minOccurs="0" name="categories" type="typens:ArrayOfString"/>
        <element minOccurs="0" name="websites" type="typens:ArrayOfString"/>
        <element minOccurs="0" name="name" type="xsd:string"/>
        <element minOccurs="0" name="description" type="xsd:string"/>
        <element minOccurs="0" name="short_description" type="xsd:string"/>
        <element minOccurs="0" name="weight" type="xsd:string"/>
        <element minOccurs="0" name="status" type="xsd:string"/>
        <element minOccurs="0" name="url_key" type="xsd:string"/>
        <element minOccurs="0" name="url_path" type="xsd:string"/>
        <element minOccurs="0" name="visibility" type="xsd:string"/>
        <element minOccurs="0" name="category_ids" type="typens:ArrayOfString"/>
        <element minOccurs="0" name="website_ids" type="typens:ArrayOfString"/>
        <element minOccurs="0" name="has_options" type="xsd:string"/>
        <element minOccurs="0" name="gift_message_available" type="xsd:string"/>
        <element minOccurs="0" name="price" type="xsd:string"/>
        <element minOccurs="0" name="special_price" type="xsd:string"/>
        <element minOccurs="0" name="special_from_date" type="xsd:string"/>
        <element minOccurs="0" name="special_to_date" type="xsd:string"/>
        <element minOccurs="0" name="tax_class_id" type="xsd:string"/>
        <element minOccurs="0" name="tier_price" type="typens:catalogProductTierPriceEntityArray"/>
        <element minOccurs="0" name="meta_title" type="xsd:string"/>
        <element minOccurs="0" name="meta_keyword" type="xsd:string"/>
        <element minOccurs="0" name="meta_description" type="xsd:string"/>
        <element minOccurs="0" name="custom_design" type="xsd:string"/>
        <element minOccurs="0" name="custom_layout_update" type="xsd:string"/>
        <element minOccurs="0" name="options_container" type="xsd:string"/>
        <element minOccurs="0" name="additional_attributes" type="typens:associativeArray"/>
        <element minOccurs="0" name="stock_data" type="typens:catalogInventoryStockItemUpdateEntity"/>
    </all>
</complexType>

What we can see here, are all the product attributes that can be set directly because the have their own element defined, and an element called "additional_attributes", which stands next to last. This is the element where we have to place the manufacturer. Its type is "typens:associativeArray", which is also defined in the WSDL. This type is based on the standard "soapenc:Array" type. It's array type is defined as "typens:associativeEntity[]", which is again part of the Magento WSDL. This "associativeEntity" type consists of two string elements: key and value:

<complexType name="associativeEntity">
    <all>
        <element name="key" type="xsd:string"/>
        <element name="value" type="xsd:string"/>
    </all>
</complexType>
<complexType name="associativeArray">
    <complexContent>
        <restriction base="soapenc:Array">
            <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:associativeEntity[]"/>
        </restriction>
    </complexContent>
</complexType>

Building this structure in PHP

Taking the time to analyze and understand the structure of the WSDL was a very big step towards the solution but there were still some problems about where to create an object and where to create an array. Some experiments, coffees and lots of swear words later I finally reached the solution:

The catalogProductCreateEntity itself has to be an stdClass object of course (like all the other request entities in this Webservice). We directly add all the direct attributes as string properties. For the "additional_attributes" property we create an array and then populate it with an stdClass object for every additional attribute we want to add. And these objects have an property "key" and a "value" one. For the manufacturer, our key is "manufacturer" and the value is an ID. So we finally get this call:

$client = new SoapClient($pathToWsdl); // set path to your Magento WSDL
$session = $client->login($apiuser, $apikey); // specify username and password

$catalogProductCreateEntity = new stdClass();
$additionalAttrs = array();

$catalogProductCreateEntity->name = "product name";
$catalogProductCreateEntity->description = "description";
$catalogProductCreateEntity->short_description = "desc";
$catalogProductCreateEntity->status = "1";
$catalogProductCreateEntity->price = "99";
$catalogProductCreateEntity->tax_class_id = "2";
/* you can add other direct attributes here */

$manufacturer = new stdClass();
$manufacturer->key = "manufacturer";
$manufacturer->value = "3";
$additionalAttrs[] = $manufacturer;        
/* you can add other additional attributes here like $manufacturer */

// finally we link the additional attributes to the $catalogProductCreateEntity object
$catalogProductCreateEntity->additional_attributes = $additionalAttrs;

// send the request
$client->catalogProductUpdate($session, "your product id", $catalogProductCreateEntity, NULL, "id");

// end session and enjoy your updated products :)
$client->endSession($session);

I hope, this article can help anyone out there, who faces the same problems. Feel free to comment :-)

Share this

Hi guys,I read your article

Hi guys,

I read your article and code where you're using the function "catalogProductUpdate" to add product to Magento
// send the request
$client->catalogProductUpdate($session, "your product id", $catalogProductCreateEntity, NULL, "id");

 

But I can't find anywhere the APIs with these functions. I'm using API I found at this page http://www.magentocommerce.com/support/magento_core_api

When I add product to Magento using APIs, they go into TheFind Feed extension and not in the Magento catalogue.

Could you help me?

there are 3 ways to call the Magento Webservice API

Hi,

first you have to know that there 3 different ways how you can consume Magento Webservices:

  • XML-RPC
  • SOAP
  • and a different SOAP API, called "SOAP v2"

Here is an overview and some small examples how you can call the first 2 methods: http://www.magentocommerce.com/wiki/doc/webservices-api/introduction

As I have written in the article, the older version is better documented than SOAP v2, which isn't really documented at all. What I did, is to look at the API documentation of v1 (the link that you have provided in your comment) and then search for the equivalent method in the WSDL of the SOAP v2 API. You can find the WSDL of your Magento installation at YOURMAGENTOURL/api/v2_soap?wsdl=1.

In case of the product update, the v1 API call can be found here: http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_product#catalog_product.update. So, for v1 I would have to call "catalog_product.update". When you look at the v2 WSDL, then you'll find this:

<operation name="catalogProductUpdate">

That's why I have called in the example: $client->catalogProductUpdate($session, "your product id", $catalogProductCreateEntity, NULL, "id");

The v2 equivalents are always (or at least almost always!?) written in the same pattern: remove the dots and underscores from the v1 method name and write it in camelcase: catalog_product.update -> catalogProductUpdate

But I personally think that you're problem is a different one. I don't understand what you mean with "When I add product to Magento using APIs, they go into TheFind Feed extension and not in the Magento catalogue." Maybe it would be better, if you provide a code example what you did. I will try my best to support you :-)

from:http://www.agoradesign.at/blog/creating-or-updating-products-magento-soap-v2-api-very-challenging-adventure

类别 :  magento(258)  |  浏览(4004)  |  评论(0)
发表评论(评论将通过邮件发给作者):

Email: