ART PROJECT GROUP:
C/ Álvaro Mutis, 1. 4º G. C.P: 29651. Mijas. Málaga. España.
Teléfono: +34 665 058 218.

Validando el campo NIF o CIF en WooCommerce

  • WooCommerce - Blog

Validando el campo NIF o CIF en WooCommerce

El otro día en el WordPress Day Marbella 2015 nuestro compañero de ponencia Andy García nos propuso el reto de validar el campo NIF/CIF, que os enseñamos a añadir en la entrada ¿Cómo añadir un campo NIF o CIF a WooCommerce 2.1?, para hacer el código perfecto a su criterio.

Pues bien, dicho y hecho. Nos hemos puesto manos a la obra para satisfacer las necesidades de Andy y os proponemos una solución para validar cualquier tipo de número NIF, CIF o NIE.

Solución

Realmente la solución al problema planteado es simple gracias al gran código PHP publicado en Comprobar CIF, NIF o NIE con PHP por da-software. Lo único que hemos hecho es adaptar su fantástica función PHP a las necesidades de WooCommerce.

Aquí tienes el código PHP que tienes que añadir al archivo functions.php de tu tema hijo o padre para que se valide correctamente el campo NIF/CIF:

//Validando el campo NIF/CIF
function validando_campo() {
	$falso = true;

    if ( isset( $_POST['billing_nif'] ) ) {
		$nif = strtoupper( $_POST['billing_nif'] );

		for ( $i = 0; $i < 9; $i ++ ) {
			$num[$i] = substr( $nif, $i, 1 );
		}

		if ( !preg_match( '/((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)/', $nif ) ) { //No tiene formato válido
			$falso = true;
		}

		if ( preg_match( '/(^[0-9]{8}[A-Z]{1}$)/', $nif ) ) {
			if ( $num[8] == substr( 'TRWAGMYFPDXBNJZSQVHLCKE', substr( $nif, 0, 8 ) % 23, 1 ) ) { //NIF válido
				$falso = false;
			}
		}

		$suma = $num[2] + $num[4] + $num[6];
		for ( $i = 1; $i < 8; $i += 2 ) {
			$suma += substr( ( 2 * $num[$i] ), 0, 1 ) + substr( ( 2 * $num[$i] ), 1, 1 );
		}
		$n = 10 - substr( $suma, strlen( $suma ) - 1, 1 );

		if ( preg_match( '/^[KLM]{1}/', $nif ) ) { //NIF especial válido
			if ( $num[8] == chr( 64 + $n ) ) {
				$falso = false;
			}
		}

		if ( preg_match( '/^[ABCDEFGHJNPQRSUVW]{1}/', $nif ) ) {
			if ( $num[8] == chr( 64 + $n ) || $num[8] == substr( $n, strlen( $n ) - 1, 1 ) ) { //CIF válido
				$falso = false;
			}
		}

		if ( preg_match( '/^[T]{1}/', $nif ) ) {
			if ( $num[8] == preg_match( '/^[T]{1}[A-Z0-9]{8}$/', $nif ) ) { //NIE válido (T)
				$falso = false;
			}
		}
		if ( preg_match( '/^[XYZ]{1}/', $nif ) ) { //NIE válido (XYZ)
			if ( $num[8] == substr( 'TRWAGMYFPDXBNJZSQVHLCKE', substr( str_replace( array( 'X','Y','Z' ), array( '0','1','2' ), $nif ), 0, 8 ) % 23, 1 ) ) {
				$falso = false;
			}
		}
	}

	if ( $falso ) {
		wc_add_notice( __( 'Por favor, introduzca un NIF/CIF válido.' ), 'error' );
	}
}
add_action( 'woocommerce_checkout_process', 'validando_campo' );

Y para que no te vuelvas loco copiando y pegando código, aquí tienes todo el código PHP completo válido desde la versión 2.1 hasta la 2.3 de WooCommerce, ambas inclusive:

