Open2b versione 7.5

API introduzione

Le app possono gestire tramite le API i dati e le funzionalità del negozio. Possono ad esempio aggiornare giacenze e prezzi dei prodotti, cambiare listino ai clienti, aggiungere nuovi ordini o pubblicare nuove pagine. Sono disponibili oltre 100 metodi che consentono di automatizzare procedure, realizzare interfacciamenti con altri gestionali o integrazioni con sistemi esterni.

Le app possono accedere ai metodi delle API sia con JavaScript che dal server tramite HTTP.

Accesso con JavaScript

L'app aperta nel gestionale può chiamare i metodi delle API direttamente con JavaScript presente nelle sue pagine. Per richiamare i metodi si utilizza la funzione Admin.api() presente in Admin SDK.

Admin.api(method, request, function(response) { … })

Chiama un metodo delle API e ne ritorna la risposta.

Parametro Descrizione
method Nome completo del metodo.
request Richiesta con i parametri per il metodo. Indicare null se non sono presenti parametri.
response Risposta del metodo.

Le chiamate alle API da JavaScript sono asincrone, ossia la funzione Admin.api() ritorna immediatamente e in seguito quando la chiamata del metodo si conclude verrà chiamata la callback, ossia la funzione passata come terzo parametro. Si possono eseguire più chiamate una dopo l'altra senza attendere che le precedenti siano terminate in quanto Open2b le accoda e le esegue una dopo l'altra.

Se non è importante conoscere la risposta e l'esito dell'esecuzione è possibile omettere la callback.

Esempio

Il seguente è un esempio di chiamata con JavaScript del metodo commerce.products.update per aggiornare un prodotto:

Admin.api('commerce.products.update', {
    id : 496,
    product : {
        isVisible: true,
        name: { it: 'Nuovo nome', en: 'New name' }
    }
}, function(response) {
    if ( response.status != 'ok' ) {
        alert('Error: '+response.error.description);
        return;
    }
    // done
});

Accesso dal server tramite HTTP

Le app possono eseguire le chiamate dal loro server al server del negozio tramite HTTP. Le chiamate alle API tramite HTTP hanno le seguenti caratteristiche:

Autenticazione

Diversamente dal JavaScript per il quale l'autenticazione è assolta dal gestionale in cui è aperta l'app, nel caso di HTTP deve essere sempre presente l'intestazione "X-Secret-Key" per l'accesso ai metodi privati o l'intestazione "X-Public-Key" per l'accesso ai metodi pubblici. Per le app pubblicate nello Store la chiave viene comunicata al momento dell'installazione dell'app sul negozio, per le altre app la chiave si può recuperare nel gestionale in "Apps > Modifica" e facendo clic sulla la riga relativa all'app.

Esempio in

In questo esempio si mostra una chiamata del metodo commerce.products.update, mostrata in precedenza nella versione in JavaScript, ma questa volta tramite HTTP con il linguaggio Go PHP Java Python Ruby Perl :

package main

import (
    "bytes"
    "encoding/json"
    "log"
    "net/http"
)

