Websites, store groups y store views con la API REST de Magento2

REST

Para quienes debemos llevar a cabo integraciones, Magento2 ha sido una bocanada de aire fresco.

Al ser API first (o al menos intentarlo), ha ayudado a simplificar muchísimo de nuestro trabajo y la integridad de lógicas.

Entre las tantas operaciones que podemos hacer de forma nativa con la API REST, quizás, en alguna oportunidad, nos puedes pasar que más que tener que operar contra la tienda (crear o actualizar productos, crear una orden o extraer datos de una compra) debamos obtener información de como está configurada.

¿A qué me refiero con información de la tienda?. Bueno, sin que el orden sea relevante, podemos obtener la listas de websites que tiene nuestra instancia.

try {
    $api_url = 'http://www.dominio.com.ar/rest/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/store/websites");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

El output de eso será:

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [code] => base
            [name] => Main Website
            [default_group_id] => 1
        )
    [1] => stdClass Object
        (
            [id] => 0
            [code] => admin
            [name] => Admin
            [default_group_id] => 0
        )
)

Si quisiéramos, en cambio, obtener los store groups, usaríamos:

try {
    $api_url = 'http://www.dominio.com.ar/rest/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/store/storeGroups");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

El output a obtener será:

Array
(
    [0] => stdClass Object
        (
            [id] => 0
            [website_id] => 0
            [root_category_id] => 0
            [default_store_id] => 0
            [name] => Default
        )
    [1] => stdClass Object
        (
            [id] => 1
            [website_id] => 1
            [root_category_id] => 2
            [default_store_id] => 1
            [name] => Main Website Store
        )
)

O si necesitáramos conocer los stores views:

try {
    $api_url = 'http://www.dominio.com.ar/rest/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/store/storeViews");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

El output:

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [code] => default
            [name] => Default Store View
            [website_id] => 1
            [store_group_id] => 1
        )
    [1] => stdClass Object
        (
            [id] => 0
            [code] => admin
            [name] => Admin
            [website_id] => 0
            [store_group_id] => 0
        )
)

Podríamos también requerir información de cómo está configurada la tienda.

try {
    $api_url = 'http://www.dominio.com.ar/rest/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/store/storeConfigs");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

Nos devolverá algo como esto:

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [code] => default
            [website_id] => 1
            [locale] => es_AR
            [base_currency_code] => ARS
            [default_display_currency_code] => ARS
            [timezone] => America/Argentina/Buenos_Aires
            [weight_unit] => kgs
            [base_url] => http://www.dominio.com.ar/
            [base_link_url] => http://www.dominio.com.ar/
            [base_static_url] => http://www.dominio.com.ar/pub/static/
            [base_media_url] => http://www.dominio.com.ar/pub/media/
            [secure_base_url] => https://www.dominio.com.ar/
            [secure_base_link_url] => https://www.dominio.com.ar/
            [secure_base_static_url] => https://www.dominio.com.ar/pub/static/
            [secure_base_media_url] => https://www.dominio.com.ar/pub/media/
        )
)

¿Por qué puede ser relevante tener esta información?.

En una tienda que no tiene múltiples websites ni múltiples store groups ni múltiples store views, no hace diferencia. Pero si nuestra tienda comienza a tener diferentes, por ejemplos, store groups, o websites; seignifica que tendrá, por lo menos, algún parámetro diferente en la configuración y, posiblemente podríamos pensar en un caso en donde el árbol de categorías sea diferente entre ellos.

Supongamos que quisiéramos obtener el árbol de categorías de una de las tiendas. Mediante los métodos anteriores pudimos haber obtenido qué store view es el default para un website dado. Sabemos también que los store views comparten store group, así que si tomamos el sotre view por defecto podemos intentar consultar un árbol de categorías para un store group en particular.

Si no tuviéramos múltiples stores groups, usaríamos:

try {
    $api_url = 'http://www.dominio.com.ar/rest/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/categories");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

Pero como, para mi ejemplo, tengo más de una tienda, y tengo diferentes árboles de categoría, habiendo obtenido antes mi el código de mi store view, probamos lo siguiente:

try {
    $api_url = 'http://www.dominio.com.ar/rest/codigo_de_mi_store_view/V1';
    $userData = array("username" => "usuario", "password" => "contraseña");
    $curl = curl_init($api_url . "/integration/admin/token");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($userData));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
    $token = curl_exec($curl);
    $curl = curl_init($api_url . "/categories");
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
    $result = curl_exec($curl);
    print_r(json_decode($result));
} catch (Exception $e) {
    print_r($e);
}

Y esto hará que el árbol de categorías que obtenga, será diferente. ¿El motivo?.

$api_url = 'http://www.dominio.com.ar/rest/codigo_de_mi_store_view/V1';

Si le indicamos a la API el código del store view, se trabajará sobre ese store view. Es el equivalente a cambiar el scope.