//Arreglamos la dirección predeterminada
function campos_de_direccion( $campos ) {
    $campos['nif'] = array( 
        'label' => __( '<abbr title="Código de Identificación Fiscal" lang="es">CIF</abbr>/<abbr title="Número de Identificación Fiscal" lang="es">NIF</abbr>', 'woocommerce' ),
        'placeholder' => _x( 'Introduzca elCIF/NIF', 'placeholder', 'woocommerce' ),
        'required' => true,
        'class' =>array( 'form-row-last' ),
        'clear' => true,
	);

    $campos['company']['class'][0] = 'form-row-first';
    $campos['city']['class'][0] = 'form-row-first';
    $campos['state']['class'][0] = 'form-row-last update_totals_on_change';
    $campos['postcode']['class'][0] .= ' update_totals_on_change';

    //Reordenamos los campos
    $campos_nuevos['country'] = $campos['country'];
    $campos_nuevos['first_name'] = $campos['first_name'];
    $campos_nuevos['last_name'] = $campos['last_name'];
    $campos_nuevos['company'] = $campos['company'];
    $campos_nuevos['nif'] = $campos['nif'];
    $campos_nuevos['address_1'] = $campos['address_1'];
    $campos_nuevos['address_2'] = $campos['address_2'];
    $campos_nuevos['postcode'] = $campos['postcode'];
    $campos_nuevos['city'] = $campos['city'];
    $campos_nuevos['state'] = $campos['state'];
    if ( isset( $campos['email'] ) ) {
		$campos_nuevos['email'] = $campos['email'];
	}
    if ( isset( $campos['phone'] ) ) {
		$campos_nuevos['phone']['required'] = true;
		$campos_nuevos['phone'] = $campos['phone'];
    }
	
    return $campos_nuevos;
}
add_filter( 'woocommerce_default_address_fields' , 'campos_de_direccion' );

//Nueva función para hacer compatible el código con WooCommerce 2.1
function dame_campo_personalizado( $campo, $pedido ) {
    $valor = get_post_meta( $pedido, $campo, false );
	if ( isset( $valor[0] ) ){
		return $valor[0];
	}
	return NULL;
}

//Añadimos el NIF y el teléfono a la dirección de facturación y envío
function anade_campo_nif_direccion_facturacion( $campos, $pedido ) {
    $campos['nif'] = dame_campo_personalizado( '_billing_nif', $pedido->id );
    $campos['phone'] = dame_campo_personalizado( '_billing_phone', $pedido->id );
	
	return $campos;
}
add_filter( 'woocommerce_order_formatted_billing_address','anade_campo_nif_direccion_facturacion', 1, 2 );

function anade_campo_nif_direccion_envio( $campos, $pedido ) {
    $campos['nif'] = dame_campo_personalizado( '_shipping_nif', $pedido->id );
    $campos['phone'] = dame_campo_personalizado( '_shipping_phone', $pedido->id );
	
	return $campos;
}
add_filter( 'woocommerce_order_formatted_shipping_address','anade_campo_nif_direccion_envio', 1, 2 );

function formato_direccion_de_facturacion( $campos, $argumentos ) {
    $campos['{nif}'] = $argumentos['nif'];
    $campos['{nif_upper}'] =strtoupper( $argumentos['nif'] );
    $campos['{phone}'] = $argumentos['phone'];
    $campos['{phone_upper}'] =strtoupper( $argumentos['phone'] );
	
	return $campos;
}
add_filter( 'woocommerce_formatted_address_replacements','formato_direccion_de_facturacion', 1, 2 );

//Reordenamos los campos de la dirección predeterminada
function formato_direccion_localizacion( $campos ) {
    $campos['default'] = "{name}n{company}n{nif}n{address_1}n{address_2}n{city}n{state}n{postcode}n{country}n{phone}";
    $campos['ES'] = "{name}n{company}n{nif}n{address_1}n{address_2}n{postcode} {city}n{state}n{country}n{phone}";
	
	return $campos;
}
add_filter( 'woocommerce_localisation_address_formats','formato_direccion_localizacion' );

