提供REST API的Web服务模块(开发者)

From Dolibarr ERP CRM Wiki
Jump to navigation Jump to search


Web services
模块ID 2610
用户手册 不适用
开发文档 本页

功能

激活此模块后,您就可以调用Dolibarr提供的Webservices。然后,您可以对Dolibarr提供的各种Web服务进行REST调用。

安装

要安装它,请打开 主页->设置->模块/应用 并激活"API / Web 服务 (REST 服务器)"模块。

激活 API / Web 服务 (REST 服务器) 模块后,Dolibarr 将成为REST Web服务器。您可以在相应的URL上发送自己的REST请求 : /api/index.php/xxx 其中xxx是要调用的API的名称。

Apache的设置

没有什么可做的。如果您的Dolibarr正在使用Apache,那么REST API也应该可以工作。APIs将由与您的应用程序相同的虚拟web服务器提供服务。

Nginx的设置

像Apache一样,如果您的Dolibarr在Nginx虚拟主机中工作,那么您不用为APIs做任何事情。APIs将由与您的应用程序相同的虚拟web服务器提供服务。

但是,Nginx在许多发行版上的默认设置通常是gaz引擎,您可能会遇到麻烦。如果遇到这样的问题,可以尝试编辑Nginx配置文件以匹配以下示例。这是一个简单的本地主机设置,提供有效的REST API处理(在parabola gnu/linux上用9.0.1测试)。

worker_processes  1;
error_log  /var/log/nginx/error.log;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
    	listen		80;
        server_name     dolibarr.localhost; # adjust to your domain

        root    /usr/share/webapps/dolibarr/htdocs; # adjust to your path 
        index   index.php;

        # from https://github.com/Dolibarr/dolibarr/issues/6163#issuecomment-391265538
        location ~ [^/]\.php(/|$) {
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            if (!-f $document_root$fastcgi_script_name) {
                return 404;
            }

            # Mitigate https://httpoxy.org/ vulnerabilities
            fastcgi_param HTTP_PROXY "";

            root           /usr/share/webapps/dolibarr/htdocs;
            fastcgi_pass   unix:/run/php-fpm/php-fpm.sock;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            # Dolibarr Rest API path support
            fastcgi_param  PATH_INFO       $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED $document_root$fastcgi_script_name;
        }
     }		
}

提供的服务清单

只有少数服务可用。从Dolibarr 5.0版开始,您可以通过以下地址调用explorer来查看提供的web服务的完整列表:

http://yourdolibarrurl/api/index.php/explorer.

例如,您可以在以下地址的演示实例上尝试使用explorer:

https://demo.dolibarr.org/api/index.php/explorer

在右上角,粘贴要用于调用API的用户的<token>,然后单击“explorer”按钮。注意:每个用户的令牌可以在用户的注册页面上设置。

您可能还希望首先调用“login”服务以获取API令牌。作为响应,您将获得用于获取和调用所提供服务列表的令牌。

输入令牌并单击“Explore”后,您应该看到该令牌的所有可用操作。如果您没有很多操作,可能是因为相应的模块未启用。如果要查看发票,必须在Dolibarr配置中启用发票模块。产品、合作方等也是如此。

然后,您可以直接从该浏览页面测试任何API。这是测试任何Dolibarr API的推荐解决方案,因为这里记录了所有API和参数。测试之后,您将获得结果,以及如何使用 curl 从命令行调用API的示例。

在这个API浏览页面上,您可以进行大量测试。例如从Dolibarr读取数据,并写入、修改和删除。警告:数据库中的数据会被真正修改。

使用方法

Grosso modo, pour utiliser REST, il faut appeler une url du genre suivant http://<mon_serveur>/api/index.php/<action>
avec une des 4 méthodes : GET, POST, PUT, DELETE, en remplaçant <action> par l'action sur laquelle vous voulez intervenir. Ex : http://<mon_serveur>/api/index.php/invoices


Avant d'utiliser une API, vous devez d'abord obtenir une clé API personnalisée. Vous devez créer un nouvel utilisateur et générer ou définir sa "clé pour l'API".

Dolibarr user for api.png


Vous devrez utiliser cette clé API dans n'importe lequel de vos programmes clients devant appeler une API Dolibarr.


Pour ce faire, il existe plusieurs méthodes. Voici un morceau de code opérationnel pour appeler une API, mais il existe également des librairies qui simplifie le travail, telles que phphttpclient.com.

