2012-01-22 9 views
11

¡Buen día!Cómo creo un producto con atributos adicionales en Magento a través de Soap/Java

me gustaría utilizar SOAP API del Magento para gestionar el catálogo de productos, atributos, etc. Estoy corriendo siguiente configuración: - cumplimiento

  • Magento 1.6
  • API SOAP WS-I
  • Mac OS X Lion
  • Mamp 2.0.5

En caso de que alguien quiere crear un nuevo producto, es necesario fijar una Fe w propiedades del objeto del producto. siguiente código demostrará mi método para hacer esto:

public int createProduct(DatabaseProduct product) { 

     ArrayOfString categories = new ArrayOfString(); 
       categories.getComplexObjectArray().add(categoryID); 
     createEntity.setCategoryIds(categories); 

     CatalogProductCreateEntity createEntity = populateCreateOrUpdateEntity(product); 

     CatalogProductCreateRequestParam param = new CatalogProductCreateRequestParam(); 
     param.setSessionId(sessionId); 
     param.setSet(setId); 
     param.setSku(product.getSku()); 
     param.setType("simple"); 
     param.setStore(storeId); 
     param.setProductData(createEntity); 

     CatalogProductCreateResponseParam response = service.catalogProductCreate(param); 
     return response.getResult(); 
    } 

    private CatalogProductCreateEntity populateCreateOrUpdateEntity(DatabaseProduct product) { 

     CatalogProductCreateEntity createEntity = new CatalogProductCreateEntity(); 
     createEntity.setShortDescription(product.getDescription().substring(0, 20) + "..."); 
     createEntity.setDescription(product.getDescription()); 
     createEntity.setName(product.getName()); 
     createEntity.setPrice(String.valueOf(product.getPrice())); 
     createEntity.setStatus("1"); //active 
     createEntity.setVisibility("4"); //visible in search/catalog 
     createEntity.setWeight("70"); //some value 
     createEntity.setTaxClassId("2"); //standard 

      AssociativeArray attributes = new AssociativeArray();    

      AssociativeEntity attr1 = new AssociativeEntity(); 
      attr1.("attribute1_key"; 
      attr1.("attribute1_value"); 
      attributes.getComplexObjectArray().add(attr1); 

      AssociativeEntity attr2 = new AssociativeEntity(); 
      attr2.("attribute2_key"); 
      attr2.("attribute2_value"); 
      attributes.getComplexObjectArray().add(attr2); 

     createEntity.setAdditionalAttributes(attributes); 

     return createEntity; 
    } 

me di cuenta que me da un error por escrito a la "system.log" de Magento.

2012-01-21T09:41:01+00:00 DEBUG (7): First parameter must either be an object or the name of an existing class/opt/website/magento/app/code/core/Mage/Catalog/Model/Product/Api/V2.php 

pude localizar el error en el archivo "V2.php" en la línea 265. De acuerdo con la documentación de php.net el método "property_exists()" sólo puede comprobar campos de objetos. De hecho, la variable "$productData" tiene una propiedad llamada "additional_attributes" que es del tipo array. Por lo tanto, la ejecución de este código dará lugar a un error.

Además, no sé reproducir el objeto de la estructura del objeto "$productData" mediante el uso de SOAP API V2 de Magento.

Si examino este código ("foreach 'loop) en la línea 270, indica que hay un objeto (' $productData ') que sostiene una matriz (' additional_attributes"), que de nuevo se encapsular un conjunto de pares clave/valor (si estoy en lo cierto)

253  protected function _prepareDataForSave ($product, $productData) 
254  { 
255   if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) { 
256    $product->setWebsiteIds($productData->website_ids); 
257   } 
258 
259   Mage::log("debug1"); 
260   Mage::log(property_exists($productData, 'additional_attributes')); 
261   
262   Mage::log($productData); 
263   
264   if (property_exists($productData, 'additional_attributes')) { 
265    if (property_exists($productData->additional_attributes, 'single_data')) { 
266     
267     Mage::log("---> single"); 
268     Mage::log($productData->additional_attributes); 
269     
270     foreach ($productData->additional_attributes->single_data as $_attribute) { 
271      $_attrCode = $_attribute->key; 
272      $productData->$_attrCode = $_attribute->value; 
273     } 
274    } 
275    if (property_exists($productData->additional_attributes, 'multi_data')) { 
276     
277     Mage::log("---> multi"); 
278     Mage::log($productData->additional_attributes); 
279     
280     foreach ($productData->additional_attributes->multi_data as $_attribute) { 
281      $_attrCode = $_attribute->key; 
282      $productData->$_attrCode = $_attribute->value; 
283     } 
284    } 
285     
286    Mage::log("debugXXX"); 
287    unset($productData->additional_attributes); 
288   } 
289   
290   Mage::log("debug2"); 
291   
292   foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { 
293    $_attrCode = $attribute->getAttributeCode(); 
294    if ($this->_isAllowedAttribute($attribute) && (isset($productData->$_attrCode))) { 
295     $product->setData(
296   ... etc ... 

Esto parece ser un error. Ésta es mi pregunta.

¿Voy directamente a llamar a esto un problema de programación que se publicará en la base de errores? ¿Hay alguna manera de superar este problema? ¿Debo reescribir partes de php.code desde arriba para satisfacer mi necesidad de manejar la información del producto para crear un producto correctamente?

Gracias de antemano

$productData 
    (
      [name] => testname 
      [description] => testdescription 
      [short_description] => shorttestdescription 
      [weight] => 70 
      [status] => 1 
      [visibility] => 4 
      [price] => 359.0 
      [tax_class_id] => 2 
      [additional_attributes] => Array 
      (
        [attribute1] => 999.0 
        [attribute2] => testcontent 
      ) 
    ) 

la CatalogProductCreate-llamada desde el WSDL generado por SoapUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Magento"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <urn:catalogProductCreateRequestParam> 
     <sessionId>?</sessionId> 
     <type>?</type> 
     <set>?</set> 
     <sku>?</sku> 
     <productData> 
      <!--Optional:--> 
      <categories> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </categories> 
      <!--Optional:--> 
      <websites> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </websites> 
      <!--Optional:--> 
      <name>?</name> 
      <!--Optional:--> 
      <description>?</description> 
      <!--Optional:--> 
      <short_description>?</short_description> 
      <!--Optional:--> 
      <weight>?</weight> 
      <!--Optional:--> 
      <status>?</status> 
      <!--Optional:--> 
      <url_key>?</url_key> 
      <!--Optional:--> 
      <url_path>?</url_path> 
      <!--Optional:--> 
      <visibility>?</visibility> 
      <!--Optional:--> 
      <category_ids> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </category_ids> 
      <!--Optional:--> 
      <website_ids> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </website_ids> 
      <!--Optional:--> 
      <has_options>?</has_options> 
      <!--Optional:--> 
      <gift_message_available>?</gift_message_available> 
      <!--Optional:--> 
      <price>?</price> 
      <!--Optional:--> 
      <special_price>?</special_price> 
      <!--Optional:--> 
      <special_from_date>?</special_from_date> 
      <!--Optional:--> 
      <special_to_date>?</special_to_date> 
      <!--Optional:--> 
      <tax_class_id>?</tax_class_id> 
      <!--Optional:--> 
      <tier_price> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray> 
        <!--Optional:--> 
        <customer_group_id>?</customer_group_id> 
        <!--Optional:--> 
        <website>?</website> 
        <!--Optional:--> 
        <qty>?</qty> 
        <!--Optional:--> 
        <price>?</price> 
       </complexObjectArray> 
      </tier_price> 
      <!--Optional:--> 
      <meta_title>?</meta_title> 
      <!--Optional:--> 
      <meta_keyword>?</meta_keyword> 
      <!--Optional:--> 
      <meta_description>?</meta_description> 
      <!--Optional:--> 
      <custom_design>?</custom_design> 
      <!--Optional:--> 
      <custom_layout_update>?</custom_layout_update> 
      <!--Optional:--> 
      <options_container>?</options_container> 
      <!--Optional:--> 
      <additional_attributes> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray> 
        <key>?</key> 
        <value>?</value> 
       </complexObjectArray> 
      </additional_attributes> 
      <!--Optional:--> 
      <stock_data> 
       <!--Optional:--> 
       <qty>?</qty> 
       <!--Optional:--> 
       <is_in_stock>?</is_in_stock> 
       <!--Optional:--> 
       <manage_stock>?</manage_stock> 
       <!--Optional:--> 
       <use_config_manage_stock>?</use_config_manage_stock> 
       <!--Optional:--> 
       <min_qty>?</min_qty> 
       <!--Optional:--> 
       <use_config_min_qty>?</use_config_min_qty> 
       <!--Optional:--> 
       <min_sale_qty>?</min_sale_qty> 
       <!--Optional:--> 
       <use_config_min_sale_qty>?</use_config_min_sale_qty> 
       <!--Optional:--> 
       <max_sale_qty>?</max_sale_qty> 
       <!--Optional:--> 
       <use_config_max_sale_qty>?</use_config_max_sale_qty> 
       <!--Optional:--> 
       <is_qty_decimal>?</is_qty_decimal> 
       <!--Optional:--> 
       <backorders>?</backorders> 
       <!--Optional:--> 
       <use_config_backorders>?</use_config_backorders> 
       <!--Optional:--> 
       <notify_stock_qty>?</notify_stock_qty> 
       <!--Optional:--> 
       <use_config_notify_stock_qty>?</use_config_notify_stock_qty> 
      </stock_data> 
     </productData> 
     <!--Optional:--> 
     <store>?</store> 
     </urn:catalogProductCreateRequestParam> 
    </soapenv:Body> 
</soapenv:Envelope> 
+0

¿Cuál es la salida de 'product_data'? pegar aquí –

Respuesta

8

Para el SOAP API V2 parece que necesitamos para anidar los additional_attributes en un multi_data o capa single_data?

En cuanto a aplicación/código/core/Mago/Catálogo/modelo/producto/API/V2.php # 256 Creo que tenemos que utilizar

$manufacturer = new stdClass(); 
$manufacturer->key = "manufacturer"; 
$manufacturer->value = "20"; 
$additionalAttrs['single_data'][] = $manufacturer; 

o

$manufacturer = new stdClass(); 
$manufacturer->key = "manufacturer"; 
$manufacturer->value = "20"; 
$additionalAttrs['multi_data'][] = $manufacturer; 

estar usado como:

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

      // manufacturer from one of the two above^

    $productData->name     = $data['name']; 
    $productData->description   = $data['description']; 
    $productData->short_description  = $data['short_description']; 
    $productData->weight     = 0; 
    $productData->status     = 2; // 1 = active 
    $productData->visibility    = 4; //visible in search/catalog 
    $productData->category_ids   = $data['categories']; 
    $productData->price     = $data['price']; 
    $productData->tax_class_id   = 2; // 2=standard 
    $productData->additional_attributes = $additionalAttrs; 

    // Create new product 
    try { 
     $proxy->catalogProductCreate($sessionId, 'virtual', 9, $sku, $productData); // 9 is courses 
    } catch (SoapFault $e) { 
     print $e->getMessage(); //Internal Error. Please see log for details. 
     exit(); 
    } 
+0

¡eso es correcto! pero no es posible la soap api generada por el wsdl. – stereoscope

+0

No entiendo a qué te refieres con que no es posible? – creuzerm

+2

las clases generadas por el wsdl no proporcionan la estructura de datos para crear un conjunto único o multidimensional. por lo tanto, no es posible empaquetar los datos en una solicitud. – stereoscope

3

Esto no es un error. He estado usando este Magento SOAP API V2 durante más de un año, y el concepto que el equipo de Magento ha aplicado aquí es absolutamente correcto.

En primer lugar, cada vez que alguien que utiliza SOAP API V2 debe verificar completamente el WSDL de ese Magento respectivo, para que pueda crear/llamar mensajes correctamente. La URL para cargar el WSDL de SOAP API V2 es "<your_magento_home_page_url>/api/v2_soap/index/wsdl/1".

Ahora volviendo a su pregunta, el tipo de elemento "additional_attributes" es "associativeArray", que significa que su XML debería ser algo así como: -

<additional_attributes> 
    <!-- 
    This XML tag "item" can be anything; 
    it's what I use, but can definitely be any other valid non-used literal. 
    --> 
    <item> 
    <key>attribute_1_code</key> 
    <value>attribute_1_value_as_defined_in_database</value> 
    </item> 
    <item> 
    <key>attribute_2_code</key> 
    <value>attribute_2_value_as_defined_in_database</value> 
    </item> 
</additional_attributes> 

Un ejemplo del formato XML anterior será : -

<additional_attributes> 
    <item> 
    <key>color</key> 
    <!-- 
    I haven't provided the name/string "Blue", 
    because Magento's EAV database structure will only hold the option value 
    (which is a unique ID) and not the option literal string. 
    --> 
    <value>56</value> <!-- assuming this value for "Blue" color --> 
    </item> 
    <item> 
    <key>manufacturer</key> 
    <value>87</value> <!-- assuming this value for the manufacturer "Intel" --> 
    </item> 
</additional_attributes> 

lo tanto, su "$productData" variable debe contener los valores de esta manera: -

$productData 
(
    [name] => testname 
    [description] => testdescription 
    [short_description] => shorttestdescription 
    [weight] => 70 
    [status] => 1 
    [visibility] => 4 
    [price] => 359.0 
    [tax_class_id] => 2 
    [additional_attributes] => Array 
    (
     [0] => Array 
     (
      [key] => attribute1 
      [value] => 999.0 
     ) 
     [1] => Array 
     (
      [key] => attribute2 
      [value] => testcontent 
     ) 
    ) 
) 

Espero que ayude.

+0

¡Hola! Gracias. Estoy al tanto de la URL a usar: .../api/v2_soap/index/wsdl/1 o .../api/v2_soap? Wsdl = 1. Así que si creo un asociativeArray solo puedo llenarlo con valores de cadena. Además, he creado los archivos Java desde el wsdl con Apache CXF – stereoscope

+0

@fritz - Genial para escuchar eso. Espero que ahora puedas resolverlo. :) –

+0

Lamento que debo revisar mi código, pero si creo un conjunto asociativo, solo puedo agregar entidades asociativas pero no mallas asociativas. por lo tanto, no es posible construir este tipo de estructura de datos que usted describió. Por fin haré una revisión del código y publicaré mi progreso mañana. – stereoscope

7

De hecho tuve que parchar la aplicación/code/core/Mage/Catalog/Model/Product/Api/V2.php para hacer que esta llamada funcione en la versión 1.6.2.0.

Los controles de código existentes, ya sea para un atributo "single_data" o "multi_data" bajo la propiedad de los 'additional_attributes' y trata de iterar sobre el los que como una matriz asociativa:

if (property_exists($productData, 'additional_attributes')) { 
     if (property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes->single_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     if (property_exists($productData->additional_attributes, 'multi_data')) { 
      foreach ($productData->additional_attributes->multi_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
} 

creo que la cuestión es que, dado que estamos pasando la estructura matriz asociativa:

<item> 
    <key>...</key> 
    <value>...</value> 
</item> 
<item> 
    <key>...</key> 
    <value>...</value> 
</item> 

directamente bajo las additional_attribtutes bloquear entonces es realmente la propiedad additional_attributes que deben repiten a lo largo de sacar las claves/valores de atributos, por lo que añadió tercio si bloque:

if (gettype($productData->additional_attributes) == 'array') { 
      foreach ($productData->additional_attributes as $k => $v) { 
        $_attrCode = $k; 
        $productData->$_attrCode = $v; 
      } 
    } 

Con ese código en el lugar mis atributos personalizados se están agregando/actualizando.

He aquí una muestra de:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Magento"> 
<soapenv:Header/> 
<soapenv:Body> 
    <urn:catalogProductUpdateRequestParam> 
    <sessionId>100fe1f9d0518b0fd0ed49cc460c1fa6</sessionId> 
    <productId>1</productId> 
    <productData> 
     <name>product 3</name> 
     <!-- the custom attributes to updated.... 
     --> 
     <additional_attributes> 
      <complexObjectArray> 
       <key>feed_id</key> 
       <value>56920</value> 
      </complexObjectArray> 
      <complexObjectArray> 
       <key>feed_active</key> 
       <value>1</value> 
      </complexObjectArray> 
     </additional_attributes> 
     </productData> 
    </urn:catalogProductUpdateRequestParam> 
    </soapenv:Body> 
</soapenv:Envelope> 
+0

Eres un genio, gracias. Todas las demás respuestas no funcionan con un proxy generado por Visual Studio. –

+0

¡Genial! Esa también fue la solución a mi problema: http://magento.stackexchange.com/questions/1308/why-does-one-of-many-attributes-does-not-get-updated-with-soapv2-ws- i –

+1

Esta es la respuesta que debe usar si está generando código de WSDL y también puede modificar el código de PHP magento. Puedo confirmar que el problema existe en 1.9.1 y esta corrección me permitió actualizar los atributos. –

2

stroisi es casi completamente correcto. Solo una solución a esa respuesta: la tercera condición que agregó evaluará a true para las dos primeras condiciones también (agregando esos atributos dos veces en caso de que esté usando SOAPv2 en modo no compatible con WSI).

Esa cadena condición debería tener este aspecto:

// ... 
     if (property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes->single_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     if (property_exists($productData->additional_attributes, 'multi_data')) { 
      foreach ($productData->additional_attributes->multi_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     else if (! property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes as $key => $value) { 
       $productData->$key = $value; 
      } 
     } 
    // ... 

La tercera condición afirma que tanto 'single_data''multi_data' y son no propiedades de additional_attributes.


Aunque, en mi opinión, la forma correcta de corregir este error es editar el archivo "wsi.xml" por lo que es consistente con wsdl.xml (o viceversa).

1

Estoy usando SOAP API para ingresar productos en las tiendas de magento. aquí está el código completo

En el caso del atributo personalizado multiselección.

   $arrProductTime = explode(',', '136,139'); 

       $result = $client->catalogProductCreate($session, 'simple', $attributeSet->set_id, 'product_sku1234', array(

        'categories' => array(36), 
        'websites' => array(1), 
        'name' => 'my_pdt1008', 
        'description' => 'my_pdt1', 
        'short_description' => 'my_pdt1000', 
        'weight' => '11', 
        'status' => '1', 
        'url_key' => 'product-url-key1', 
        'url_path' => 'product-url-path1', 
        'visibility' => '4', 
        'price' => '100', 
        'tax_class_id' => 1, 
        'meta_title' => 'Product meta title1', 
        'meta_keyword' => 'Product meta keyword1', 
        'meta_description' => 'Product meta description1', 
        'stock_data' => array('qty'=>'100','is_in_stock'=>1,'manage_stock'=>1), 
        'additional_attributes' => array('multi_data' => array(array('key' => 'product_time', 'value' => $arrProductTime))) 
       )); 
Cuestiones relacionadas