//Arreglamos el formulario de envío
function formulario_de_envio( $campos ) {
    $campos['shipping_email'] =array( 
        'label' => __( 'EmailAddress', 'woocommerce' ),
        'required' => false,
        'class' =>array( 'form-row-first' ),
        'validate' =>array(  'email'  ),
	);
    $campos['shipping_phone'] =array( 
        'label' => __( 'Phone', 'woocommerce' ),
        'required' => true,
        'class' =>array( 'form-row-last' ),
        'clear' => true,
	);
    $campos['shipping_postcode'] =array( 
        'label' => __(  'Postcode /Zip', 'woocommerce'  ),
        'placeholder' => __(  'Postcode /Zip', 'woocommerce'  ),
        'required' => true,
        'class' =>array(  'form-row-wide', 'address-field'  ),
        'clear' => true,
        'custom_attributes' =>array( 
            'autocomplete' => 'no'
         )
	);
	 
	return $campos;
}
add_filter( 'woocommerce_shipping_fields' , 'formulario_de_envio' );

//Arreglamos el formulario de cobro
function formulario_de_cobro( $campos ) {
	$campos['billing_postcode'] =array( 
        'label' => __(  'Postcode /Zip', 'woocommerce'  ),
        'placeholder' => __(  'Postcode /Zip', 'woocommerce'  ),
        'required' => true,
        'class' => array(  'form-row-wide', 'address-field'  ),
        'clear' => true,
        'custom_attributes' => array( 
            'autocomplete' => 'no'
         )
	);
	
	return $campos;
}
add_filter( 'woocommerce_billing_fields' , 'formulario_de_cobro' );

//Añade el campo CIF/NIF a usuarios
function anade_campos_administracion_usuarios( $campos ) {
    $campos['billing']['fields']['billing_nif'] = array( 
            'label' => __( 'CIF/NIF', 'woocommerce' ),
            'description' => ''
	);

    $campos['shipping']['fields']['shipping_nif'] = array( 
            'label' => __( 'CIF/NIF', 'woocommerce' ),
            'description' => ''
	);
    $campos['shipping']['fields']['shipping_email'] = array( 
            'label' => __( 'Email', 'woocommerce' ),
            'description' => ''
	);
	$campos['shipping']['fields']['shipping_phone'] = array( 
            'label' => __( 'Telephone', 'woocommerce' ),
            'description' => ''
	);

    //Reordenamos los campos
    $campos_nuevos['billing']['title'] = $campos['billing']['title'];
    $campos_nuevos['billing']['fields']['billing_first_name'] = $campos['billing']['fields']['billing_first_name'];
    $campos_nuevos['billing']['fields']['billing_last_name'] = $campos['billing']['fields']['billing_last_name'];
    $campos_nuevos['billing']['fields']['billing_company'] = $campos['billing']['fields']['billing_company'];
    $campos_nuevos['billing']['fields']['billing_nif'] = $campos['billing']['fields']['billing_nif'];
    $campos_nuevos['billing']['fields']['billing_address_1'] = $campos['billing']['fields']['billing_address_1'];
    $campos_nuevos['billing']['fields']['billing_address_2'] = $campos['billing']['fields']['billing_address_2'];
    $campos_nuevos['billing']['fields']['billing_postcode'] = $campos['billing']['fields']['billing_postcode'];
    $campos_nuevos['billing']['fields']['billing_city'] = $campos['billing']['fields']['billing_city'];
    $campos_nuevos['billing']['fields']['billing_state'] = $campos['billing']['fields']['billing_state'];
    $campos_nuevos['billing']['fields']['billing_country'] = $campos['billing']['fields']['billing_country'];
    $campos_nuevos['billing']['fields']['billing_phone'] = $campos['billing']['fields']['billing_phone'];
    $campos_nuevos['billing']['fields']['billing_email'] = $campos['billing']['fields']['billing_email'];

    $campos_nuevos['shipping']['title'] = $campos['shipping']['title'];
    $campos_nuevos['shipping']['fields']['shipping_first_name'] = $campos['shipping']['fields']['shipping_first_name'];
    $campos_nuevos['shipping']['fields']['shipping_last_name'] = $campos['shipping']['fields']['shipping_last_name'];
    $campos_nuevos['shipping']['fields']['shipping_company'] = $campos['shipping']['fields']['shipping_company'];
    $campos_nuevos['shipping']['fields']['shipping_nif'] = $campos['shipping']['fields']['shipping_nif'];
    $campos_nuevos['shipping']['fields']['shipping_address_1'] = $campos['shipping']['fields']['shipping_address_1'];
    $campos_nuevos['shipping']['fields']['shipping_address_2'] = $campos['shipping']['fields']['shipping_address_2'];
    $campos_nuevos['shipping']['fields']['shipping_postcode'] = $campos['shipping']['fields']['shipping_postcode'];
    $campos_nuevos['shipping']['fields']['shipping_city'] = $campos['shipping']['fields']['shipping_city'];
    $campos_nuevos['shipping']['fields']['shipping_state'] = $campos['shipping']['fields']['shipping_state'];
    $campos_nuevos['shipping']['fields']['shipping_country'] = $campos['shipping']['fields']['shipping_country'];
    $campos_nuevos['shipping']['fields']['shipping_phone'] = $campos['shipping']['fields']['shipping_phone'];
    $campos_nuevos['shipping']['fields']['shipping_email'] = $campos['shipping']['fields']['shipping_email'];

    $campos_nuevos = apply_filters( 'wcbcf_customer_meta_fields', $campos_nuevos );
	
	return $campos_nuevos;
}
add_filter( 'woocommerce_customer_meta_fields', 'anade_campos_administracion_usuarios' );

