- Introducción
- Habilitar la API
- Autenticación
- Códigos de respuesta
- Encabezados
- Obtener listados
- Ejemplos
- Newsletter
- EndPoints en swagger
Laudus dispone de una API para que puedas conectar tus sistemas a Laudus, para obtener y actualizar información desde y hacia nuestro ERP. Con nuestra API podrás, por ejemplo, insertar un pedido de ventas, u obtener los movientos contables filtrados por fecha y cuenta contable, desde un sistema externo.
Una API (Application Programming Interface) es una herramienta para programadores. Si vas a utilizarla, y no eres técnico, necesitarás a alguien que te ayude a realizar tus proyectos. Por este motivo verás que el lenguaje que ocupamos en esta documentación es para desarrolladores.
GET /sales/customers
GET /sales/customers/{id}
GET /sales/customers/12
GET /sales/customers/12
GET /sales/customers/12/contacts
POST /sales/customers/
PUT /sales/customers/12
DELETE /sales/customers/12
Content-Type: application/json
Accept: application/xml
Accept-Encoding: gzip, deflate, br
Te indicamos los primeros pasos para comenzar a utilizar la API :
Una vez que se ha habilitado la API y generado un usuario, ya puedes autenticarte y comenzar a funcionar, tal y como se describe en el siguiente apartado.
Lo primero que debes hacer para comenzar a llamar a cualquier endPoint de la API es autenticarte, para obtener un token.
Para ello debes llamar al endPoint:
POST https://api.laudus.cl/security/login
Y en el cuerpo debes poner el nombre de usuario que has creado para la API, así como la contraseña y el RUT de la empresa a la que vas a acceder. Por ejemplo:
{
"userName": "usuario_creado_para_la_API",
"password": "contraseña_del_usuario_API",
"companyVATId": "RUT_de_la_empresa_con_guión_y_dígito_verificador"
}
Como respuesta de este POST obtendrás un token en formato JWT, junto con su fecha de caducidad. Por ejemplo:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI .......... ifW6_p4IYBrLRNY_Dqgl_1Ms",
"expiration": "2021-06-25T17:48:45-04:00"
}
Este token debes utilizarlo en todas las llamadas a la API, en un encabezado Authorization
, después de la palabra Bearer
, y sin comillas. Por ejemplo:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI .......... ifW6_p4IYBrLRNY_Dqgl_1Ms
Cuando haces una llamada a la API siempre obtienes una respuesta, ya sea del servidor (porque haces una llamada inválida) o de la API. Siempre deberías comprobar la respuesta después de cada llamada, no des por hecho que todo siempre funciona bien :-)
En esta sección intentamos resumir qué es lo que puedes esperar en las respuestas al llamar a la API
Como norma general recuerda que en HTTP los códigos de estado 2XX son para cuando todo va bien, los 4XX cuando hay un error de quien hace la petición (tu parte del trabajo), y los 5XX cuando el error es de la parte del servidor (nuestra parte del trabajo). Nosotros no utilizamos los códigos 1XX (son informativos), ni 3XX (indican algún tipo de redirección).
Aquí te describimos los códigos en general, y más abajo algunos casos específicos en el caso de los diferentes tipos de verbos utilizados
{
"type": "error",
"message": "El token ha expirado",
"status": 401,
"code": "TOKEN_EXPIRED"
}
{
"type": "error",
"message": "Access denied",
"status": 403,
"code": "FORBIDDEN"
}
GET /sales/quotes/12034
@
, un precio unitario fuera de rango, o una factura a un cliente bloqueado. Hay gente que prefiere un código 409
para las reglas de validación, a nosotros nos encaja más el 422. En el cuerpo del mensaje recibirás información descriptiva de la validación que falla.
{
"type": "error",
"message": "Variable not found: miVariableQueNoExiste",
"status": 500,
"code": "INTERNAL_SERVER_ERROR"
}
Accept
GET /sales/quotes/12034
En los endPoints del tipo "list", que devuelven listados de información de las diferentes entidades, retornamos lo siquiente:
Accept
de la petición. Recuerda que esos endPoints permiten los formatos JSON, XML y CSVAuthorization: Bearer eyJhbGciOiJIXzI1NiI..............MRjkQyO17GholDyRAjrYSE
Content-Type: application/json
Accept: application/json
Accept: application/xml
Accept: text/csv
Accept-Encoding: gzip, deflate, br
Casi todas las entidades tienen un endPoint que permite obtener listados de información de la misma. Estos endPoints son del estilo (por ejemplo, para obtener cotizaciones):
POST /sales/quotes/list
Utilizamos el verbo POST porque estos endPoints deben incluir un cuerpo con los filtros y condiciones de la consulta. Y el esquema es demasiado completo como para enviarlo en un GET en forma de parámetros.
Hoy en día no hay nada que impida enviar una petición GET con cuerpo, pero el problema está en que algunos lenguajes, notablemente Javascript, no
permiten peticiones GET con cuerpo.
En nuestra opinión no se explica que a estas alturas del siglo XXI arrastremos una decisión de 1990. No solo la estructura de parámetros no es adecuada para
muchas consultas, sino que se puede chocar con el límite que imponen los navegadores al tamaño de la URL.
Cada vez hay más ejemplos de compañías que admiten GET con body (siendo Elastic una de las más conocidas con su servicio Elastic Search), tal vez lo incorporemos en algún momento.
Estos endPoints llevan siempre un cuerpo en JSON (por lo tanto es obligatorio el encabezado Content-Type: application/json
), con las especificaciones de la consulta, y pueden recibir la información en los formatos JSON, XML y CSV,
incorporando alguno de los encabezados:
Accept: application/json
Accept: application/xml
Accept: text/csv
El contenido del JSON con la consulta a realizar tiene 4 apartados:
limit
y offset
.offset
: de todos los resultados de la consulta, se devolverán las filas a partir de este valor + 1. Es decir, se ignoran los offset
primeros resultados.limit
: la cantidad de resultados que queremos retornar a partir de offset."options": {
"offset": 10,
"limit": 50
}
offset
). Es decir, de toda la consulta que hallamos especificado,
nos devolverá los resultados del 11 al 60 (50 filas en total). Esto se utiliza para paginar consultas muy grandes, e ir obteniendo las diferentes páginas de resultados.
"filterBy": [{"field": "quoteId", "operator": "<=", "value": 50}]
"filterBy": [{"field": "customerId", "operator": "=", "value": [34, 56, 77]}]
"filterBy": [{"field": "customerId", "operator": "=", "value": 34},
{"field": "customerId", "operator": "=", "value": 56},
{"field": "customerId", "operator": "=", "value": 77}]
field
y direction
.direction
puede tener los valores ASC
y DESC
.
Con algunos ejemplos se comprenderá mejor las consultas que se pueden realizar.
Vamos primero con un ejemplo del JSON completo, y después ejemplos de las diferentes secciones.
Queremos obtener el id, razón social, RUT, y datos de facturación de todos los clientes de la comuna de Arica, ordenados por RUT de manera creciente:
{
"options": {
"offset": 0,
"limit": 0
},
"fields": [
"customerId", "legalName", "VATId", "addressBilling", "cityBilling", "countyBilling",
"zipCodeBilling", "stateBilling"
],
"filterBy": [
{
"field": "countyBilling",
"operator": "=",
"value": "arica"
}
],
"orderBy": [
{
"field": "VATId",
"direction": "ASC"
}
]
}
Todos los ejemplos que vienen a continuación se ha elaborado para el endPoint de Pedidos de Ventas:
POST /sales/orders/list
"fields": ["salesOrderId", "issuedDate", "customer.name", "modifiedBy.name"]
"fields": ["salesOrderId", "issuedDate", "customer.name",
"modifiedBy.name", "items.product.SKU", "items.quantity",
"items.product.unitOfMeasure"]
"filterBy": [{
"field": "issuedDate",
"operator": ">",
"value": "2020-12-31T23:59:59"
}]
"filterBy": [{
"field": "issuedDate",
"operator": ">",
"value": "2020-12-31T23:59:59"
},
{
"field": "items.product.SKU",
"operator": "contains",
"value": "aceite"
}]
"filterBy": [{
"field": "issuedDate",
"operator": ">",
"value": "2020-12-31T23:59:59"
},
{
"field": "items.product.SKU",
"operator": "contains",
"value": ["aceite", "vinagre"]
}]
"filterBy": [{
"field": "salesOrderId",
"operator": "<=",
"value": 100
},
{
"field": "salesOrderId",
"operator": "!=",
"value": [50, 51, 52, 53, 54]
}]
"filterBy": [{
"field": "customer.countyBilling",
"operator": "=",
"value": "Arica"
}]
"orderBy": [{
"field": "issuedDate",
"direction": "ASC"
}]
"orderBy": [{
"field": "items.product.SKU",
"direction": "ASC"
},
"field": "items.quantity",
"direction": "DESC"
}]
// Ejemplo para ejecutar por consola que recupera un cliente a través de la API, realiza unos cambios.
// y graba el cliente modificado. Incluye obtención de token
// Este ejemplo utiliza la librería Newtonsoft.Json que debe estar instalada
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Dynamic;
using System.IO;
using System.Net;
namespace LaudusAPI_Ejemplos
{
class Program
{
// Clase para preservar credencial de acceso a la API (token y fecha de expiración del mismo)
public class Credential
{
public string token;
public DateTime expiration;
}
// Clase para representar la entidad Account (Cuenta del plan de cuentas contable)
public class Account
{
public int accountId;
public string accountNumber;
public string name;
}
// Clase para representar la entidad Customer (Cliente)
public class Customer
{
public int customerId;
public string name;
public string legalName;
public string VATId;
public string activityName;
public Account account;
}
static void Main(string[] args)
{
// Url base de la API
string url = "https://api.laudus.cl/";
// Obtener credenciales de acceso a la API
Credential credencial = ObtenerToken(url);
if (credencial != null)
{
Console.WriteLine("-----------------------<< Obtener Token >>-----------------------");
Console.WriteLine("Token = " + credencial.token);
Console.WriteLine("Expiration = " + credencial.expiration.ToString());
// Obtener datos del cliente con el customerId 18
var cliente = GetCliente(url, credencial, 18);
if (cliente != null)
{
Console.WriteLine("-----------------------<< Get Cliente >>-----------------------");
Console.WriteLine("Id = " + cliente.customerId.ToString());
Console.WriteLine("Nombre = " + cliente.name);
Console.WriteLine("LegalName = " + cliente.legalName);
Console.WriteLine("VATId = " + cliente.VATId);
Console.WriteLine("ActivityName = " + cliente.activityName);
Console.WriteLine("account.accountId = " + cliente.account.accountId.ToString());
Console.WriteLine("account.accountNumber = " + cliente.account.accountNumber);
Console.WriteLine("account.name = " + cliente.account.name);
// Cambio algunos datos del cliente obtenido para luego guardar esos cambios
cliente.name = "Nombre Modificado";
cliente.legalName = "Modificado S.A.";
// Body del put para guardar los cambios
string body = JsonConvert.SerializeObject(cliente);
// Guardo los cambios
var clienteGuardado = GuardarCliente(url, credencial, cliente.customerId, body);
if (clienteGuardado != null)
{
Console.WriteLine("-----------------------<< Put Cliente >>-----------------------");
Console.WriteLine("Id = " + clienteGuardado.customerId.ToString());
Console.WriteLine("Nombre = " + clienteGuardado.name);
Console.WriteLine("LegalName = " + cliente.legalName);
Console.WriteLine("VATId = " + cliente.VATId);
Console.WriteLine("ActivityName = " + cliente.activityName);
Console.WriteLine("account.accountId = " + cliente.account.accountId.ToString());
Console.WriteLine("account.accountNumber = " + cliente.account.accountNumber);
Console.WriteLine("account.name = " + cliente.account.name);
}
}
}
Console.WriteLine("----------------------------------------------------------------");
Console.ReadLine();
}
public static Credential ObtenerToken(string url)
{
Credential token = null;
try
{
// Se replica la estructura del JSON a enviar con un objecto expando.
dynamic loginInfo = new ExpandoObject();
loginInfo.userName = "mi-nombre-de-usuario";
loginInfo.password = "mi-contraseña";
// RUT de la empresa con guión. Puede llevar puntos o no
loginInfo.companyVATId = "XXXXXXXXXX-X";
// Se serializa el objeto a JSON
string json_data = JsonConvert.SerializeObject(loginInfo);
// Se configura la petición.
HttpWebRequest request;
request = WebRequest.Create(url + "security/login") as HttpWebRequest;
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.ContentType = "application/json";
request.Method = "POST";
// Body de la petición
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json_data);
streamWriter.Flush();
streamWriter.Close();
}
// Respuesta
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
var reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
token = JsonConvert.DeserializeObject(result);
}
}
catch (WebException exception)
{
// Se intenta atrapar primero cualquier webExcepcion
using (var stream = exception.Response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
Console.ReadLine();
}
}
catch (Exception exception)
{
// Cualquier otra excepcion la atrapamos aqui
Console.WriteLine(exception.Message);
Console.ReadLine();
}
return token;
}
public static Customer GetCliente(string url, Credential credencial, int idCliente)
{
Customer retVal = null;
try
{
//Se configura la petición.
HttpWebRequest request;
request = WebRequest.Create(string.Format("{0}sales/customers/{1}", url, idCliente)) as HttpWebRequest;
request.Headers.Add("Authorization", "Bearer " + credencial.token);
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.ContentType = "application/json";
request.Method = "GET";
// Respuesta
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
var reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
// Si se trabaja con un modelo de datos:
// se deserializa la respuesta de la API como un objeto de la clase Customer
retVal = JsonConvert.DeserializeObject(result);
// Si no se trabaja con un modelo de datos:
// se deserializa la respuesta de la API como un objeto dynamic
// para que funcione hay que cambiar también el tipo de retorno del método de
// Customer a dynamic, y lo mismo con la variable retVal
// var expConverter = new ExpandoObjectConverter();
// retVal = JsonConvert.DeserializeObject(result, expConverter);
}
}
catch (WebException exception)
{
// Se intenta atrapar primero cualquier webExcepcion
using (var stream = exception.Response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
Console.ReadLine();
}
}
catch (Exception exception)
{
// Cualquier otra excepcion la atrapamos aqui
Console.WriteLine(exception.Message);
Console.ReadLine();
}
return retVal;
}
// Si trabajamos con un modelo de datos, la delcaración es "public static Customer".
// Pero ni no trabajásemos con un modelo de datos, debería ser "public static dynamic"
public static Customer GuardarCliente(string url, Credential credencial, int idCliente, string body)
{
// Si trabajamos con un modelo de datos, creamos la variable de retorno del modelo
Customer retVal = null;
// Si NO trabajamos con un modelo de datos, la variable de retorno tiene que ser de tipo dynamic
// dynamic retVal = null;
try
{
// Se configura la petición.
HttpWebRequest request;
request = WebRequest.Create(string.Format("{0}sales/customers/{1}", url, idCliente)) as HttpWebRequest;
request.Headers.Add("Authorization", "Bearer " + credencial.token);
request.ContentType = "application/json";
request.Method = "PUT";
// Body de la petición
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(body);
streamWriter.Flush();
streamWriter.Close();
}
// Respuesta
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
var reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
retVal = JsonConvert.DeserializeObject(result);
}
}
catch (WebException exception)
{
// Se intenta atrapar primero cualquier webExcepcion
using (var stream = exception.Response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
Console.ReadLine();
}
}
catch (Exception exception)
{
// Cualquier otra excepcion la atrapamos aqui
Console.WriteLine(exception.Message);
Console.ReadLine();
}
return retVal;
}
}
}
# Ejemplo para ejecutar por consola que recupera un cliente a través de la API, realiza unos cambios,
# y graba el cliente modificado. Incluye obtención de token
import requests
import json
import sys
from collections import OrderedDict
from datetime import datetime
class laudusAPI_Ejemplos:
#Host
hostAPI = "https://api.laudus.cl"
#objeto para preservar los credenciales de acceso a la API
credential = {"token": "", "expiration": ""}
#objeto para representar la entidad Account (Cuenta del plan de cuentas contable)
account = {}
#objeto para representar la entidad Customer (clientes)
customer = {}
##########################################################################################
def obtenerToken(self):
#obtiene un token realizando un request a la API
vReturn = False
self.credential = {}
#esquema de request Login
requestLoginSchema = {"userName": "", "password": "", "companyVATId": ""}
#se aplican los valores finales al esquema de request Login
requestLoginSchema["userName"] = "su nombre de usuario"
requestLoginSchema["password"] = "su clave de acceso"
requestLoginSchema["companyVATId"] = "el rut de su empresa"
#se contruye el request body en json
requestBodyJson = json.dumps(requestLoginSchema)
#se construyen los headers requeridos para el request
requestHeaders = {"Content-type": "application/json", "Accept": "application/json"}
print("-----------------------<< Obtener Token >>-----------------------")
try:
request = requests.post(self.hostAPI + "/security/login", data = requestBodyJson, headers = requestHeaders)
respondStatusCode = request.status_code
#Se verifica al código status de respuesta
#Requests viene de fábrica con un 'status code lookup object' para una fácil referencia
if respondStatusCode == requests.codes.ok:
vReturn = True
self.credential = json.loads(request.text)
print("token = " + self.credential["token"])
print("expiration = " + self.credential["expiration"])
else:
vReturn = False
requestError = json.loads(request.text)
requestErrorMessage = ""
if 'message' in requestError:
requestErrorMessage = requestError['message']
print('error login ' + requestErrorMessage)
except:
vReturn = False
print("Unexpected error: ", sys.exc_info()[0])
return vReturn
##########################################################################################
def isValidToken(self):
#indica si el token almacenado en el objeto credential es válido
#si el token almacenado no es válido obtiene un nuevo token e igualmente indica su validez
vReturn = True
if "expiration" in self.credential and len(self.credential["expiration"]) > 0:
ltNow = datetime.now()
ltToken = datetime.fromisoformat(self.credential["expiration"])
ltToken = ltToken.replace(tzinfo=None)
if ltToken < ltNow:
return self.obtenerToken()
else:
return vReturn
else:
return self.obtenerToken()
##########################################################################################
def getCliente(self, customer_id):
print("-----------------------<< Obtener Customer >>-----------------------")
vReturn = False
#se verifica la validez del token almacenado y si no lo fuera se obtiene uno nuevo
if not self.isValidToken():
print("No se pudo obtener un token válido")
return vReturn
self.customer = {}
#se construyen los headers requeridos para el request
requestHeaders = {'Authorization': 'Bearer ' + self.credential["token"], 'Accept': 'application/json'}
try:
#request
request = requests.get(self.hostAPI + "/sales/customers/" + str(customer_id), headers = requestHeaders)
respondStatusCode = request.status_code
#Se verifica al código status de respuesta
if respondStatusCode == requests.codes.ok:
vReturn = True
self.customer = json.loads(request.text)
print(self.customer)
else:
vReturn = False
requestError = json.loads(request.text)
requestErrorMessage = ""
if 'message' in requestError:
requestErrorMessage = requestError['message']
print('error get customer ' + requestErrorMessage)
except:
vReturn = False
print("Unexpected error: ", sys.exc_info()[0])
return vReturn
##########################################################################################
def putCliente(self, customer_id):
print("-----------------------<< Guardar Customer >>-----------------------")
vReturn = False
#se verifica la validez del token almacenado y si no lo fuera se obtiene uno nuevo
if not self.isValidToken():
print("No se pudo obtener un token válido")
return vReturn
#se contruye el request body en json
requestBodyJson = json.dumps(self.customer)
#se construyen los headers requeridos para el request
requestHeaders = {'Authorization': 'Bearer ' + self.credential["token"], 'Accept': 'application/json', "Content-type": "application/json"}
try:
#request
request = requests.put(self.hostAPI + "/sales/customers/" + str(customer_id), data = requestBodyJson, headers = requestHeaders)
respondStatusCode = request.status_code
#Se verifica al código status de respuesta
if respondStatusCode == requests.codes.ok:
vReturn = True
self.customer = json.loads(request.text)
print(self.customer)
else:
vReturn = False
requestError = json.loads(request.text)
requestErrorMessage = ""
if 'message' in requestError:
requestErrorMessage = requestError['message']
print('error put customer ' + requestErrorMessage)
except:
vReturn = False
print("Unexpected error: ", sys.exc_info()[0])
return vReturn
##########################################################################################
if __name__ == '__main__':
ejemplo = laudusAPI_Ejemplos()
if ejemplo.obtenerToken():
#[opcionalmente] al llamar al ejemplo 'python code.py 606' puede indicarse un customerId '606' con el que usar el ejemplo
#si no se pasó ningún customerId se usará por defecto el customerId '18'
customerId = 18
if len(sys.argv) > 1:
if int(sys.argv[1]) > 0:
customerId = int(sys.argv[1])
if ejemplo.getCliente(customerId):
ejemplo.customer["legalName"] = "new legalName"
if ejemplo.putCliente(customerId):
pass
<?php
class laudusAPI_Ejemplos {
public function __construct()
{
//host
$this->hostAPI = "https://api.laudus.cl";
//objeto para preservar los credenciales de acceso a la API
$this->credential = array("token" => "", "expiration" => "");
//objeto para representar la entidad Account (Cuenta del plan de cuentas contable)
$this->account = array();
//objeto para representar la entidad Customer (clientes)
$this->customer = array();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function obtenerToken() {
//obtiene un token realizando un request a la API
$vReturn = false;
$this->credential = array();
//esquema de request Login
$requestLoginSchema = array("userName" => "", "password" => "", "companyVATId" => "");
#se aplican los valores finales al esquema de request Login
$requestLoginSchema["userName"] = "su nombre de usuario";
$requestLoginSchema["password"] = "su clave de acceso";
$requestLoginSchema["companyVATId"] = "el RUT de su empresa";
//se contruye el request body en json
$requestBodyJson = json_encode($requestLoginSchema);
echo "-----------------------<< Obtener Token >>-----------------------\n\n";
try {
$request = curl_init($this->hostAPI."/security/login");
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($request, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($request, CURLOPT_POSTFIELDS, $requestBodyJson);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_HTTPHEADER, array(
"Accept: application/json",
"Content-type: application/json",
"Content-Length: ".strlen($requestBodyJson))
);
//make post
$respond = curl_exec($request);
//respond status code
$respondStatusCode = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($respondStatusCode == 200) {
$vReturn = true;
$this->credential = json_decode($respond);
echo "token = " . $this->credential->{"token"}."\n\n";
echo "expiration = " . $this->credential->{"expiration"}."\n\n";
}
else {
$vReturn = false;
$requestError = json_decode($respond);
$requestErrorMessage = "";
if (isset($requestError->{"message"})) {
$requestErrorMessage = $requestError->{"message"};
}
echo "error login ".$requestErrorMessage."\n\n";
}
}
catch (Exception $error) {
$vReturn = false;
echo "Unexpected error: ", $error->getMessage(), "\n";
}
return $vReturn;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function getCliente($customerId) {
//se obtiene la información del cliente
echo "-----------------------<< Obtener Customer >>-----------------------\n\n";
$vReturn = false;
#se verifica la validez del token almacenado y si no lo fuera se obtiene uno nuevo
if (!$this->isValidToken()) {
echo "No se pudo obtener un token válido";
return $vReturn;
}
$this->customer = array();
try {
$request = curl_init($this->hostAPI."/sales/customers/".$customerId);
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($request, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_HTTPHEADER, array(
"Accept: application/json",
"Authorization: Bearer ".$this->credential->{"token"})
);
//make GET
$respond = curl_exec($request);
//respond status code
$respondStatusCode = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($respondStatusCode == 200) {
$vReturn = true;
$this->customer = json_decode($respond);
echo "customerId = " . $this->customer->{"customerId"}."\n\n";
echo "name = " . $this->customer->{"name"}."\n\n";
echo "legalName = " . $this->customer->{"legalName"}."\n\n";
}
else {
$vReturn = false;
$requestError = json_decode($respond);
$requestErrorMessage = "";
if (isset($requestError->{"message"})) {
$requestErrorMessage = $requestError->{"message"};
}
echo "error get customer ".$requestErrorMessage."\n\n";
}
}
catch (Exception $error) {
$vReturn = false;
echo "Unexpected error: ", $error->getMessage(), "\n";
}
return $vReturn;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function putCliente($customerId){
//se realiza el guardado de datos del cliente
echo "-----------------------<< Guardar Customer >>-----------------------\n\n";
$vReturn = false;
#se verifica la validez del token almacenado y si no lo fuera se obtiene uno nuevo
if (!$this->isValidToken()) {
echo "No se pudo obtener un token válido";
return $vReturn;
}
try {
#se contruye el request body en json
$requestBodyJson = json_encode($this->customer);
$request = curl_init($this->hostAPI."/sales/customers/".$customerId);
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($request, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($request, CURLOPT_POSTFIELDS, $requestBodyJson);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_HTTPHEADER, array(
"Accept: application/json",
"Authorization: Bearer ".$this->credential->{"token"},
"Content-type: application/json",
"Content-Length: ".strlen($requestBodyJson))
);
//make POST
$respond = curl_exec($request);
//respond status code
$respondStatusCode = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($respondStatusCode == 200) {
$vReturn = true;
$this->customer = json_decode($respond);
echo "customerId = " . $this->customer->{"customerId"}."\n\n";
echo "name = " . $this->customer->{"name"}."\n\n";
echo "legalName = " . $this->customer->{"legalName"}."\n\n";
}
else {
$vReturn = false;
$requestError = json_decode($respond);
$requestErrorMessage = "";
if (isset($requestError->{"message"})) {
$requestErrorMessage = $requestError->{"message"};
}
echo "error get customer ".$requestErrorMessage."\n\n";
}
}
catch (Exception $error) {
$vReturn = false;
echo "Unexpected error: ", $error->getMessage(), "\n";
}
return $vReturn;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function isValidToken() {
#indica si el token almacenado en el objeto credential es válido
#si el token almacenado no es válido obtiene un nuevo token e igualmente indica su validez
$vReturn = true;
if (isset($this->credential->{"expiration"})) {
$ltNow = new DateTime("NOW");
$ltNow = $ltNow->format('c');
if ($this->credential->{"expiration"} < $ltNow) {
return $this->obtenerToken();
}
else {
return $vReturn;
}
}
else {
return $this->obtenerToken();
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
$ejemplo = new laudusAPI_Ejemplos();
if ($ejemplo->obtenerToken()) {
//en este ejemplo se usa el customerId 18
$customerId = 18;
if ($ejemplo->getCliente($customerId)) {
//se cambia el valor de la propiedad 'legalName' del cliente
$ejemplo->customer->{"legalName"} = "new legal Name";
if ($ejemplo->putCliente($customerId)) {
//guardado correctamente
}
}
}
?>
/*
Ejemplo para ejecutar por consola que recupera un cliente a través de la API, realiza unos cambios,
y graba el cliente modificado. Incluye obtención de token.
No hemos incluido tratamiento de llamadas síncronas/asincrónicas para no complicar el ejemplo.
Pero en un código en producción habría que tenerlo en cuenta para utilizar callbacks u otro método
para tener en cuenta los retrasos que se producen entre la llamda a la función y la respuesta del servidor
Por la misma razón no hemos incluido clases como en los otros ejemplos de los otros lenguajes de
programación, para no complicar más el código e ir directamente a la funcionalidad que se precisa.
*/
//Host
let hostAPI = "https://api.laudus.cl";
//objeto para preservar los credenciales de acceso a la API
let credential = {"token": "", "expiration": ""};
//objeto para representar la entidad Account (Cuenta del plan de cuentas contable)
let account = {};
//objeto para representar la entidad Customer (clientes)
let customer = {};
///////////////////////////////////////////////////////////////////////////////////////////////////////
function obtenerToken() {
//obtiene un token realizando un request a la API
let vReturn = false;
credential = {};
//esquema de request Login
let requestLoginSchema = {"userName": "", "password": "", "companyVATId": ""};
//se aplican los valores finales al esquema de request Login
requestLoginSchema.userName = "su nombre de usuario";
requestLoginSchema.password = "su clave de acceso";
requestLoginSchema.companyVATId = "RUT de sus empresa";
let requestBodyJson = JSON.stringify(requestLoginSchema);
console.log("-----------------------<< Obtener Token >>-----------------------");
let requestAPI = new XMLHttpRequest();
requestAPI.open("POST", hostAPI + '/security/login', false);
requestAPI.onreadystatechange=function() {
if (requestAPI.readyState==4) {
let respondStatusCode = requestAPI.status;
//se verifica al código status de respuesta
if (respondStatusCode == 200 && requestAPI.responseText.length > 0) {
vReturn = true;
credential = JSON.parse(requestAPI.responseText);
if (credential.token) {
console.log("token = " + credential.token);
console.log("expiration = " + credential.expiration);
}
}
else {
vReturn = false;
let requestErrorMessage = '';
if (requestAPI.responseText.length > 0) {
let requestError = JSON.parse(requestAPI.responseText);
if (requestError.message) {
requestErrorMessage = requestError.message;
}
}
console.log('error login ' + requestErrorMessage);
}
return vReturn;
}
}
//se construyen los headers requeridos para el request
requestAPI.setRequestHeader("Content-Type", "application/json");
requestAPI.setRequestHeader("Accept", "application/json");
requestAPI.send(requestBodyJson);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
function getCliente(customerId) {
//obtiene los datos de un cliente realizando un request a la API
let vReturn = false;
customer = {};
console.log("-----------------------<< Obtener Customer >>-----------------------");
let requestAPI =new XMLHttpRequest();
requestAPI.open("GET", hostAPI + '/sales/customers/' + customerId, false);
requestAPI.onreadystatechange=function() {
if (requestAPI.readyState==4) {
let respondStatusCode = requestAPI.status;
//se verifica al código status de respuesta
if (respondStatusCode == 200 && requestAPI.responseText.length > 0) {
vReturn = true;
customer = JSON.parse(requestAPI.responseText);
if (customer.customerId) {
console.log("customerId = " + customer.customerId);
console.log("name = " + customer.name);
console.log("legalName = " + customer.legalName);
}
}
else {
vReturn = false;
let requestErrorMessage = '';
if (requestAPI.responseText.length > 0) {
let requestError = JSON.parse(requestAPI.responseText);
if (requestError.message) {
requestErrorMessage = requestError.message;
}
}
console.log('error get cliente ' + requestErrorMessage);
}
return vReturn;
}
}
//se construyen los headers requeridos para el request
requestAPI.setRequestHeader("Accept", "application/json");
requestAPI.setRequestHeader("Authorization", "Bearer " + credential.token);
requestAPI.send();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
function putCliente(customerId) {
//modifica y guarda un cliente
let vReturn = false;
//se contruye el body del request
let requestBodyJson = JSON.stringify(customer);
console.log("-----------------------<< Guardar Customer >>-----------------------");
//send request
let requestAPI = new XMLHttpRequest();
requestAPI.open("PUT", hostAPI + '/sales/customers/' + customerId, false);
requestAPI.onreadystatechange=function() {
if (requestAPI.readyState==4) {
let respondStatusCode = requestAPI.status;
//se verifica al código status de respuesta
if (respondStatusCode == 200 && requestAPI.responseText.length > 0) {
vReturn = true;
customer = JSON.parse(requestAPI.responseText);
if (customer.customerId) {
console.log("customerId = " + customer.customerId);
console.log("name = " + customer.name);
console.log("legalName = " + customer.legalName);
}
}
else {
vReturn = false;
let requestErrorMessage = '';
if (requestAPI.responseText.length > 0) {
let requestError = JSON.parse(requestAPI.responseText);
if (requestError.message) {
requestErrorMessage = requestError.message;
}
}
console.log('error put customer ' + requestErrorMessage);
}
return vReturn;
}
}
//se construyen los headers requeridos para el request
requestAPI.setRequestHeader("Content-Type", "application/json");
requestAPI.setRequestHeader("Accept", "application/json");
requestAPI.setRequestHeader("Authorization", "Bearer " + credential.token);
requestAPI.send(requestBodyJson);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
function isValidToken() {
//indica si el token es válido
let vReturn = false;
let ldNow = new Date();
ldNow = ldNow.toISOString();
if (credential.expiration) {
if (credential.expiration > ldNow) {
vReturn = true;
}
}
return vReturn;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//customerId usado en el ejemplo
let customerId = 18;
obtenerToken();
if (isValidToken()) {
getCliente(customerId);
//se verifica que exista un cliente cargado y que corresponde con el que queremos modificar
if (customer.customerId && customer.customerId == customerId) {
//se modifica la propiedad legalName del cliente
customer.legalName = 'Mi razón social';
putCliente(customerId);
}
}