Publicado por & archivado en PHP, Programación.

Desde febrero de 2014 es obligatorio el uso de cuentas en formato IBAN (International Bank Account Number), y aunque casi todos los bancos aun admiten el antiguo formato, antes o después nos encontraremos con la necesidad de convertir las cuentas en formato CCC.

Las cuentas IBAN se calculan añadiendo el código ISO 3166-1 del país junto a un código de control de dos cifras delante del BBAN (Basic Bank Account Number), que en España se corresponde con los 20 dígitos del CCC (Código Cuenta Cliente).

 

Para calcular el dígito de control del IBAN se añade el código ISO 3166-1 del país y dos ceros, se divide el número resultante entre 97 y el resto se resta de 98.

 

Aunque la norma ISO 3166-1 tiene especificado un código numérico, no es ese el que debe usarse, sino el conocido código alfa-2, que en el caso de España es ES.

 

Para convertir el código alfa-2 de la ISO 3166-1 se usa la siguiente correlación numérica con las letras:

A = 10 F = 15 K = 20 P = 25 U = 30 Z = 35
B = 11 G = 16 L = 21 Q = 26 V = 31
C = 12 H = 17 M = 22 R = 27 W = 32
D = 13 I = 18 N = 23 S = 28 X = 33
E = 14 J = 19 O = 24 T = 29 Y = 34

 

 

De esta forma, para el cálculo de España (ES), se utilizaría:

E=14
S=28

A esto se le añaden dos ceros, por lo que el código para España sería 142800.

 

Es decir, se divide el número resultante de concatenar los 20 dígitos de la cuenta bancaria con 142800 entre 97 y luego se resta a 98 el resto de esa división.

 

Hasta aquí todo fácil, pero hay un problema y es que el número resultante de sumar los 20 dígitos de la cuenta corriente, más los 4 del código ISO 3166-1, más dos ceros, es un número de 26 dígitos, demasiado grande para operar normalmente con las funciones de programación habituales, de esta forma, si lo intentamos con este código PHP:


echo 98 - (12341234161234567890142800 % 97);

No será capaz de manejar un número tan grande y devolverá siempre 0 de resto.

Esto empeora aun más con cuentas de otros países, ya que el BBAN puede tener hasta 34 caracteres alfanuméricos, lo que podría dar un número realmente gigante, por ejemplo un código de 34 caracteres con 4 letras nos daría un número de 48 dígitos, ya que todas las letras deben convertirse por su correspondiente número según la tabla anterior.

 

Para hacer semejante división hay varias soluciones, pero yo he decidido usar la librería de Pear Math_BigInteger, que permite hacer operaciones con números grandes que se le suministran como cadenas de texto (strings).

 

Se puede instalar desde la línea de comando con este simple comando:

pear install Math_BigInteger-1.0.2

 

Si no se puede acceder a la línea de comando y el proveedor no lo instala, siempre se puede descargar y descomprimirlo en nuestro proyecto directamente. Esta es la página de descarga:
http://download.pear.php.net/package/Math_BigInteger-1.0.2.tgz

Ahora ya podemos calcular el IBAN de una CCC:


/**
 * @name Ejemplo de conversor de CCC a IBAN
 * @copyright (c)2015 Intervia IT
 * @link http://intervia.com/doc/convertir-cuentas-de-formato-ccc-a-iban/
 * @license MIT http://opensource.org/licenses/MIT
 */

/*
 * Este conversor necesita el paquete de Pear Math_BigInteger
 * http://pear.php.net/package/Math_BigInteger/
 * 
 * Se puede instalar desde la línea de comando como:
 * pear install Math_BigInteger-1.0.2
 * 
 * Si no se puede instalar, basta con descargarlo y descomprimirlo
 * en el mismo directorio de este archivo:
 * http://download.pear.php.net/package/Math_BigInteger-1.0.2.tgz
 */

//Incluye el paquete para cálculo con grandes números
include_once "Math/BigInteger.php";

$es_iso = '142800'; //Código ISO ES + 00
$ccc = '12341234161234567890'; //Cuenta de ejemplo
$bban_es = $ccc.$es_iso; //CCC + ES + 00

$a = new Math_BigInteger($bban_es); //Dividendo
$b = new Math_BigInteger('97'); //Divisor (97)
list($cociente, $resto) = $a->divide($b); //Carga el resultado en dos variables
//$cociente->toString(); //El cociente no es necesario

