Tu primera App para BigCommerce - Parte III
Para finalizar la serie vamos a ver los aspectos de integración de nuestra App con BigCommerce y la gestión multi-tenant
En la segunda parte de esta serie indicamos cómo crear paso a paso una sencilla App para BigCommerce. En aquél artículo nos concentramos en los aspectos de desarrollo interno de la App a partir de un modelo de desarrollo local basado en Docker.
En esta parte, final de la serie, veremos otros aspectos importantes que también debemos abordar: la integración de la App con BigCommerce y los aspectos multi-tenant que toda buena App debe gestionar.
Pruebas de integración
Aunque el modelo que presentamos en la segunda parte es útil para desarrollar en local y desentendernos de la capa de complejidad adicional que supone trabajar como una verdadera App de BigCommerce, lo cierto es que de esta forma tenemos acceso a un único store de BigCommerce.
Recuerda que una App es multi-tenant por naturaleza. Eso significa que estará alojada en un servidor y dando servicio a un número indeterminado de tiendas. Cada una de las tiendas requiere de unos credenciales de acceso diferentes, y además tendrá que ser BigCommerce el que proporcione estos credenciales durante el dialogo de instalación de la App en la tienda.
En algún momento tendremos que pasar de nuestro ambiente de desarrollo puramente local a una prueba integrada con BigCommerce.
En la primera parte de este artículo se describió como crear y configurar nuestro borrador de aplicación en BigCommerce. Vamos a ver ahora como podemos hacer una prueba de nuestra App integrada con BigCommerce sin renunciar a trabajar en un entorno de desarrollo local basado en Docker.
Para ello la clave será una herramienta que se denomina ngrok. Esta utilidad crea un túnel desde Internet a un puerto local en nuestra computadora. Eso permite que un puerto como localhost:80
sea accesible a través de una URL pública de Internet.
Si no dispones de la herramienta, revisa la documentación para la mejor forma de instalarla en tu equipo. Cuando ya la tengas disponible ejecútala con el siguiente comando:
ngrok http 80
Esto hace que tanto https://0f06-185-248-78-225.ngrok-free.app como http://0f06-185-248-78-225.ngrok-free.app estén redirigidas a nuestro puerto local 80, que es donde lanzaremos nuestro contenedor Docker con la aplicación Laravel.
Ahora tenemos que hacer un pequeño cambio en el archivo de configuración de entorno (.env
) para indicar que ya no estamos en modo local:
APP_ENV=ngrok
APP_URL=https://0f06-185-248-78-225.ngrok-free.app
Tras hacer este cambio volvamos a levantar los contenedores:
vendor/bin/sail up
Y también vamos a hacer un cambio en el comportamiento de Laravel para que nos permita usar sin problemas un esquema de direcciones basado en HTTPS. En app/Providers/AppServiceProvider.php
incluir este código en el método boot()
:
public function boot(\Illuminate\Routing\UrlGenerator $url): void
{
if (env('APP_ENV') !== 'local') {
$url->forceScheme('https');
}
}
Si lanzamos nuestra aplicación en https://0f06-185-248-78-225.ngrok-free.app nos aparecerá un aviso indicando que estamos accediendo a través de un túnel y al aceptar volveremos a ver nuestra aplicación pero sin el nombre de la tienda y con el error en la consola al tratar de acceder al Proxy.
Para que el proxy funcione deberemos hacer dos cosas. Primero, en la definición del perfil de la aplicación de BigCommerce indicar las nuevas URLs de los callbacks, usando las URLs generadas por ngrok
. Para ello iremos al Developer Portal buscaremos nuestra App y pulsaremos el botón de Edit App:
Cuando hayamos terminado de editar las URLs pulsaremos Update & close. A continuación pulsaremos en View Client ID para obtener los parámetros que necesitamos para el segundo paso.
Los valores obtenidos debemos incluirlos en nuestro .env en las siguientes variables:
BC_APP_CLIENT_ID=<your-app-client-id>
BC_APP_SECRET=<your-app-client-secret>
Finalmente para probar nuestra App tendremos que instalarla en una tienda. Para ello inicia sesión en el panel de una tienda y vete a Apps > My Apps > My Draft Apps
Tu aplicación debería aparecer listada aquí:
Si has ejecutado bien todos los pasos deberías ver la App mostrando el nombre de la tienda:
Si miras el contenido de la tabla bc_authirzed_users
de tu base de datos local, comprobarás que se ha creado un registro para un store_hash
determinado y para el owner de esa tienda. Este registro contiene el access_token
que se está usando para pedirle a BigCommerce los datos de configuración básicos de la tienda.
Tokens JWT
¡¡Enhorabuena!! Tienes todas las piezas para desarrollar tu App en un entorno dockerizado, pero pudiendo probar de forma integrada con BigCommerce. Ha llegado la hora de hablar de aquél token que decidimos ignorar hace unos cuantos párrafos.
Vimos como nuestro controlador recibía un parámetro de entrada token, que luego en la vista convertía en una variable Javascript auth_token y que el contenido de esta variable se enviaba en una cabecera X-Auth-Token en las llamadas al proxy. Ésto es lo primero que hay que comprender:
El token se nos entrega al cargarse la aplicación.
Debemos hacerlo persistir en nuestra aplicación.
Debemos enviarlo en las futuras llamadas al proxy de BigCommerce.
De hecho la forma de hacer persistir el token que hemos empleado en el ejemplo no sería para nada la recomendada en un caso de uso genérico. Se debería guardar en una cookie o en Local Storage.
Como puedes suponer uno de los propósitos del token es que el proxy de BigCommerce pueda validar que las llamadas que se le hacen son lícitas, ya que solo el módulo bigcommerce-app-adapter puede generar tokens que luego él mismo reconozca como válidos.
Pero para ese propósito podríamos haber generado una clave de API cualquiera. Lo importante de un token JWT es que además nos provee de un mecanismo para adjuntar información.
Este es un ejemplo de token JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwic3ViIjoiMjNrZTd1dThnMCIsImlzcyI6IkxhcmF2ZWwiLCJpYXQiOjE2OTI3MjI3MzksImV4cCI6MTY5Mjc1MTUzOX0.1TczhZx25HUSovWiORdMORfIFcyFYBf_MWl-0AYHDCw
Aunque inicialmente parece un secreto criptográfico, no lo es. Este token está firmado, pero no encriptado. Por lo demás simplemente se ha codificado usando BASE64URL
que es un algoritmo reversible.
¿Cuál es la diferencia? Para decodificar un token encriptado necesitaríamos la clave (simétrica) o una parte de la clave (asimétrica). Un token firmado, por el contrario, no exige que conozcamos ningún secreto para poder decodificarlo. Sin embargo contiene una firma digital que nos impide alterar el contenido del token sin hacerlo inválido. Así que con una firma criptográfica sabemos: 1) que el token fue generado por la entidad que creo la firma (o por otra que conozca la clave); 2) que el contenido del token no se ha alterado.
Si copiamos el token anterior y lo pegamos en esta página podremos ver el contenido en claro del mismo:
El secreto que se ha usado para generar este token es ‘sample-insecure-signature-secret
’. Puedes pegarlo en your-256-bit-secret y entonces te dirá que la firma es válida.
El token tiene tres partes (si te fijas en la estructura del mismo hay dos ‘.’ que delimitan estas tres partes). La cabecera dice el algoritmo que se ha usado para firmar el token. La segunda y la que mas nos interesa es el payload o datos que incluye el token. La firma es la tercera parte.
Como hemos dicho estos datos no están encriptados y podríamos recuperarlos en nuestra aplicación con una sentencia como:
$payload = json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $token)[1]))));
Entendamos el significado de los datos que bigcommerce-app-adapter incluye en el token:
id: Es un identificador numérico único que representa al usuario administrador de BigCommerce que está usando la App.
sub: (subject) Es un identificador único de la tienda desde la que se está usando la App.
iss: (issuer): Identifica a la aplicación que generó el token (en Laravel se toma el parámetro APP_NAME)
iat: (issued at) Indica el instante de tiempo en que se generó el token (formato timestamp de Unix)
exp: (expires) Indica el instante de tiempo en que el token expira (formato timestamp de Unix)
Primera cosa que aprendemos: los tokens expiran. Podemos validar si el nuestro ya ha expirado en cualquier momento. El periodo de validez de los tokens que genera bigcommerce-app-adapter se puede configurar a través de token_duration_hours
en config/bigcommerce-app-adapter.php
. Cuando el token expira, es como si la sesión de la App de BigCommerce se cancelase. El usuario tendrá que volver a cargar la App para que se genere un token nuevo.
Gestión multi-tenant
El token también es importante para que nuestra App pueda gestionar los aspectos multi-tenant.
Repetimos que una App de BigCommerce debe ser diseñada como multi-tenant y que el caso de que haya una sola tienda en la que esté instalada (App llave en mano para un cliente) no deja de ser un caso de uso particular.
Para que nuestra App almacene o recupere datos de un tenant concreto, debemos basarnos en dos de los campos que van incluidos en el token:
Cuando tengamos datos que van asociados a un usuario, debemos asociarlos al campo
id
, que es un identificador único que representa a un usuario administrador concreto de una tienda en particular.Si por el contrario los datos deben estar asociados a nivel de tienda, entonces debemos usar el campo
sub
.
Podemos además extraer información adicional sobre el usuario como su e-mail y su id en BigCommerce (no tiene por que ser único). Para ello debemos acceder a la tabla bc_authorized_users
con el campo id = $id
o usar el modelo Eloquent Ebolution\BigcommerceAppAdapter\Infrastructure\Repositories\BCAuthorizedUser
(si tu aplicación usa arquitectura hexagonal usa en su lugar Ebolution\BigcommerceAppAdapter\Domain\BCAuthorizedUser
).
Conclusión
Siguiendo estos pasos puedes crear tu primera aplicación para BigCommerce, evitándote gran parte de la complejidad que ello supone gracias al módulo bigcommerce-app-adapter. Tendrás no obstante que desarrollar las vistas, controladores, modelos y demás elementos de la funcionalidad de tu App propiamente dicha.
Puedes desarrollar el dashboard de tu App de forma local abstrayéndote totalmente de la capa de BigCommerce. Cuando necesites integrar tu App con BigCommerce, puedes definir un perfil de aplicación en modo borrador y continuar con un modelo de desarrollo local pero de forma integrada con BigCommerce. El dashboard de tu App dentro del back-office de BigCommerce se muestra como un iframe dentro del panel de control de BigCommerce.
bigcommerce-app-adapter te permite gestionar las llamadas a la API de BigCommerce tanto en un modo de desarrollo local como en un modo de desarrollo integrado. También te da la información base para que puedas realizar la gestión multi-tenant.
No lo hemos cubierto en este artículo, pero es de suponer que desarrolles también una librería JavaScript que, partiendo del conocimiento de la estructura del DOM de tu plantilla, gestione los eventos que sean oportunos para que la funcionalidad de la App repercuta sobre el funcionamiento del front-office de la tienda.
Una App bien diseñada debería ser transparente para el desarrollador de front-end de la tienda, inyectando un script en el código HTML de la tienda y creando hooks a las funciones de la App vinculados con eventos sobre los elementos del DOM de tu plantilla.
¿Has usado bigcommerce-app-adapter y tienes sugerencias de ampliación o mejora? Eres bienvenido a contribuir con una pull request. También puedes contactar con Ebolution a través de https://www.ebolution.com/contacto/ o puedes escribirme directamente a carlos.cid@ebolution.com