Seamos sinceros. Crear un endpoint en Magento es como intentar recordar la letra de una canción del verano de 2003. Te lo sabes seguro, pero hacerlo bien a la primera es imposible.
Llevas toda la mañana peleando y tu historial de Google parece un grito de auxilio (magento api endpoint example not working please help), y con IA no tienes más suerte. Eso sí, te responde con la seguridad de un político en campaña: parece que sabe, pero en realidad no tiene ni p*** idea.
Tranquilo, respira. Estoy aquí para dejarte una guía que SÍ funciona, explicada para que no tengas que vender tu alma al diablo.
Hoy vamos a crear:
- Un endpoint REST privado (tipo POST, de los de toda la vida)
- Los datos de entrada y salida son json
- Accesible con identificación (access token) de cliente de tu tienda (no admin, sino cliente registrado, eso otro es otro post…)
A primera vista, el API de Magento puede parecer un monstruo mitológico hecho de interfaces, XMLs y clases que se llaman unas a otras. Pero la realidad es que, una vez le pillas el truco, es un proceso bastante lógico. Como montar un mueble de IKEA, pero con menos tornillos sobrantes (normalmente).
Me evitaré el rollo de siempre, de empezar creando un módulo… eso ya te lo sabes… o eso espero. Si no, no se muy bien que haces aquí 😜.
Crea las Interfaces. Dan una pereza mortal, pero son tu salvavidas.
Hacer esto es como cuando tu madre te decía que te pusieras una rebequita «por si refresca». Que te da una pereza tremenda, pero luego cuando refresca y no la llevas te cagas de frio (aunque eso nunca se lo reconociste).
Y sí, ya se: «¿Una interfaz y una clase para pasar un triste string? ¿Estamos locos?». Confía en el proceso. Es la magia negra de Magento. Hoy es un string, mañana te piden añadir 15 campos más y te acordarás de mí (para bien). Escríbelas.
Define una interfaz para la petición (o sea, para lo que entra):
<?php
namespace Bydn\Helpdesk\Api\Ai;
interface RequestInterface {
const CONVERSATION = 'conversation';
/**
* @return string
*/
public function getConversation();
/**
* @param string $description
* @return $this
*/
public function setConversation(string $conversation);
}
Y otra interfaz para lo que será la respuesta (lo que sale):
<?php
namespace Bydn\Helpdesk\Api\Ai;
interface ResponseInterface {
const RESPONSE = 'response';
/**
* @return string
*/
public function getResponse();
/**
* @param string $response
* @return $this
*/
public function setResponse(string $response);
}
Ahora necesitarás una Interfaz para el «director de orquesta», la clase que gestionará la llamada. Lógicamente, usará las dos interfaces que acabas de crear.
<?php
namespace Bydn\Helpdesk\Api;
interface AiInterface
{
/**
* @param \Bydn\Helpdesk\Api\Ai\RequestInterface $data Input data
* @return \Bydn\Helpdesk\Api\Ai\ResponseInterface data return
* @throws \Magento\Framework\Webapi\Exception Exception thrown
*/
public function process(\Bydn\Helpdesk\Api\Ai\RequestInterface $data): \Bydn\Helpdesk\Api\Ai\ResponseInterface;
}
La implementación. Ahora sí, a picar código de verdad 🤘
Listo. Ya le hemos prometido a Magento el oro y el moro con las interfaces. Ahora toca la parte divertida (o menos aburrida).
La Request (la caja para los datos de entrada):
<?php
namespace Bydn\Helpdesk\Model\Api\Ai;
class Request implements \Bydn\Helpdesk\Api\Ai\RequestInterface
{
/**
* @var string|null
*/
private $conversation;
/**
* Get conversation
*
* @return string|null
*/
public function getConversation()
{
return $this->conversation;
}
/**
* Set conversation
*
* @param string $conversation
* @return $this
*/
public function setConversation($conversation)
{
$this->conversation = $conversation;
return $this;
}
}
La Response (la caja para los datos de salida):
<?php
namespace Bydn\Helpdesk\Model\Api\Ai;
class Response implements \Bydn\Helpdesk\Api\Ai\ResponseInterface
{
/**
* @var string|null
*/
private $response;
/**
* Get Description
*
* @return string|null
*/
public function getResponse()
{
return $this->response;
}
/**
* Set Description
*
* @param string $description
* @return $this
*/
public function setResponse($response)
{
$this->response = $response;
return $this;
}
}
Y la clase que hace la magia de verdad:
<?php
namespace Bydn\Helpdesk\Model\Api;
use Bydn\Helpdesk\Api\AiInterface;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\Webapi\Exception as WebapiException;
use Magento\Framework\Phrase;
class Ai implements AiInterface
{
private Curl $curl;
private Json $json;
private \Bydn\Helpdesk\Model\Api\Ai\ResponseFactory $responseFactory;
public function __construct(
Curl $curl,
Json $json,
\Bydn\Helpdesk\Model\Api\Ai\ResponseFactory $responseFactory
) {
$this->curl = $curl;
$this->json = $json;
$this->responseFactory = $responseFactory;
}
/**
* @inheritdoc
*/
public function process(\Bydn\Helpdesk\Api\Ai\RequestInterface $data): \Bydn\Helpdesk\Api\Ai\ResponseInterface
{
try {
// Pon aquí tiu lógica maravillosa
$r = $this->responseFactory->create();
$requestText = $data->getConversation();
$r->setResponse($requestText . " => hola caracola");
return $r;
}
catch (\Exception $e) {
// Gestiona aquí los errores
}
}
}
Configurando los XMLs (la parte menos sexy)
Vale, ya tenemos la lógica. Ahora hay que ponerle un cartel de neón en la puerta para que las peticiones sepan dónde llamar. Eso se hace en el maravilloso mundo del XML.
etc/webapi.xml
Con esto le decimos a Magento: «La URL https://<mi-tienda>/rest/V1/ai/process la atiende el método process de la clase que implemente \Bydn\Helpdesk\Api\AiInterface«.
Y con ref="self", le ponemos un portero en la puerta que solo deja pasar a clientes con su token. 💪
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route url="/V1/ai/process" method="POST">
<service class="Bydn\Helpdesk\Api\AiInterface" method="process"/>
<resources>
<resource ref="self"/>
</resources>
</route>
</routes>
Y ahora el último puzzle. Tenemos las promesas (Interfaces) y los que cumplen las promesas (Clases). Ahora falta el chivato que le dice a Magento quién es quién. O sea el di.xml. Básicamente, aquí jugamos a «Unir con flechas».
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Bydn\Helpdesk\Api\AiInterface"
type="Bydn\Helpdesk\Model\Api\Ai" />
<preference for="Bydn\Helpdesk\Api\Ai\RequestInterface"
type="Bydn\Helpdesk\Model\Api\Ai\Request" />
<preference for="Bydn\Helpdesk\Api\Ai\ResponseInterface"
type="Bydn\Helpdesk\Model\Api\Ai\Response" />
</config>
Y… ¡voilà! 🎩✨ Con este conjuro, te prometo que funciona. Si no, es culpa de la caché (el 99,9% de las veces es la maldita caché). Ahora ya tienes el esqueleto. ¡A integrar se ha dicho!
Probando el endpoint (que funciona seguro, pero tu por si acaso pruebalo 😅)
Hora de jugar con la línea de comandos.
Primero, necesitamos un access token. Recuerda, con un cliente de la tienda, no un admin.
curl -X POST \
-H "Content-Type: application/json" \
-d '{"username":"<email del cliente>","password":"<password>"}' \
https://<url-de-la-tienda>/rest/V1/integration/customer/token
Esto te devolverá el preciado token. Cópialo.
Y ahora, el momento de la verdad. Lanza la petición a tu flamante endpoint:
curl -X POST "https://<url-de-mi-tienda>/rest/V1/ai/process" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token-del-usuario>" \
-d '{"data": {"conversation": "Texto de entrada"}}'

Hey! Qué opinas sobre el artículo?