func main() {

    body, err := json.Marshal(map[string]interface{}{
        "id": 3,
        "product": map[string]interface{}{
            "isVisible": true,
            "name":      map[string]string{"it": "Nuovo nome", "en": "New name"},
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    req, err := http.NewRequest("POST", "https://www.store.com/open2b/api/v10/commerce.products.update", bytes.NewReader(body))
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("X-Secret-Key", "EZMRp7tfDT7JisRlGREU3R00do4nq0BSLHRKToTppOZRiTc75a")
    req.Header.Set("Content-Type", "application/json; charset=UTF-8")

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    result := struct {
        Status string
        Error  struct {
            Description string
        }
    }{}
    err = json.NewDecoder(res.Body).Decode(&result)
    if err != nil {
        log.Fatal(err)
    }

    if result.Status != "ok" {
        log.Printf("Request failed: %s\n", result.Error.Description)
    }

}
import org.codehaus.jackson.map.ObjectMapper;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.net.URL;
import java.net.HttpURLConnection;
import java.io.*;

public class UpdateProduct{
    public static void main(String[] args){
        ObjectMapper mapper = new ObjectMapper();

        Map<String,Object> request = new HashMap<String,Object>();
        Map<String,Object> product = new HashMap<String,Object>();
        Map<String,String> name    = new HashMap<String,String>();

        name.put("it", "Nuovo nome");
        name.put("en", "New name");

        product.put("isVisible", (Boolean)true);
        product.put("name", name);

        request.put("id",(Integer)3);
        request.put("product",product);

        String body;
        try {
            body = mapper.writeValueAsString(request);
        } catch (Exception e) {
            return;
        }

        HttpURLConnection connection = null;
        URL url;
        Map<?,?> result;
        try {
            url = new URL("https://www.store.com/open2b/api/v10/commerce.products.update");
            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setRequestProperty("X-Secret-Key", "jIG0FzJ4OSpilRikDsVtDVmnuWFxaUT41-238_j24gr37-MI6T1QyrtMeq2V0Yj7");
            connection.setRequestProperty("Content-Length", Integer.toString(body.getBytes().length));

            connection.setDoInput(true);
            connection.setDoOutput(true);

            DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
            writer.write(body.getBytes());
            writer.flush();
            writer.close();

            InputStream inputStream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String tmp;
            StringBuffer responseBuffer = new StringBuffer();
            while((tmp = reader.readLine()) != null) {
                responseBuffer.append(tmp);
                responseBuffer.append('\r');
            }
            reader.close();
            result = mapper.readValue(responseBuffer.toString(), Map.class);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        } finally {
            if (connection!=null) {
                connection.disconnect();
            }
        }

        if (result.get("status").equals("error")) {
            System.out.println("error: "+((Map<?,?>)(result.get("error"))).get("description"));
            System.exit(-1);
        }
    }
}
require 'uri'
require 'net/http'
require 'json'

body = JSON.dump({
    "id" => 3,
    "product" => {
        "isVisible" => 1,
        "name" => { "it" => "Nuovo nome", "en" => "New name" },
    },
})

uri  = URI.parse("https://www.store.com/open2b/api/v10/commerce.products.update")
http = Net::HTTP.new(uri.host,uri.port)

headers = {
    "X-Secret-Key" => "EZMRp7tfDT7JisRlGREU3R00do4nq0BSLHRKToTppOZRiTc75a",
    "Content-Type" => "application/json; charset=UTF-8",
}

req = Net::HTTP::Post.new(uri.path, initheader = headers)
req.body = body

result = JSON.parse(http.request(req).body)

if result["status"] != "ok"
    abort("Request failed: " + result["error"]["description"])
end
import json
import http.client
import sys

connection = http.client.HTTPConnection("www.store.com")

body = json.dumps({
    "id" : 3,
    "product" : {
        "isVisible" : True,
        "name" : { "it" : "Nuovo nome", "en" : "New name" },
    },
})

headers = {
    "X-Secret-Key" : "EZMRp7tfDT7JisRlGREU3R00do4nq0BSLHRKToTppOZRiTc75a",
    "Content-Type" : "application/json; charset=UTF-8",
}

connection.request("POST", "/open2b/api/v10/commerce.products.update", body, headers)
response = connection.getresponse().read()

result = json.loads(response.decode("utf-8"))

if result["status"] != "ok":
    sys.exit("Request failed: " + result["error"]["description"])
require JSON;
require LWP::UserAgent;

my $json = new JSON();
my $ua   = new LWP::UserAgent();

my %headers = (
    "X-Secret-Key" => "EZMRp7tfDT7JisRlGREU3R00do4nq0BSLHRKToTppOZRiTc75a",
    "Content-Type" => "application/json; charset=UTF-8",
);

my $body = $json->encode({
    "id" => 3,
    "product" => {
        "isVisible" => 1,
        "name" => { "it" => "Nuovo nome", "en" => "New name" },
    },
});

my $response = $ua->post("https://www.store.com/open2b/api/v10/commerce.products.update", %headers, "Content" => $body);

my $result = $json->decode($response->content());

if ($result->{"status"} ne "ok") {
    die("Request failed: ".$result->{"error"}{"description"}."\n");
}
$ch = curl_init();

// il POST è usato per tutte le chiamate
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// il metodo chiamato è indicato nell'URL
curl_setopt($ch, CURLOPT_URL,
    'https://www.store.com/open2b/api/v10/commerce.products.update');

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    // la chiave deve essere presente in ogni chiamata
    'X-Secret-Key: EZMRp7tfDT7JisRlGREU3R00do4nq0BSLHRKToTppOZRiTc75a',
    // il content type può essere "application/json" o "text/javascript"
    'Content-Type: application/json; charset=UTF-8'));

// la richiesta è in formato JSON
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array(
    'id' => 496,
    'product' => array(
    'isVisible' => true,
    'name' => array( 'it' => 'Nuovo nome', 'en' => 'New name' ),
))));

// la risposta è in formato JSON
$response = json_decode(curl_exec($ch), true);

// nella risposta viene riportato sempre lo stato dell'esecuzione
if ( $response['status'] != 'ok' ) {
    die("Request failed: ".$response['error']['description']);
}

curl_close($ch);

Come leggere la documentazione delle API

Nella documentazione di ogni metodo la chiamata viene esemplificata sia per JavaScript:

Admin SDK
Admin.api('commerce.products.update', request, function(response) { … });

che per HTTP:

HTTP POST
/api/v10/commerce.products.update

dopodiché seguono la richiesta e la risposta in formato JSON. Per JavaScript il codice JSON corrisponde praticamente al JavaScript, per HTTP si tratta del codice inviato attraverso il corpo della chiamata senza però i commenti e gli ulteriori spazi presenti invece nella documentazione.