function CallAPI($method, $apikey, $url, $data = false)
{
    $curl = curl_init();
    $httpheader = ['DOLAPIKEY: '.$apikey];

    switch ($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);
            $httpheader[] = "Content-Type:application/json";

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

            break;
        case "PUT":

	    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
            $httpheader[] = "Content-Type:application/json";

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

            break;
        default:
            if ($data)
                $url = sprintf("%s?%s", $url, http_build_query($data));
    }

    // Optional Authentication:
	//    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
	//    curl_setopt($curl, CURLOPT_USERPWD, "username:password");

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl, CURLOPT_HTTPHEADER, $httpheader);

    $result = curl_exec($curl);

    curl_close($curl);

    return $result;
}

Ce n'est qu'un exemple, ce n'est pas sécurisé, cela ne prend pas en compte les codes erreurs mais vous pouvez le modifier et l'adapter à vos besoins. la fonction prend 4 paramètres :

  • $method : string "GET", "POST", "PUT", "DELETE"
  • $apikey : string "votre <token> généré plus haut"
  • $url : string l'url à appeler. Ex : "http://<mon_serveur>/api/index.php/invoices"
  • $data : string flux au format json. Ce champ est requis pour les appels POST ou PUT.

Exemples avec PHP

Maintenant, quelques exemples opérationnels pour différents cas d'utilisation.

Dans tous les cas, on a :

  • $apiKey = "<mon token>";
  • $apiUrl = "http://<mon_serveur>/api/index.php/";


// Récupérer la liste des produits
	$listProduits = [];
	$produitParam = ["limit" => 10000, "sortfield" => "rowid"];
	$listProduitsResult = CallAPI("GET", $apiKey, $apiUrl."products", $produitParam);
	$listProduitsResult = json_decode($listProduitsResult, true);

	if (isset($listProduitsResult["error"]) && $listProduitsResult["error"]["code"] >= "300") {
	} else {
		foreach ($listProduitsResult as $produit) {
			$listProduits[intval($produit["id"])] = html_entity_decode($produit["ref"], ENT_QUOTES);
		}
	}

Commentaires :

  • récupérer les 10'000 premiers produits triés par leur id dans la base
  • html_entity_decode est nécessaire car les apostrophes sont encodés
  • il est facile d'utiliser la même méthode (en remplaçant products par dictionnarycountries) pour récupérer la liste des pays


// Créer un produit
	$ref = "ma_reference_produit_X203ZZ";
	$newProduct = [
		"ref"	=> $ref,
		"label"	=> $ref
	];
	$newProductResult = CallAPI("POST", $apiKey, $apiUrl."products", json_encode($newProduct));
	$newProductResult = json_decode($newProductResult, true);

Commentaires :

  • avant de créer un produit, il peut être sage de vérifier qu'il existe. En reprenant le premier exemple, cela fait :


// ma référence
	$ref = "ma_reference_produit_X203ZZ";
// existe-t-elle dans mon tableau
	$produitKey = array_search($ref, $listProduits);
	if ($produitKey) {
// oui
		$fk_product = $produitKey;
	} else {
// non
// Créer un produit
		$newProduct = [
			"ref"	=> $ref,
			"label"	=> $ref
		];
		$newProductResult = CallAPI("POST", $apiKey, $apiUrl."products", json_encode($newProduct));
		$newProductResult = json_decode($newProductResult, true);
		if (isset($newProductResult["error"]) && $newProductResult["error"]["code"] >= "300") {
// il y a eu une erreur
			echo "<pre>ERROR", var_dump($newProductResult), "</pre>";
			exit;
		} else {
// tout va bien
			$fk_product = $newProductResult;
			$listProduits[$fk_product] = $ref;
		}
	}

Commentaires :

  • je regarde si la référence de mon article existe dans le tableau créé dans le premier exemple.
  • si elle existe, j'utilise sa clé dans le tableau comme id
  • si elle n'existe pas, je crée l'article puis le j'ajoute à mon tableau pour les prochaines fois et je récupère l'id créé
  • cette méthode permet de limiter les appels API quand on doit importer 500 commandes par exemple. Récupérer une fois la liste des produits au début au lieu de chercher à chaque fois dans Dolibarr.


// créer une commande avec 2 articles

// le tableau qui contiendra toutes les lignes d'articles de la commande
	$newCommandeLine = [];

// article 1
	$ref1 = "ma_reference_produit_X203ZZ";
	$prix1 = 10;
	$qtt1  = 100;
	$tva1 = 20;
	$fk_product1
