Saltar al contenido

Etiqueta: wordpress

Agregar rutas personalizadas en el API REST de WooCommerce

WooCommerce es una excelente plataforma para montar tu propia tienda en línea. Aunque mucha gente piensa que WordPress sigue siendo solo una plataforma para blogs, desde hace años se ha cambiado el funcionamiento interno para soportar todo tipo de contenido. WooCommerce es un ejemplo de ellos, pues este plugin permite soportar todo el contenido requerido en una tienda en línea como: productos, órdenes, pagos, descuentos, entre otros. Además de incluir una API REST para realizar acciones adicionales sobre él.

API REST

El plugin incluye una API REST para las operaciones mas básicas (se debe activar previamente), permitiendo comunicación hacia o desde aplicaciones externas, extendiendo aún mas las posibilidades de procesos que se pueden implementar en la tienda. Sin embargo, si manejas flujos de compras personalizados o deseas realizar acciones mas allá de las disponibles en el API por defecto, puedes agregar las tuyas tal como se explicará a continuación.

Desarrollo del plugin

El plugin se divide en 2 archivos, el principal para definir el plugin como tal y permitirle indicar a WordPress en que momento se va a cargar el segundo archivo, que contiene los métodos que responden a las rutas personalizadas del API.

Cargador de la clases

Para modificar WordPress, siempre es recomendable hacerlo a través de plugins, por eso el primer paso es definir un plugin como cualquier otro y dentro del constructor de la clase del plugin, indicar a WooCommerce que luego de cargar el código necesario para implementar el API (a través del hook woocommerce_api_loaded) se deben agregar la(s) clase(s) que implementan las rutas personalizadas (a través del hook woocommerce_api_classes), este código lo pueden ver a continuación:

/**
 * Custom API REST path  class
 *
 * @package MyPlugin
 * @author Skatox
 */
class WC_API_Custom extends WC_API_Resource
{

    const PATH = '/custom';

    /**
     * Function to define each of the custom path
     */
    public function register_routes($routes)
    {
        //GET Request
        $routes[self::PATH . '/orders'] = array(
            array(array($this, 'listShippingOrders'), WC_API_Server::READABLE),
        );

        //POST Request
        $routes[self::PATH . '/orders/(?P<order_id>\d+)/fulfillments.json'] = array(
            array(array($this, 'createItem'), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA),
        );

        //PUT Request
        $routes[self::PATH . '/variants/(?P<id>\d+).json'] = array(
            array(array($this, 'updateItem'), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA),
        );

        return $routes;
    }

    public function listShippingOrders($fields = null, $filter = array(), $status = null, $page = 1)
    {
        $wcApiOrders = new WC_API_Orders($this->server);
        $orders = $wcApiOrders->get_orders($fields, $filter, $status, $page);

        //Removes orders without shipping methods
        foreach ($orders['orders'] as $key => $order)
        {
            if (empty($order['shipping_methods'])) {
                unset($orders['orders'][$key]);
                continue;
            }
        }

        return $order;
    }

    public function createItem($order_id, $data)
    {
        //Do insert proccess and then return the response array
    }

    public function updateItem($id, $data)
    {
        //Do update proccess and then return the response array

    }
}

Leyendo observarán que es un plugin de WordPress donde la clase WD_API_LOADER registra los hooks mencionados anteriormente, para inyectar en el momento que Woocommerce carga sus clases del API, las clases que instancia los procesos personalizados a ser implementados en el API.

Al final es recomendable instanciar la clase en un objeto, de este modo es posible acceder a los métodos de forma global desde plugines externos, como por ejemplo para detener la carga de las clases o implementar modificaciones permitiendo dar mayor flexibilidad al plugin.

Clase con los métodos de la API REST

El siguiente paso corresponde a crear la clase que responde a las peticiones HTTP del API. En este ejemplo, se define una constante con el PATH personalizado y en el constructor se definen las rutas personalizadas y el método que se debe llamar que responderá a la petición realizada. Si observas, el parámetro recibido es un array donde la llave representa la ruta relativa del API y como valor, otro arreglo con el nombre de la función a procesar la petición y las banderas del tipo de petición. Estas últimas banderas permiten definir el tipo de petición a recibir, por ejemplo
WC_API_Server::READABLE indica que lee datos desde la petición tal como es una petición GET,
WC_API_Server::ACCEPT_DATA permite decir que lea el cuerpo de la petición y permite leer información para peticiones POST y PUT, entre otros.

