Conecta Zoho con WordPress a través de su API

Cómo conectar los formularios de WordPress con las campañas de Zoho a través de su API.

Al tener tantas opciones/caminos Zoho puedes perderte entre tanta documentación, paneles, etc…

En esta ocasión os voy a contar el camino que tomé para suscribir a usuarios a unas determinadas listas y tener sincronizado los con WordPress para tener lo centralizado en un sitio y no depender 100% de la plataforma, y migrar relativamente fácil, entre Salesforce, HubSpot, Zoho, etc.

El código que se muestra en este artículo es de prueba y he intentado simplificarlo para una mejor compresión. No quiere decir que está sea la mejor forma de hacerlo.

Crear aplicación a través de la consola de Zoho.

Una vez que ya tienes cuenta de Zoho, nos vamos a su consola para crear la aplicación que vamos a usar.

Tienes que estar muy atento al dominio de la consola porque, si no te das cuenta, puedes crear la Aplicación en .eu, luego en la API llamar desde la .com y darte el error ‘invalid_client. Estos son los data centers que existen en este momento:

  • United States – .com
  • Europe – .eu
  • China – .cn
  • India – .in
  • Australia – .net.au

Existen varios tipos de aplicaciones, pero para este caso crearé una Aplicación Self Client, ya que voy a utilizarla desde el servidor.

Una vez creada, te genera el client_id y el clicent_secret.

Keys de Zoho
Keys para utilizar la API en la aplicación de Zojho.

El siguiente paso es generar manualmente el Code para solicitar el token. Configúralo con una duración de 10 minutos para que te dé tiempo a insertarlo en tu código y el Scope, que necesites.

En mi caso voy a usar el Scope ZohoCampaigns.contact.ALL, para tener control total sobre las campañas. Cada módulo de Zoho tiene sus Scope, en el caso de la API de campañas puedes verlos aquí.

Estos son los pasos que hay que seguir para generar el Code.

Paso 1 para generar el código de Zoho
Paso 1 para generar el código de Zoho
Paso 2 para generar el código de Zoho
Paso 2 para generar el código de Zoho
Paso 3 para generar el código de Zoho
Paso 3 para generar el código de Zoho

El código solo funciona para una vez, el resto de veces te da el error ‘invalid_client

Más información sobre este paso, aquí.

Solicitar token

Como ya disponemos del: client_id, client_secret, code solicitamos el token con el siguiente código.

function getToken() {
	$code = '1000.xxx.xxx';
	$client_id = '1000.xxx';
	$client_secret = '18dxxxx';
	$url_api = 'https://accounts.zoho.eu/oauth/v2';
	$token_transient_name = 'zoho_token';

		$args = array(
			'httpversion' 	=> '1.1',
			'timeout'		=> 300,
			'headers' 		=> array(
								'Accept' 			=> 'application/json',
								'Content-Type'		=> 'application/json'
			)
		);

		$url = $url_api .'/token?client_id='. $client_id .'&client_secret='. $client_secret .'&code='. $code .'&grant_type=authorization_code';
		$response = wp_remote_post($url, $args);

		if (!is_wp_error($response)) {
			$body = json_decode( wp_remote_retrieve_body($response), true);
			$status_code = wp_remote_retrieve_response_code($response);

			if (200 === $status_code) {

				if ($body['error']) {
					return false;
				}

				$access_token = $body['access_token'];
				$refresh_token = $body['refresh_token'];
				$api_domain = $body['api_domain'];
				$token_type = $body['token_type'];
				$expires_in = $body['expires_in'];

				$data = compact('access_token','refresh_token','api_domain','token_type','expires_in');

				// guardamos el token
				set_transient( $token_transient_name, $data, DAY_IN_SECONDS );
				return true;
			}
		}

		return false;
}

Utilizamos wp_remote_post para conectarnos a la API según nos indica la documentación de Zoho (más info) y, si todo va bien, guardamos el token y otros valores en la API Transient (opción con fecha de caducidad) para luego recuperarlos. Tenéis un ejemplo entrando más en detalle de cómo funciona Transients en la web de Pablo López.

A Tener en cuenta a la hora de solicitar el token

  • No hace falta la serialización de los datos a la hora de guardarlo en la API Transient, ya que lo hace por nosotros.
  • Para que funcione perfectamente la API Transient de WordPress, en el fichero wp-config.php poner «define(‘WP_CACHE’, true);» y si tenéis la web en Siteground desactivar la opción «Memcached» 😞

Refrescar Token.

Después necesitamos una función para refrescar el token y que no nos caduque de la siguiente forma:

function refershToken(){
        $toke_data = get_transient('zoho_token');
		$refresh_token = $toke_data['refresh_token'];

		$args = array(
			'httpversion' 	=> '1.1',
			'timeout'		=> 300,
			'headers' 		=> array(
								'Accept' 			=> 'application/json',
								'Content-Type'		=> 'application/json'
			)
		);

		$url = $this->_url_api .'/token?client_id='. $this->_client_id .'&client_secret='. $this->_client_secret .'&refresh_token='. $refresh_token .'&grant_type=refresh_token';
		$response = wp_remote_post($url, $args);

		if (!is_wp_error($response)) {
			$body = json_decode( wp_remote_retrieve_body($response), true);
			$status_code = wp_remote_retrieve_response_code($response);

			if (200 == $status_code) {

				if ($body['error']) {
					return false;
				}

				$toke_data['access_token'] = $body['access_token'];

				// guardamos el token.
				set_transient( $this->_token_transient_name, $toke_data, DAY_IN_SECONDS );
				return true;
			}
		} 
		
		return false;
    }

Cron para refrescar el token