// article 2
	$ref2 = "ma_reference_produit_B707FD";
	$prix2 = 13;
	$qtt2  = 37;
	$tva2 = 20;

	$newCommandeLine[] = [
		"desc"		=> $ref1,
		"subprice"	=> $prix1,
		"qty"		=> $qtt1,
		"tva_tx"	=> floatval($tva1),
		"fk_product"=> $fk_product1
	];

	$newCommandeLine[] = [
		"desc"		=> $ref2,
		"subprice"	=> $prix2,
		"qty"		=> $qtt2,
		"tva_tx"	=> floatval($tva2),
		"fk_product"=> $fk_product2
	];

	if (count($newCommandeLine) > 0) {
		$newCommande = [
			"socid"			=> $clientDoliId,
			"type" 			=> "0",
			"lines"			=> $newCommandeLine,
			"note_private"	=> "Commande importée automatiquement depuis l'application",
		];
		$newCommandeResult = CallAPI("POST", $apiKey, $apiUrl."orders", json_encode($newCommande));
		$newCommandeResult = json_decode($newCommandeResult, true);
	}

Commentaires :

  • $clientDoliId vaut l'id du client dans la base doli. Soit vous le connaissez, soit vous pouvez le chercher auparavant
  • type => 0, c'est une commande client (par opposition à 1 = commande fournisseur)


// Valider une commande 
	$newCommandeValider = [
		"idwarehouse"	=> "0",
		"notrigger"		=> "0"
	];
	$newCommandeValiderResult = CallAPI("POST", $apiKey, $apiUrl."orders/".$newCommandeResult."/validate", json_encode($newCommandeValider));
	$newCommandeValiderResult = json_decode($newCommandeValiderResult, true);

Commentaires :

  • on voit dans cet exemple, en avant dernière lignes, on a : $apiUrl."orders/".$newCommandeResult."/validate".

$newCommandeResult est l'id de la commande crée (récupéré dans l'exemple précédent)


// chercher si le client existe dans la base
	$clientSearch = json_decode(CallAPI("GET", $apiKey, $apiUrl."thirdparties", array(
		"sortfield" => "t.rowid", 
		"sortorder" => "ASC", 
		"limit" => "1", 
		"mode" => "1",
		"sqlfilters" => "(t.nom:=:'".$nom_client."')"
		)
	), true);

Commentaires :

  • limit => 1 pour ne renvoyer que 1 client
  • mode => 1 car on cherche un client (on aurait aussi pu chercher un fournisseur qui est aussi un tiers mais avec un statut différent)
  • sqlfilters syntaxe un peu particulière mais il y a qq autres exemples sur la page d'explorer d'API


//client n'existe pas. le crée puis on récupère son id
	$newClient = [
		"name" 			=> "nom société client",
		"email"			=> "email société client",
		"client" 		=> "1",
		"code_client"	=> "-1"
	];
	$newClientResult = CallAPI("POST", $apiKey, $apiUrl."thirdparties", json_encode($newClient));
	$newClientResult = json_decode($newClientResult, true);
	$clientDoliId = $newClientResult;

Commentaires :

  • client => 1 car c'est un client (et pas un fournisseur)
  • code_client => -1 pour que le code client soit généré automatiquement.
  • on récupère l'id du client dans $clientDoliId

Développer un nouveau service / sa propre API

Ajouter un nouveau service est aussi facile qu'ajouter un fichier nommé api_monmoduleobject.class.php dans le dossier htdocs/monmodule/class. Si vous utilisez le "modulebuilder" pour développer sur Dolibarr, cette API avec les méthode CRUD pourra même être générée pour vous. Sinon, un copié-collé d'un fichier API existant fera l'affaire. Vous pouvez prendre comme exemple le fichier dans htdocs/commande/class/api_orders.class.php et l'adapter à votre classe / besoin.

Le framework détecte automatiquement les API et elle devrait être visible dans l'explorateur.

Les méthodes et paramètres sont détectées en fonction de l'introspection réalisée dans les classes PHP de l'objet (htdocs/monmodule/class/object.class.php) en utilisant les annotations trouvées dans la classe.

Pour une documentation à propos des annotations : https://github.com/Luracast/Restler/blob/master/ANNOTATIONS.md


Vous trouverez pas mal d'autres informations dans le code de Dolibarr. Vous trouverez tous les fichiers API de Dolibarr sous le nom htdocs/<dossier>/class/api_xxx_class.php

Vidéos sur le sujet