Contenido
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?.
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.
Gracias.
Nosotros si lo hemos probado y funciona perfectamente.
Un saludo.
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.
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.
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?
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.
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
¿De cuál?
https://artprojectgroup.es/como-hacer-obligatorio-el-telefono-y-mostrarlo-en-la-factura-junto-al-cifnif-en-woocommerce-2-1
Usé este código y le quité la parte del teléfono. Por lo demás va genial 😀
En principio de ahí copiamos el código para poner todo el conjunto en un sólo paquete.
De todas formas volveremos a revisar el código, no vaya a ser que se haya roto u olvidado algo.
Un saludo.
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
Lo revisamos y actualizamos lo antes posible.
Un saludo.
Ya lo tienes solucionado en ¿Cómo añadir un campo NIF o CIF con validación a WooCommerce 2.4?.
Gracias por el aviso.
Un saludo.