Valida tus teléfonos móviles y fijos con la base de datos del IFT

13 Ene

Plan de numeración Instituto Federal de Telecomunicaciones

La versión más reciente de este código la podrás encontrar en Github.

En México tenemos diferentes mecanismos de marcación de un número, dependiendo si este es fijo (01) o celular (044 o 045). Esto complica un poco las cosas, ya que el identificador de llamadas (callerid) siempre es de 10 dígitos, por lo que si recibimos una llamada de un número X, no podemos simplemente devolver la llamada a este número ya que tenemos que prefijarlo según el tipo de teléfono destino que es.

Afortunadamente, el Instituto Federal de Telecomunicaciones (IFT) publica una base de datos que determina si una serie telefónica corresponde a un número móvil o fijo. Dado que aquí los teléfonos los marcamos diferentes dependiendo del tipo de línea, es muy importante tener presente siempre que tipo de teléfono es el que estamos llamando para ajustar nuestro plan de marcación acorde.

Esto resulta muy conveniente de hacer en sistemas de marcación predictiva donde las listas pueden estar capturadas a 10 dígitos y nosotros convertir cada número a fijo o móvil según la base nos lo diga. En Asterisk, esta funcionalidad es muy fácil de implementar con una base de datos, una función personalizada de ODBC (func_odbc) o un AGI. Aquí te dejo la guía de como lograrlo utilizando un AGI.

Antes de comenzar, asumimos lo siguiente:

  • Que ya tienes instalado PHP en tu sistema.
  • Que ya tienes instalado y cuentas con experiencia con MySQL y que sabes como importar tablas a partir de un archivo SQL.
  • Que la base de datos de nombre asterisk ya está creada.
  • Que entiendes el plan de marcación básico.

Dando esto por sentado, comencemos:

Paso 1. Consigue el listado de numeración del IFT

Ya me encargué de limpiar la lista y dejar solamente estos 5 campos:

  • Código de área (int)
  • Serie (int)
  • Numeración inicial (int)
  • Numeración final (int)
  • Móvil (bool)

Puedes descargar el archivo ya en formato SQL listo para importar. Si prefieres conseguir el archivo por tu cuenta directamente del IFT y actualizarlo tu, puedes conseguirlo desde esta liga.

Una vez descargado, descomprímelo e impórtalo en MySQL. En este tutorial asumiremos que la tabla se creará en la base de datos asterisk. Si lo quieres poner en una base de datos diferente, edita el archivo SQL y apúntalo a donde necesites.

Para proceder, necesitas la contraseña de root de MySQL:

mysql -p asterisk < bdift_safe.sql

Esto creará la tabla ift en la base de datos asterisk. Ahora crearemos el AGI para poder consultarla.

Paso 2. Crea el AGI ift.php

Para el siguiente paso, crearemos un AGI que se encargue de consultar la tabla creada en el paso anterior. El AGI lo crearemos con el nombre /var/lib/asterisk/agi-bin/ift.php.

#!/usr/bin/php -q
<?php

// Cambiar esta constante por el codigo de area local desde donde se originan las llamadas
define('LOCAL','55');

// Parametros de acceso a la base de datos.
$db['user'] = 'asteriskuser';
$db['pass'] = 'asteriskpass';
$db['name'] = 'asterisk';
$db['host'] = 'sql.enlaza.mx';

// ***************** No cambiar nada a partir de este punto

require_once "phpagi.php";
$agi = new AGI();

if ( (!is_numeric($argv[1])) || (strlen($argv[1]) < 10) ) {
	$agi->verbose('No se proporciono un numero de 10 digitos');
	$agi->set_variable('MOVIL',0);
	$agi->set_variable('PREFIJO','');
	$agi->set_variable('COMPLETO','');
	exit;
}

// Nos quedamos solo con los ultimos 10 digitos para asegurar que quitamos cualquier prefijo
$numero = substr($argv[1],-10);

if (!$data = mysql_connect($db['host'],$db['user'],$db['pass'])) {
	$agi->verbose('Error de conexion a la BD');
	$agi->set_variable('MOVIL',0);
	$agi->set_variable('PREFIJO','');
	$agi->set_variable('COMPLETO','');
	exit;
}