Tuve que crear un cron específico para refrescar el token que ejecuto cada 30 min a través de cron-job.org con el siguiente código.

// creamos un hook para indicar el metodo a ejecutar.
add_action('bk_cron_refershtoken', 'cronRefershToken', 10);
if (! wp_next_scheduled('bk_cron_refershtoken')) {
   /**
   * hourly: Cada hora
   * twicedaily: Dos veces al día (cada 12 horas)
   * daily: Una vez al día (cada 24 horas)
   * weekly: Una vez a la semana
   */
			
   $time = time();
   wp_schedule_event(($time), 'hourly', 'bk_cron_refershtoken');
}

function cronRefershToken(){
	refershToken();
}

// Si necesitas eliminarlo.
$timestamp = wp_next_scheduled('bk_cron_refershtoken');
wp_unschedule_event($timestamp, 'bk_cron_refershtoken');

Si necesitas más información pásate por el artículo: Cómo trabajar con los crons de WordPress y no morir en el intento de Pablo López

Es muy útil utilizar el plugin WP Crontrol para ver si se ha creado y hacerle un seguimiento.

Suscribir al usuario a una lista

Lo primero que debemos hacer es ir a Zoho para crear una lista, campos, etc. y, una vez la tengamos, nos vamos a su configuración para coger su clave.

Clave de la lista para tener acceso a través de la API.
Clave de la lista para tener acceso a través de la API.

Una vez tengamos la Clave de la lista ya podemos acceder a ella a través de la API para hacer lo que necesitemos. En este caso nos suscribiremos a ella a través de unos datos que podemos recibir de un formulario de WordPress por ejemplo. Lo haremos con el siguiente código:

function subscribe(){
   // Sacamos los datos de la API Transient 
   $toke_data = get_transient('zoho_token');
   $token = $toke_data['access_token'];
		
   $args = array(
      'httpversion' 	=> '1.1',
      'timeout'		    => 300,
      'headers' 		=> array(
         'Accept' 			=> 'application/json',
         'Content-Type'		=> 'application/json',
         'Authorization'		=> 'Zoho-oauthtoken '. $token
      )
   );

   $listkey = '3zxxxx'; // Clave de la lista que hemos sacado del CMS.
   $data = '{"First Name":"Cachito","Last Name" :"De Cielo", "Contact Email":"test@vgamil.com", "Job Title": "Mosca cojonera"}';
   $source = 'Api test';
   $url = 'https://campaigns.zoho.eu/api/v1.1/json/listsubscribe?resfmt=JSON&listkey='. $listkey .'&contactinfo='. $data .'&sources='. $source;
   $response = wp_remote_post($url, $args);

   if (!is_wp_error($response)) {
      $body = json_decode( wp_remote_retrieve_body($response), true);
      $status_code = wp_remote_retrieve_response_code($response);

      if ( 200 === $status_code) {
         $status = $body['status'];  // ok -> 'success', Ko -> 'error'
         $code = $body['code']; // ok -> 0 , Ko -> Otro número
         $message = $body['message'];
         return compact('status', 'code', 'message');
      }
   }
   return false;
}

Lo más importante de estas líneas de código es que en la cabecera tenemos que poner en autorización «Zoho-oauthtoken», un espacio seguido del token para que tengamos acceso a la API y el valor de ‘source’.

Podemos tener diferentes valores de Sources para que se quede guardado de dónde vienen los datos y hacer así una mejor segmentación de las personas registradas.

En esta ocasión hemos utilizado la versión 1.1 de la API de campañas que es la recomendada.

A tener en cuenta a la hora de suscribir usuarios

  • Si el email ya está registrado los datos de ese registro se actualizaran.
  • El mayor problema que me he encontrado es que al solicitar el Token si es erróneo te muestra el error ‘invalid_client’. Prácticamente todos los mensajes de error es ese mensaje, y te pasas el tiempo en verificar el ID del Cliente probando diferentes aplicaciones de la consola, etc. Tenedlo en cuenta a la hora de identificar el problema.

Avisos por email si se produce un error en la API de Zoho al suscribir al usuario.

Inssertando el siguiente código donde se producen los errores de la API, podemos enviar notificaciones por email y así recuperar los datos perdidos y ponernos en contacto con el posible cliente.

$html_msg = '<p>source: '. $source.'</p><p>contact: '. $data .'</p><p>message: '. $message .'</p>';
sendMail('Error '. $code .' - Zoho subscribe', $html_msg);

// función que realiza el envío.
function sendMail ($subject, $body){
    $to = 'cachito.decielo@vgamil.com';
    $headers = array('Content-Type: text/html; charset=UTF-8');
	wp_mail( $to, $subject, $body, $headers );
}

Y así quedaría la notificación.

Notificación de error a la hora de suscribirte en una lista de Zoho.
Notificación de error a la hora de suscribirte en una lista de Zoho.

Conclusión

Lo peor de la API, en mi opinión, es la forma de conseguir el token, diferentes sitios/api  con documentación y los mensajes de error.

Quizás sea porque no haya profundizado suficiente en la documentación o no lo haya dedicado el tiempo necesario. Lo que me mata es no poder solicitar el nuevo Token a través de la API.

Pero si quieres que utilicen tu producto, api, etc. tienes que facilitar las cosas e ir al grano. Por normal general somos vagos y cuánto menos nos cueste más lo utilizaremos… «la ley del mínimo esfuerzo».

Utilizo en mi día a día Salesforce, Hubspot y ahora Zoho. Y como desarrollador, con el que más cómodo me siento es «Hubspot», buena documentación, etc. Aunque «en el reino de los ciegos el tuerto es el rey».