//Añadimos el NIF a la dirección de facturación y envío
function anade_campo_nif_usuario_direccion_facturacion( $campos, $usuario ) {
    $campos['nif'] = get_user_meta( $usuario, 'billing_nif', true );
    $campos['phone'] = get_user_meta( $usuario, 'billing_phone', true );return $campos;
}
add_filter( 'woocommerce_user_column_billing_address','anade_campo_nif_usuario_direccion_facturacion', 1, 2 );

function anade_campo_nif_usuario_direccion_envio( $campos, $usuario ) {
    $campos['nif'] = get_user_meta( $usuario, 'shipping_nif', true );
    $campos['phone'] = get_user_meta( $usuario, 'shipping_phone', true );return $campos;
}
add_filter( 'woocommerce_user_column_shipping_address','anade_campo_nif_usuario_direccion_envio', 1, 2 );

//Añade el campo NIF a Editar mi dirección
function anade_campo_nif_editar_direccion( $campos, $usuario, $nombre ) {
    $campos['nif'] = get_user_meta( $usuario, $nombre . '_nif', true );
    $campos['phone'] = get_user_meta( $usuario, $nombre . '_phone', true );

    //Ordena los campos
    $campos_nuevos['first_name'] = $campos['first_name'];
    $campos_nuevos['last_name'] = $campos['last_name'];
    $campos_nuevos['company'] = $campos['company'];
    $campos_nuevos['nif'] = $campos['nif'];
    $campos_nuevos['address_1'] = $campos['address_1'];
    $campos_nuevos['address_2'] = $campos['address_2'];
    $campos_nuevos['postcode'] = $campos['postcode'];
    $campos_nuevos['city'] = $campos['city'];
    $campos_nuevos['state'] = $campos['state'];
    $campos_nuevos['country'] = $campos['country'];
    $campos_nuevos['phone'] = $campos['phone'];
	
	return $campos_nuevos;
}
add_filter( 'woocommerce_my_account_my_address_formatted_address', 'anade_campo_nif_editar_direccion', 10, 3 );