/**
 * Custom API REST path  class
 *
 * @package MyPlugin
 * @author Skatox
 */
class WC_API_Custom extends WC_API_Resource
{

    const PATH = '/custom';

    /**
     * Function to define each of the custom path
     */
    public function register_routes($routes)
    {
        //GET Request
        $routes[self::PATH . '/orders'] = array(
            array(array($this, 'listShippingOrders'), WC_API_Server::READABLE),
        );

        //POST Request
        $routes[self::PATH . '/orders/(?P<order_id>\d+)/fulfillments.json'] = array(
            array(array($this, 'createItem'), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA),
        );

        //PUT Request
        $routes[self::PATH . '/variants/(?P<id>\d+).json'] = array(
            array(array($this, 'updateItem'), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA),
        );

        return $routes;
    }

    public function listShippingOrders($fields = null, $filter = array(), $status = null, $page = 1)
    {
        $wcApiOrders = new WC_API_Orders($this->server);
        $orders = $wcApiOrders->get_orders($fields, $filter, $status, $page);

        //Removes orders without shipping methods
        foreach ($orders['orders'] as $key => $oreder)
        {
            if (empty($oreder['shipping_methods'])) {
                unset($oreders['orders'][$key]);
                continue;
            }
        }

        return $order;
    }

    public function createItem($order_id, $data)
    {
        //Do insert proccess and then return the response array
    }

    public function updateItem($id, $data)
    {
        //Do update proccess and then return the response array

    }
}

Una vez que proceses la petición, si necesitas devolver un objeto JSON, simplemente debes retornar un array con la información deseada y automáticamente Woocommerce se encargará de transformarlo en un objeto JSON e imprimirlo en la salida.

Recomendaciones

Como podrás observar, no es difícil. En caso que no sepas como desarrollar debido a la poca documentación. Te recomiendo leer el código fuente de las clases del API de Woocommerce, son fáciles de entender, creadas por el mismo equipo del plugin y verás como están creados los métodos existentes. Una de las mejores clases para guiarte, es la de productos que se encuentra ubicada en la ruta wp-plugins/woocommerce/includes/api/class-wc-api-products.php, pues es muy completa y posee todas las operaciones REST soportadas.

Recuerda crear un plugin para esto, evita colocarlo en el functions.php pues será difícil de mantener y dificulta migrar de tema (porque el API dependerá de ésta). Finalmente, recuerda respetar el estándar REST, he visto gente que implementa todo en POST y agrega incompatibilidades a aplicaciones.

Ya depende de tu imaginación, descubrir como extender las funcionalidades de WooCommerce a través de un API REST personalizado.

2 comentarios

Como migrar tu base de datos de WordPress desde tu servidor local a producción

Generalmente si eres un buen desarrollador, tendrás tu entorno de desarrollo (servidor web, base de datos, etc) instalado en tu máquina local. De esta manera, puedes trabajar rápidamente al evitar solicitudes al servidor web remoto cada vez que realices modificaciones en un archivo o necesites visualizar cambios (por nombrar ejemplos), además, no requieres conexión a Internet, por lo que si ocurre una falla con el servicio o estas usando el ancho de banda para descargar cosas, no afectará tu flujo de trabajo.

En el caso de WordPress, existen dos opciones de configuración: home y siteurl que indican las URLs de la página inicial y sitio respectivamente. Por ello al realizar una instalación y configuración local, éstas variables tienen valores que apunta a localhost. Entonces, al momento de migrar la base de datos al servidor de producción, muchos enlaces quedan bajo el dominio localhost y no al dominio del sitio. Cambiar estos valores no ayuda mucho, pues si tienen imágenes, vídeos y archivos enlazados a contenidos creados dentro del editor, verán que no son accesibles porque siguen apuntando a localhost.

Para cambiarlo, se puede hacer con WP-CLI que es una útil herramienta de interfaz de comandos para WordPress, donde puedes administrar el sitio, datos, respaldos, entre otras cosas, sin salir de la consola. Pues para renombrar los URL de localhost a tu dominio, simplemente debes ejecutar los siguientes dos comandos.

Instalas wp-cli en tu sitio WordPress de producción usando curl:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar

Luego ejecutas el comando search-replace cuyo primer parámetro es la dirección actual (la local) y el segundo la dirección final del sitio:

wp search-replace 'https://localhost/sitio-de-desarollo' 'https://sitio-de-produccion.com/'