//Obtiene el resto y lo resta de 98 para obtener el dígito de control, 
//sacando siempre 2 dígitos
$ibandc = str_pad(98 - $resto->toString(),2,0,STR_PAD_LEFT);
$iban = 'ES'.$ibandc.$ccc; //El código IBAN es el código ISO de país más el DC

//Para mostrar el IBAN en bloques de 4 dígitos
$iban2 = substr($iban,0,4).' '.
 substr($iban,4,4).' '.
 substr($iban,8,4).' '.
 substr($iban,12,4).' '.
 substr($iban,16,4).' '.
 substr($iban,20,4).' '.
 substr($iban,24,4);

echo 'IBAN formato electrónico: '.$iban.'<br>';
echo 'IBAN formato impreso: '.$iban2;

Esto devuelve:

IBAN formato electrónico: ES7712341234161234567890
IBAN formato impreso: ES77 1234 1234 1612 3456 7890

 

Nótese que se le suministran los números a la clase Math_BigInteger en formato “string”. Como puede verse al asignar las variables, los números van entre comillas, por ejemplo, ‘142800’, si se quitan las comillas y se le dan en formato numérico, no funciona.

 

Este ejemplo es válido para cuentas bancarias españolas y este proceso además, no verifica la validez de la cuenta BBAN (CCC), que tiene su propio dígito de control.

 

Para validar un DC de una cuenta española, se usan dos números, el primero resultado de concatenar el código del banco y de la sucursal y el segundo el número de cuenta, entre estos dos grupos está el dígito de control de dos dígitos, el primero valida el banco y sucursal y el segundo la cuenta.

 

Los dos números del dígito de control, se obtienen multiplicado cada dígito del número de banco+cuenta y del número de cuenta, por un número arbitrario, sumando el resultado de las multiplicaciones de todos los dígitos de cada uno de los dos números y restando de 11 el resto de dividir la suma de los números entre 11. Si el número resultante es de un dígito se usa directamente, si tiene dos dígitos, si es 10 vale 1, y si es 11 vale 0.

Empezando por las unidades (el dígito de la derecha), deben multiplicarse cada uno por los siguientes números.

 

Para los 8 dígitos de concatenar el código del banco y de la sucursal:

6, 3, 7, 9, 10, 5, 8, 4

 

Para los 10 dígitos del número de cuenta:

6, 3, 7, 9, 10, 5, 8, 4, 2, 1

 

Por ejemplo, para la cuenta 1234 1234 16 1234567890:

Número 1 = 12341234
Número 2 = 1234567890

Número 1 = 4×6 + 3×3 + 2×7 + 1×9 + 4×10 + 3×5 + 2×8 + 1×4 = 131
Resto de 131 / 11 = 10
11 – 10 = 1, por lo que el primer dígito es 1

Número 2 = 0x6 + 9×3 + 8×7 + 7×9 + 6×10 + 5×5 + 4×8 + 3×4 + 2×2 + 1×1 = 280
Resto de 280 / 11 = 5
11- 5 = 6, por lo que el segundo dígito es 6

Así, el dígito de control debe ser 16.

 

 

Un ejemplo de validación de cuentas CCC en PHP:


/**
 * @name Ejemplo de validación de cuentas bancarias CCC
 * @copyright (c)2015 Intervia IT
 * @link http://intervia.com/doc/convertir-cuentas-de-formato-ccc-a-iban/
 * @license MIT http://opensource.org/licenses/MIT
 */

/*
 * ******************
 * Validación del CCC
 * ******************
 */

//Inicializa la variable de error
$error = 0;

//Suma los dígitos del banco y la sucursal multiplicados por sus pesos
$dc1s = 0;
$dc1s += $ccc[0] * 4;
$dc1s += $ccc[1] * 8;
$dc1s += $ccc[2] * 5;
$dc1s += $ccc[3] * 10;
$dc1s += $ccc[4] * 9;
$dc1s += $ccc[5] * 7;
$dc1s += $ccc[6] * 3;
$dc1s += $ccc[7] * 6;

//El primer DC es 11 menos el resto de la anteror suma entre 11
$dc1 = 11 - $dc1s % 11;