//Añade el campo NIF a Detalles del pedido
function anade_campo_nif_editar_direccion_pedido( $campos ) {
    $campos['nif'] = array( 
        'label' => __( 'CIF/NIF', 'woocommerce' ),
        'show'  => false
     );
    $campos['phone'] = array( 
        'label' => __( 'Telephone', 'woocommerce' ),
        'show'  => false
     );

    //Ordena los campos
    $campos_nuevos['first_name'] = $campos['first_name'];
    $campos_nuevos['last_name'] = $campos['last_name'];
    $campos_nuevos['company'] = $campos['company'];
    $campos_nuevos['nif'] = $campos['nif'];
    $campos_nuevos['address_1'] = $campos['address_1'];
    $campos_nuevos['address_2'] = $campos['address_2'];
    $campos_nuevos['postcode'] = $campos['postcode'];
    $campos_nuevos['city'] = $campos['city'];
    $campos_nuevos['state'] = $campos['state'];
    $campos_nuevos['country'] = $campos['country'];
    $campos_nuevos['phone'] = $campos['phone'];

    return $campos_nuevos;
}
add_filter( 'woocommerce_admin_billing_fields', 'anade_campo_nif_editar_direccion_pedido' );
add_filter( 'woocommerce_admin_shipping_fields', 'anade_campo_nif_editar_direccion_pedido' );

function carga_hoja_de_estilo_editar_direccion_pedido() {
    echo '</pre>
<style type="text/css"><!-- #order_data .order_data_column ._billing_company_field, #order_data .order_data_column ._shipping_company_field { float: left; margin: 9px 0 0; padding: 0; width: 48%; } #order_data .order_data_column ._billing_nif_field, #order_data .order_data_column ._shipping_nif_field { float: right; margin: 9px 0 0; padding: 0; width: 48%; } --></style>
<pre>';
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'carga_hoja_de_estilo_editar_direccion_pedido' );

//Validando el campo NIF/CIF
function validando_campo() {
	$falso = true;

    if ( isset( $_POST['billing_nif'] ) ) {
		$nif = strtoupper( $_POST['billing_nif'] );

		for ( $i = 0; $i < 9; $i ++ ) {
			$num[$i] = substr( $nif, $i, 1 );
		}

		if ( !preg_match( '/((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)/', $nif ) ) { //No tiene formato válido
			$falso = true;
		}

		if ( preg_match( '/(^[0-9]{8}[A-Z]{1}$)/', $nif ) ) {
			if ( $num[8] == substr( 'TRWAGMYFPDXBNJZSQVHLCKE', substr( $nif, 0, 8 ) % 23, 1 ) ) { //NIF válido
				$falso = false;
			}
		}

		$suma = $num[2] + $num[4] + $num[6];
		for ( $i = 1; $i < 8; $i += 2 ) {
			$suma += substr( ( 2 * $num[$i] ), 0, 1 ) + substr( ( 2 * $num[$i] ), 1, 1 );
		}
		$n = 10 - substr( $suma, strlen( $suma ) - 1, 1 );

		if ( preg_match( '/^[KLM]{1}/', $nif ) ) { //NIF especial válido
			if ( $num[8] == chr( 64 + $n ) ) {
				$falso = false;
			}
		}

		if ( preg_match( '/^[ABCDEFGHJNPQRSUVW]{1}/', $nif ) ) {
			if ( $num[8] == chr( 64 + $n ) || $num[8] == substr( $n, strlen( $n ) - 1, 1 ) ) { //CIF válido
				$falso = false;
			}
		}

		if ( preg_match( '/^[T]{1}/', $nif ) ) {
			if ( $num[8] == preg_match( '/^[T]{1}[A-Z0-9]{8}$/', $nif ) ) { //NIE válido (T)
				$falso = false;
			}
		}
		if ( preg_match( '/^[XYZ]{1}/', $nif ) ) { //NIE válido (XYZ)
			if ( $num[8] == substr( 'TRWAGMYFPDXBNJZSQVHLCKE', substr( str_replace( array( 'X','Y','Z' ), array( '0','1','2' ), $nif ), 0, 8 ) % 23, 1 ) ) {
				$falso = false;
			}
		}
	}

	if ( $falso ) {
		wc_add_notice( __( 'Por favor, introduzca un NIF/CIF válido.' ), 'error' );
	}
}
add_action( 'woocommerce_checkout_process', 'validando_campo' );