// Definimos codigos de area de 2 digitos para conocer cual es el codigo de area y cual es el numero local
$areas = array('55','81','33');
if (in_array(substr($numero,0,2),$areas)) {
	$area = substr($numero,0,2);
	$local= substr($numero,2);
	$serie= substr($local,0,4);
}
else {
	$area = substr($numero,0,3);
	$local= substr($numero,3);
	$serie= substr($local,0,3);
}

$query = "SELECT movil FROM ".$db['name'].".ift WHERE SUBSTRING('$numero',7) BETWEEN inicial AND final AND `area` = $area AND serie = $serie LIMIT 1";
$result = mysql_query($query,$data);
$row = mysql_fetch_array($result);
$agi->set_variable('MOVIL',$row['movil']);

if (substr($numero,0,strlen(LOCAL)) == LOCAL) {
	if ($row['movil'] == 1) {
		$agi->set_variable('PREFIJO','044');
		$agi->set_variable('COMPLETO', '044'.$numero);
	}
	else {
		$agi->set_variable('PREFIJO','');
		$agi->set_variable('COMPLETO', $local);
	}
}
else {
	if ($row['movil'] == 1) {
		$agi->set_variable('PREFIJO','045');
		$agi->set_variable('COMPLETO', '045'.$numero);
	}
	else {
		$agi->set_variable('PREFIJO','01');
		$agi->set_variable('COMPLETO', '01'.$numero);
	}
}
exit;
?>

Para que funcione es necesario cambiar:

  • La constante LOCAL. Reemplázala por el código de área de tu población.
  • Los parámetros de conexión a tu base de datos.

El AGI es bastante sencillo y lo que hace es:

  1. Recibe como argumento un número de 10 dígitos. No debe tener más ni menos.
  2. Descompone ese número y extrae el código de área, ya sea de 2 dígitos (México, Guadalajara o Monterrey) o de 3 dígitos (resto del país) y la serie del número local.
  3. Compara estos números contra la base de datos creada.
    1. Si encuentra el registro, lo cataloga de acuerdo al campo movil de la tabla.
    2. Si no lo encuentra, lo cataloga como fijo.
  4. Para la entrega de resultados, el AGI crea las siguientes variables:
    1. ${MOVIL}. Es 0 o 1, dependiendo si el número se considera fijo o móvil, respectivamente.
    2. ${PREFIJO} es el prefijo de marcación: 01, 044 o 045.
    3. ${COMPLETO} contiene el número tal cual se tiene que marcar de acuerdo al plan de numeración de México. Es la combinación de ${PREFIJO} y de ${EXTEN}. Si el número es fijo y está en el mismo código de área que el AGI, entonces te lo entrega en 7 dígitos.

Ejemplos de corrida. Asumimos que la variable LOCAL es configurada con 33 (Guadalajara):

  • AGI(ift.php,5546144400) te da:
    • ${MOVIL} es 0, ya que el número es fijo.
    • ${PREFIJO} es 01, ya que es considerado larga distancia nacional.
    • ${COMPLETO} es 013346144400
  • AGI(ift.php,5513208860) te da:
    • ${MOVIL} es 1, ya que el número es celular.
    • ${PREFIJO} es 045, ya que es considerado celular con LDN.
    • ${COMPLETO} es 0455513208860.

Paso 3. Crea el plan de marcación

El último paso es utilizar las variables que el AGI crea para hacer la marcación. El plan de marcación se colocará en el extensions.conf de /etc/asterisk, y será algo más o menos así:

exten => _NXXXXXXXXX,1,AGI(ift.php,${EXTEN})
same => n,Dial(DAHDI/g0/${COMPLETO},,Tt)

Si estás utilizando FreePBX o Elastix, el plan de marcación lo pondrás dentro del extensions_custom.conf, y la troncal la crearás de tipo custom para que pueda apuntar a este plan de marcación personalizado.

Con este AGI puedes implementar una marcación uniforme y evitar muchos posibles errores de marcación (muy útil si esto lo haces en un callcenter). Actualmente, muchos de nuestros clientes utilizan una variante de este script y sus sistemas funcionan sin problema.

¿Alguna duda? Déjala en los comentarios.

¡Suerte!

Christian Cabrera

Soy ingeniero en comunicaciones con especial interés en el área de voz sobre IP y tecnologías sobre información. He usado Asterisk de manera diaria desde hace más de 18 años. En el 2011 co-fundé Enlaza Comunicaciones, una empresa que se especializa en brindar servicios profesionales de consultoría sobre voz sobre IP basadas en Asterisk, así como servicios de interpretación simultánea y traducción.