//Si vale 11 se le asigna 0, si vale 10 se le asigna 1
if ($dc1 == 11) $dc1 = 0;
if ($dc1 == 10) $dc1 = 1;

//Si no coincide con el DC 1 marca error
if ($dc1 != $ccc[8]) $error = 1;

//Suma los dígitos de la cuenta multiplicados por sus pesos
$dc2s = 0;
$dc2s += $ccc[10] * 1;
$dc2s += $ccc[11] * 2;
$dc2s += $ccc[12] * 4;
$dc2s += $ccc[13] * 8;
$dc2s += $ccc[14] * 5;
$dc2s += $ccc[15] * 10;
$dc2s += $ccc[16] * 9;
$dc2s += $ccc[17] * 7;
$dc2s += $ccc[18] * 3;
$dc2s += $ccc[19] * 6;

//El segundo DC es 11 menos el resto de la anteror suma entre 11
$dc2 = 11 - $dc2s % 11;

//Si vale 11 se le asigna 0, si vale 10 se le asigna 1
if ($dc2 == 11) $dc2 = 0;
if ($dc2 == 10) $dc2 = 1;

//Si no coincide con el DC 2 marca error
if ($dc2 != $ccc[9]) $error = 2;

 echo $dc1s.' - '.$dc2s.'<br>';

if ($error){
 //Error si alguna de las casillas está vacía
 echo '<b>ERROR:</b> Número de cuenta incorrecto.';
 
 exit;
}

 

 

Si juntamos la validación del DC de la CCC con la conversión a IBAN, podemos verificar y convertir las cuentas, aquí puede verse el código completo:


/**
 * @name Ejemplo de conversor de CCC a IBAN con validación de cuentas
 * @copyright (c)2015 Intervia IT
 * @link http://intervia.com/doc/convertir-cuentas-de-formato-ccc-a-iban/
 * @license MIT http://opensource.org/licenses/MIT
 */

/*
 * Este conversor necesita el paquete de Pear Math_BigInteger
 * http://pear.php.net/package/Math_BigInteger/
 * 
 * Se puede instalar desde la línea de comando como:
 * pear install Math_BigInteger-1.0.2
 * 
 * Si no se puede instalar, basta con descargarlo y descomprimirlo
 * en el mismo directorio de este archivo:
 * http://download.pear.php.net/package/Math_BigInteger-1.0.2.tgz
 */

//Incluye el paquete para cálculo con grandes números
include_once "Math/BigInteger.php";

//Inicializa el array para mensajes de error
$msg = array();

//Captura las variables del POST y filtra todo lo que no sean números
$p = preg_replace("/[^0-9]/i","",$_REQUEST['p']); //switch para el envío
$b = preg_replace("/[^0-9]/i","",$_REQUEST['b']); //códico de entidad
$s = preg_replace("/[^0-9]/i","",$_REQUEST['s']); //códico de sucursal
$d = preg_replace("/[^0-9]/i","",$_REQUEST['d']); //dígito de control
$c = preg_replace("/[^0-9]/i","",$_REQUEST['c']); //número de cuenta
$ccc = preg_replace("/[^0-9]/i","",$_REQUEST['ccc']); //CCC entero


//Si no existe el número CCC completo lo concatena de b, s, d y c
if (!$ccc){
 $ccc = $b.$s.$d.$c;
}




/*
 * ******************
 * Validación del CCC
 * ******************
 */

//Inicializa la variable de error
$error = 0;

//Suma los dígitos del banco y la sucursal multiplicados por sus pesos
$dc1s = 0;
$dc1s += $ccc[0] * 4;
$dc1s += $ccc[1] * 8;
$dc1s += $ccc[2] * 5;
$dc1s += $ccc[3] * 10;
$dc1s += $ccc[4] * 9;
$dc1s += $ccc[5] * 7;
$dc1s += $ccc[6] * 3;
$dc1s += $ccc[7] * 6;

//El primer DC es 11 menos el resto de la anteror suma entre 11
$dc1 = 11 - $dc1s % 11;

//Si vale 11 se le asigna 0, si vale 10 se le asigna 1
if ($dc1 == 11) $dc1 = 0;
if ($dc1 == 10) $dc1 = 1;

//Si no coincide con el DC 1 marca error
if ($dc1 != $ccc[8]) $error = 1;