En caso que no te sirva el comando anterior porque no tienes configurado para la ejecución de archivos PHP automáticamente desde la consola ejecuta:

php wp-cli.phar search-replace 'https://localhost/sitio-de-desarollo' 'https://sitio-de-produccion.com/'

¡Listo! El comando se encargará de buscar en la base de datos cualquier referencia y la actualiza.

P.D: Si siempre trabajas en el servidor de producción o en un servidor remoto, estas perdiendo tiempo, ancho de banda, recursos y sobre todo dinero. ¡Aprende a optimizar!

Deja un comentario

Aumenta la seguridad de tu sesión en WordPress

Una de las principales preocupaciones de los usuarios de WordPress es el acceso al panel de administración, pues por defecto se encuentra en la ruta /wp-admin y está compuesto de un simple formulario que puede ser atacado por fuerza bruta. Por eso les voy a recomendar dos complementos para aumentar la seguridad de tu sesión en WordPress, al implementar autenticación de dos factores (Two Factor Authentication) y cambiar la ruta por defecto del formulario de inicio de sesión:

  • Rename WP Login: es un plugin muy liviano y sencillo, simplemente te permite definir una url personalizada para el formulario de inicio de sesión en la pantalla de enlaces permanentes, como por ejemplo https://tusitio.org/entrar-al-admin/. Aunque en el título dice que el plugin no tiene soporte, el autor se refiere a que no posee tiempo para resolver cualquier duda que se presente en los foros , sin embargo, acepta parches de código, nuevas funcionalidades, correcciones de bugs, entre otros. Por lo que puedes instalarlo sin preocuparte de que esté obsoleto.
  • Clef: un plugin recomendado por Manuel Camacho, consiste en una autenticación de 2 factores, es decir, aparte de brindar una información que solo tú conoces, debes dar información generada de un objeto que tienes contigo (el móvil o una tarjeta por ejemplo). En este caso, una vez que instalas el plugin la pantalla de inicio de sesión cambia a una especie de QR dinámico, el cual debes escanear con tu teléfono móvil a través de la aplicación Clef, una vez que reconoce el patrón único automáticamente inicia sesión en el sitio, lo chévere es que desde el teléfono controlas el tiempo de sesión e inclusive cerrarla remotamente. También se configurar para usar el inicio tradicional como respaldo en caso de que no tengas el teléfono contigo.

 

Utiliza Clef para aumentar seguridad de tu sesión en WordPress
Ejemplo de como funciona Clef

Con estos 2 sencillos plugins que puedes instalar y configurar en poco tiempo, podrás seguridad de tu sesión en WordPress, o mejor aún, el de tus clientes. Finalmente, si conocen alguna alternativa o desean compartir información adicional, no duden en dejar un comentario para mejorar la seguridad de nuestros sitios.

Editado el 15/06/2016: Ya el servicio de Clef no está disponible 🙁 puedes usar Google Authenticator para validar tus credenciales.

 

2 comentarios

Liberado jQuery Archive List 3.0

Luego de mas de un año sin poder dedicarme a este proyecto personal, he podido liberar la versión 3.0 de jQuery Archive List un widget de WordPress para mostrar el historial de sitio de una mejor manera y con efectos de jQuery. El salto a la versión 3, es debido a grandes cambios en el código de Javascript y en algunas cosas internas de plugin.

Entre las mejoras de esta nueva versión podrán encontrar:

  • Re-escritura completa del código Javascript, ahora ocupa menos espacio, código mas entendible y debería funcionar mas rápido.
  • Finalmente he agregado soporte para tipos de entradas personalizadas, así que puedes usar este widget si tienes tipos de contenido personalizados.
  • Agregué la clase active a los elementos que enlazan a la página actual.
  • Agregué el atributo de título a los enlaces para generar código HTML validado por la W3C.
  • Se agregó traducción al Holadés (gracias a Patrick Schreibing).
  • Se migró la selección de categorías al API de WordPress.
  • Se solucionó errores de exclusión de categorías.
  • Se solucionó el error de la ausencia de la clase expanded  en los meses (gracias to pjarts).
  • Se solucionó el error de no expandirse los meses al seleccionar algunas opciones.

Descárgalo desde el gestor de Plugins de WordPress o desde el sitio oficial de jQuery Archive List Widget. Y cualquier reporte o duda, no te olvides de reportarla en los foros de soporte de WordPress.

Deja un comentario