Conclusión

Esperamos que el bueno de Andy de por satisfecha la necesidad planteada a APG y que a vosotros os resulte útil esta función en vuestras tiendas virtuales.

Tanto si lo has usado como si has conseguido mejorarlo, quedamos a la espera de vuestros comentarios y aportaciones.

Actualización: la actualización para WooCommerce 2.4 está disponible en ¿Cómo añadir un campo NIF o CIF con validación a WooCommerce 2.4?.

13 Comentarios

  1. Manuel martes, 9 de junio de 2015 en 22:20- Responder

    Felicidades. Efectivamente ahora si es un codigo perfecto (Bueno aún no lo he probado, pero se entiende que está nueva funcionalidad es a lo que me refiero) Yo también lo echaba de menos.

  2. Francisco Ramirez lunes, 27 de julio de 2015 en 10:26- Responder

    Hola buenos días. He copiado el código y no me funciona. No verifica nada del CIF. Le puesto meter cualquier cosa y lo acepta. Otra opción que no se si está en el código, es que el campo del NIF CIF no se almacena en ningún sitio. Me gustaría que cuando se envían los resúmenes de los pedidos o se emiten facturas con el plugin de PDF INVOICE se adjuntara el NIF/CIF ya que no tiene ningún sentido introducir este dato y que no figure en ningún sitio.
    Gracias por vuestra web y por vuestro tiempo. Saludos.

    • Art Project Group lunes, 27 de julio de 2015 en 10:39- Responder

      Francisco, o lo has copiado mal, o la versión de WooCommerce que usas no es la correcta, o hay algo mal en tu instalación.

      El código funciona perfectamente en todos los aspectos que mencionas, probado en cientos, muchos cientos, de instalaciones.

      Un saludo.

  3. Francisco Ramirez lunes, 27 de julio de 2015 en 11:35- Responder

    Tengo la versión 2.3.13 que es la última versión. He revisado el texto y estaba todo copiado bien. He cogido de donde pone que está el código completo. Que podría hacer?

    • Art Project Group miércoles, 29 de julio de 2015 en 12:30- Responder

      En principio debería funcionarte sin ningún tipo de problema. Puede ser que te esté provocando algún tipo de error algún plugin que tengas instalado o que haya algún tipo de incompatibilidad con algún componente de tu sitio web.

      Habría que verlo con detenimiento para ver qué ocurre en tu instalación.

      Lo que si te aseguramos es que funcionar, funciona 😉

      Un saludo.

  4. Francisco Ramirez miércoles, 29 de julio de 2015 en 12:35- Responder

    Hola. Hoy he conseguido hacer que me funcione. Copié el código de otro de vuestros posts y añadí el código de validación de DNI después. Ha quedado genial. Muchas gracias por vuestra página. La consulto muy a menudo y me soluciona grandes problemas. Sois unos cracks

  5. power lunes, 17 de agosto de 2015 en 20:03- Responder

    Hola buenas como puedo reorganizar de nuevo los campos con esta ultima versión de woocommerce Versión 2.4.4 habido cambio en código que los campos ahora se ven desorganizados, como puedo volver a organizar como antes de esta versión se veían correctamente pero en esta actualización no

Deje un comentario

Comparte esto con un amigo