//Suma los dígitos de la cuenta multiplicados por sus pesos
$dc2s = 0;
$dc2s += $ccc[10] * 1;
$dc2s += $ccc[11] * 2;
$dc2s += $ccc[12] * 4;
$dc2s += $ccc[13] * 8;
$dc2s += $ccc[14] * 5;
$dc2s += $ccc[15] * 10;
$dc2s += $ccc[16] * 9;
$dc2s += $ccc[17] * 7;
$dc2s += $ccc[18] * 3;
$dc2s += $ccc[19] * 6;

//El segundo DC es 11 menos el resto de la anteror suma entre 11
$dc2 = 11 - $dc2s % 11;

//Si vale 11 se le asigna 0, si vale 10 se le asigna 1
if ($dc2 == 11) $dc2 = 0;
if ($dc2 == 10) $dc2 = 1;

//Si no coincide con el DC 2 marca error
if ($dc2 != $ccc[9]) $error = 2;

if ($error){
 //Error si alguna de las casillas está vacía
 $msg[] = '
 <b>ERROR:</b> Número de cuenta incorrecto.<br>
 No es posible calcular el IBAN con un CCC incorrecto.';
}





/*
 * ***************************************
 * Cálculo del IBAN si el CCC era correcto
 * ***************************************
 */

//Si se envió el formulario
if ($p ==1 && !$error){
 
 //Si falta alguno de los dígitos da error
 if(strlen($ccc) == 20){
 
 //Código de España para cálculo del DC del IBAN
 $es_iso = '142800';
 
 //Concatena el CCC con el código de país de España
 $bban_es = $ccc.$es_iso;

 //Hace la división del número de cuenta 
 //concatenado con el código de país entre 97
 $a = new Math_BigInteger($bban_es);
 $b = new Math_BigInteger('97');
 list($cociente, $resto) = $a->divide($b);

 //Obtiene el resto y lo resta de 98 para obtener el dígito de control
 $ibandc = str_pad(98 - $resto->toString(),2,0,STR_PAD_LEFT);
 
 //Crea el código IBAN
 $iban = 'ES'.$ibandc.$ccc;

 //Separa el iban en grupos de 4 para el formato impreso
 $ibani = substr($iban,0,4).' '.
 substr($iban,4,4).' '.
 substr($iban,8,4).' '.
 substr($iban,12,4).' '.
 substr($iban,16,4).' '.
 substr($iban,20,4).' '.
 substr($iban,24,4);

 //Muestra el resultado de la conversión
 $msg[] = '<h3>Código IBAN</h3>
 <b>Electrónico:</b> '.$iban.'<br>
 <b>Impreso:</b> '.$ibani;
 
 
 }else{
 //Error si alguna de las casillas está vacía
 $msg[] = '<b>ERROR:</b> Hay que introducir datos en todas las casillas 
 y sólo se admiten números. Si se pone el número entero, debe 
 tener 20 dígitos.';
 }
}




/*
 * *************************
 * Muestra mensajes de error
 * *************************
 */

if ($msg){
 echo '<div style="background-color:#eee;padding:3px;">';
 foreach ($msg as $m){
 echo $m;
 }
 echo '</div>';
}





/*
 * ************************************
 * Formulario para introducir la cuenta
 * ************************************
 */

?> 
<h3>Conversor de CCC a IBAN en PHP</h3>

<form method="GET" action="">
<input type="hidden" name="p" value="1">
<input type="text" placeholder="CCC entero" size="26" name="ccc" maxlength="23">
<input type="submit" value="Validar">
</form>

Código de ejemplo: 12341234161234567890<br><br><br>

<form method="GET" action="">
<input type="hidden" name="p" value="1">
<input type="text" placeholder="Banco" size="8" name="b" maxlength="4">/
<input type="text" placeholder="Oficina" size="8" name="s" maxlength="4">/
<input type="text" placeholder="DC" size="5" name="d" maxlength="2">/
<input type="text" placeholder="Cuenta" size="14" name="c" maxlength="10">/
<input type="submit" value="Validar">
</form>

Código de ejemplo: 1234 / 1234 / 16 / 1234567890<br><br><br>

 

 

Hay una demostración del funcionamiento de este código:
http://intervia.com/ccc2iban

 

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada.