Snippet php para facturación electrónica DIAN con WooCommerce de WordPress.
Aquí tienes una guía completa para implementar facturación electrónica DIAN Colombia en WooCommerce usando snippets PHP a través de un plugin como Code Snippets:
Requisitos Previos
- Certificado DIAN (Archivos .p12 o .pfx con contraseña)
- Software de Facturación homologado por DIAN (Puedes implementar el tuyo)
- Plugin Code Snippets instalado
- Conocimiento de la Resolución 000042 de 2022 (Nuevo formato factura electrónica)
Paso 1: Añadir Campos Obligatorios en Checkout
// Añadir campo NIT/Cédula en checkout
add_action('woocommerce_after_checkout_billing_form', 'custom_checkout_field_nit');
function custom_checkout_field_nit($checkout) {
woocommerce_form_field('billing_nit', array(
'type' => 'text',
'class' => array('form-row-wide'),
'label' => __('NIT/Cédula'),
'required' => true,
), $checkout->get_value('billing_nit'));
}
// Guardar campo NIT
add_action('woocommerce_checkout_update_order_meta', 'save_custom_checkout_nit');
function save_custom_checkout_nit($order_id) {
if (!empty($_POST['billing_nit'])) {
update_post_meta($order_id, '_billing_nit', sanitize_text_field($_POST['billing_nit']));
}
}
Paso 2: Generar XML DIAN (Facturación Electrónica)
add_action('woocommerce_order_status_completed', 'generar_factura_electronica_dian');
function generar_factura_electronica_dian($order_id) {
$order = wc_get_order($order_id);
// Datos base DIAN
$data = array(
'cabecera' => array(
'cude' => generar_cude($order_id), // Función para generar CUDE
'fechaEmision' => date('c'),
'tipoOperacion' => '10',
'codigoTipoDocumento' => '01' // 01 = Factura electrónica
),
'vendedor' => array(
'nit' => '900123456-7', // Tu NIT empresa
'dv' => '1',
'razonSocial' => get_bloginfo('name'),
'direccion' => get_option('woocommerce_store_address'),
'telefono' => get_option('woocommerce_store_phone')
),
'comprador' => array(
'nit' => get_post_meta($order_id, '_billing_nit', true),
'dv' => calcular_dv(get_post_meta($order_id, '_billing_nit', true)),
'razonSocial' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
'direccion' => $order->get_billing_address_1(),
'telefono' => $order->get_billing_phone()
),
'items' => array()
);
// Agregar productos
foreach ($order->get_items() as $item) {
$data['items'][] = array(
'codigo' => $item->get_product_id(),
'descripcion' => $item->get_name(),
'cantidad' => $item->get_quantity(),
'precioUnitario' => $item->get_subtotal(),
'iva' => calcular_iva($item->get_subtotal())
);
}
// Generar XML
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
$root = $xml->createElement('FacturaElectronica');
$root->setAttribute('xmlns', 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2');
$root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
// Estructura DIAN
$cabecera = $xml->createElement('cbc:CustomizationID', 'urn:cen:tech:xsd:ubl-2.1:FacturaElectronica:1.1');
$root->appendChild($cabecera);
// ... (Agregar todos los elementos según Resolución 000042 de 2022)
$xml->appendChild($root);
$xml_content = $xml->saveXML();
// Firmar XML
$xml_firmado = firmar_xml_dian($xml_content, $order_id);
// Guardar y adjuntar
$upload_dir = wp_upload_dir();
file_put_contents($upload_dir['path'] . "/factura-$order_id.xml", $xml_firmado);
update_post_meta($order_id, '_factura_dian', $upload_dir['url'] . "/factura-$order_id.xml");
}
Paso 3: Función para Firma Digital (DIAN)
function firmar_xml_dian($xml_content, $order_id) {
$certificado = 'ruta/certificado.p12';
$clave_certificado = 'tu_clave';
// Cargar certificado
openssl_pkcs12_read(file_get_contents($certificado), $cert_info, $clave_certificado);
// Crear firma
$signature = new DOMDocument();
$signature->loadXML('<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"></ds:Signature>');
// ... (Implementar firma XAdES según especificaciones DIAN)
// Insertar firma en XML
$xml = new DOMDocument();
$xml->loadXML($xml_content);
$xml->documentElement->appendChild($xml->importNode($signature->documentElement, true));
return $xml->saveXML();
}
Paso 4: Generar CUDE y QR
function generar_cude($order_id) {
$order = wc_get_order($order_id);
$datos = array(
'nit_emisor' => '900123456-7',
'nit_comprador' => get_post_meta($order_id, '_billing_nit', true),
'fecha' => date('Y-m-d'),
'total' => $order->get_total(),
'uuid' => wp_generate_uuid4()
);
$cadena = implode('|', $datos);
return hash('sha384', $cadena);
}
// Shortcode para QR
add_shortcode('qr_factura', 'generar_qr_factura');
function generar_qr_factura() {
$order_id = wc_get_order_id_by_order_key($_GET['order']);
$cude = get_post_meta($order_id, '_cude', true);
return '<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=' . $cude . '">';
}
Paso 5: Validación DIAN (XSD)
function validar_xml_dian($xml_content) {
$xsd_url = 'https://facturaelectronica.dian.gov.co/politicadevalidacion/ubl-2.1/maindoc/DIAN_UBL2_Invoice.xsd';
libxml_use_internal_errors(true);
$xml = new DOMDocument();
$xml->loadXML($xml_content);
if (!$xml->schemaValidate($xsd_url)) {
$errors = libxml_get_errors();
// Registrar errores en log
error_log('Errores validación DIAN: ' . print_r($errors, true));
return false;
}
return true;
}
Recomendaciones Esenciales
- Numeración DIAN: Implementa secuencia numérica única:
add_action('init', 'inicializar_consecutivo');
function inicializar_consecutivo() {
if (!get_option('consecutivo_dian')) {
update_option('consecutivo_dian', 900000000);
}
}
- Adjuntar a Emails:
add_filter('woocommerce_email_attachments', 'adjuntar_factura_dian_email', 10, 3);
function adjuntar_factura_dian_email($attachments, $email_id, $order) {
$file_url = get_post_meta($order->get_id(), '_factura_dian', true);
if ($file_url && $email_id === 'customer_completed_order') {
$attachments[] = str_replace(site_url('/'), ABSPATH, $file_url);
}
return $attachments;
}
- Registro en Logs DIAN:
function registrar_evento_dian($order_id, $evento) {
$log = "Orden $order_id: $evento - " . date('Y-m-d H:i:s') . "\n";
file_put_contents(WP_CONTENT_DIR . '/dian.log', $log, FILE_APPEND);
}
Consideraciones Clave
- Ambiente de Pruebas: Usa el ambiente de habilitación de DIAN primero
- Certificado Digital: Debes renovarlo anualmente
- Tiempo Límite: Genera la factura máximo 48 horas después de la venta
- Notificaciones DIAN: Implementa webhook para recibir respuestas de la DIAN
Este es un esquema básico. La implementación real requiere:
- Validación estricta de todos los campos DIAN
- Manejo de contingencia (Formatos PDF con QR)
- Integración con el Web Service de la DIAN (SOAP)
- Consulta de listados técnicos (Responsables de IVA, etc.)
Guía Paso a Paso para Implementar Facturación Electrónica DIAN Colombia en WooCommerce (2,000 palabras)
(Basado en Resolución 000042 de 2022 y Documentación Oficial DIAN)
1. Entender los Requisitos DIAN (Fuera de WordPress)
a) Documentación Obligatoria:
- Resolución 000042 de 2022: Norma técnica para facturación electrónica (Descargar aquí).
- Listados Técnicos DIAN: Campos obligatorios XML y validaciones (Consulta aquí).
b) Requisitos Técnicos Externos:
- Certificado Digital (.p12): Debes obtenerlo en la DIAN (proceso presencial o virtual).
- Software Homologado: Si usas tu propio desarrollo, debes registrarlo en la DIAN (Guía aquí).
- Servidor con OpenSSL: Para firmar XMLs (compatible con PHP 7.4+).
c) Procesos Fuera de WordPress:
- Registro en Ambiente de Pruebas DIAN (Enlace).
- Configuración de Webhooks para recibir respuestas de la DIAN (necesitas un servidor externo).
- Renovación anual del certificado digital.
2. Estructura de Snippets PHP (Dentro de WordPress)
Total de Snippets Necesarios: 8 (cada uno con funciones específicas).
Snippet 1: Campos Obligatorios en Checkout
Objetivo: Capturar NIT/CI del cliente y tipo de responsabilidad fiscal.
“`php
// Añadir campos al checkout
add_action(‘woocommerce_after_checkout_billing_form’, ‘campos_fiscales_dian’);
function campos_fiscales_dian() {
woocommerce_form_field(‘billing_nit’, [
‘type’ => ‘text’,
‘label’ => __(‘NIT/Cédula’),
‘required’ => true,
‘class’ => [‘form-row-wide’]
]);
woocommerce_form_field('billing_tipo_responsable', [
'type' => 'select',
'label' => __('Tipo de Responsable'),
'options' => [
'O-13' => 'Responsable del IVA',
'R-99-PN' => 'No Responsable'
],
'required' => true
]);
}
// Guardar datos
add_action(‘woocommerce_checkout_update_order_meta’, ‘guardar_campos_dian’);
function guardar_campos_dian($order_id) {
if (!empty($_POST[‘billing_nit’])) {
update_post_meta($order_id, ‘_billing_nit’, sanitize_text_field($_POST[‘billing_nit’]));
}
if (!empty($_POST[‘billing_tipo_responsable’])) {
update_post_meta($order_id, ‘_billing_tipo_responsable’, sanitize_text_field($_POST[‘billing_tipo_responsable’]));
}
}
---
#### **Snippet 2: Generación del XML DIAN (UBL 2.1)**
**Objetivo:** Crear estructura XML según listados técnicos.
php
add_action(‘woocommerce_order_status_completed’, ‘generar_xml_dian’);
function generar_xml_dian($order_id) {
$order = wc_get_order($order_id);
// Datos base
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
// Raíz según UBL 2.1
$Invoice = $xml->createElement('Invoice');
$Invoice->setAttribute('xmlns', 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2');
$Invoice->setAttribute('xmlns:cac', 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2');
$Invoice->setAttribute('xmlns:cbc', 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2');
// ID único DIAN (Ej: FE-900000001-1)
$ID = $xml->createElement('cbc:ID', 'FE-' . get_option('consecutivo_dian'));
$Invoice->appendChild($ID);
// Fecha emisión
$IssueDate = $xml->createElement('cbc:IssueDate', date('Y-m-d'));
$Invoice->appendChild($IssueDate);
// ... (Agregar todos los campos del Anexo 1.7 de la Resolución 000042)
// Guardar XML
$xml->appendChild($Invoice);
$xml->save(WP_CONTENT_DIR . "/facturas/factura-$order_id.xml");
update_post_meta($order_id, '_factura_xml', WP_CONTENT_DIR . "/facturas/factura-$order_id.xml");
// Actualizar consecutivo
update_option('consecutivo_dian', get_option('consecutivo_dian') + 1);
}
---
#### **Snippet 3: Firma Digital con Certificado .p12**
**Objetivo:** Firmar XML según estándar XAdES.
php
function firmar_xml_dian($order_id) {
$cert_path = ‘/ruta/certificado.p12’;
$cert_pass = ‘clave_del_certificado’;
// Cargar certificado
openssl_pkcs12_read(file_get_contents($cert_path), $cert_info, $cert_pass);
// Firmar con OpenSSL
$xml = file_get_contents(get_post_meta($order_id, '_factura_xml', true));
$private_key = openssl_pkey_get_private($cert_info['pkey']);
openssl_sign($xml, $signature, $private_key, OPENSSL_ALGO_SHA256);
// Insertar firma en XML
$xml_firmado = new DOMDocument();
$xml_firmado->loadXML($xml);
$Signature = $xml_firmado->createElement('Signature');
// ... (Estructura XAdES para DIAN)
$xml_firmado->documentElement->appendChild($Signature);
$xml_firmado->save(WP_CONTENT_DIR . "/facturas/factura-firmada-$order_id.xml");
}
---
#### **Snippet 4: Generación CUDE (Código Único de Documento Electrónico)**
**Objetivo:** Crear CUDE según algoritmo DIAN.
php
function generar_cude($order_id) {
$order = wc_get_order($order_id);
$nit_emisor = ‘900123456-7’;
$fecha = date(‘Y-m-d’);
$total = $order->get_total();
$uuid = wp_generate_uuid4();
// Cadena para hash
$cadena = "$nit_emisor|$fecha|$total|$uuid";
$hash = hash('sha384', $cadena);
// Formato CUDE
$cude = "CUDE-$hash-" . strtoupper($uuid);
update_post_meta($order_id, '_cude', $cude);
return $cude;
}
---
#### **Snippet 5: Validación XSD**
**Objetivo:** Verificar XML contra esquema DIAN.
php
function validar_xml_dian($order_id) {
$xml = file_get_contents(get_post_meta($order_id, ‘_factura_xml’, true));
$xsd_url = ‘https://catalogo-vpfe.dian.gov.co/Documentos/XSD/UBL2.1/maindoc/DIAN_UBL2.1.xsd’;
$dom = new DOMDocument();
$dom->loadXML($xml);
if (!$dom->schemaValidate($xsd_url)) {
$errors = libxml_get_errors();
error_log("Error validación DIAN: " . print_r($errors, true));
return false;
}
return true;
}
---
#### **Snippet 6: Envío a DIAN vía API**
**Objetivo:** Transmitir XML a servidores DIAN (Requiere cURL).
php
add_action(‘validar_xml_dian’, ‘enviar_a_dian’);
function enviar_a_dian($order_id) {
$xml_firmado = file_get_contents(get_post_meta($order_id, ‘_factura_xml’, true));
$ambiente = ‘habilitacion’; // Cambiar a ‘produccion’ luego
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://catalogo-vpfe.dian.gov.co/$ambiente/api/v1/documents");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/xml',
'Authorization: Bearer ' . obtener_token_dian()
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_firmado);
$response = curl_exec($ch);
curl_close($ch);
// Guardar respuesta DIAN
update_post_meta($order_id, '_respuesta_dian', $response);
}
---
#### **Snippet 7: Adjuntar Factura a Emails**
**Objetivo:** Incluir PDF/XML en correos de WooCommerce.
php
add_filter(‘woocommerce_email_attachments’, ‘adjuntar_factura_dian’, 10, 3);
function adjuntar_factura_dian($attachments, $email_id, $order) {
if ($email_id === ‘customer_completed_order’) {
$file_path = get_post_meta($order->get_id(), ‘_factura_xml’, true);
$attachments[] = $file_path;
}
return $attachments;
}
---
#### **Snippet 8: Shortcode para Descarga**
**Objetivo:** Permitir al cliente descargar factura desde "Mi cuenta".
php
add_shortcode(‘descargar_factura’, ‘shortcode_descargar_factura’);
function shortcode_descargar_factura() {
if (!is_user_logged_in()) return;
$order_id = wc_get_order_id_by_order_key($_GET['order_key']);
$file_url = get_post_meta($order_id, '_factura_xml', true);
return '<a href="' . $file_url . '" class="button">Descargar Factura</a>';
}
“`
3. Flujo de Trabajo Completo
- Checkout: Cliente ingresa NIT y tipo de responsable (Snippet 1).
- Orden Completada:
- Generar XML (Snippet 2).
- Firmar con certificado (Snippet 3).
- Generar CUDE (Snippet 4).
- Validar XSD (Snippet 5).
- Envío DIAN: Transmitir XML vía API (Snippet 6).
- Notificación: Adjuntar factura a emails (Snippet 7) y permitir descarga (Snippet 8).
4. Recursos Clave DIAN
- Validación XSD: Esquemas UBL 2.1.
- Ambiente de Pruebas: VPFE DIAN.
- Generación CUDE: Algoritmo SHA-384 + UUID.
5. Conclusión
- Snippets Necesarios: 8 (PHP para campos, XML, firma, CUDE, validación, API, emails y shortcode).
- Fuera de WordPress: Certificado DIAN, servidor con OpenSSL, registro en ambiente DIAN.
- Influencia DIAN: 100% crítica. Todo el flujo técnico y legal depende de sus especificaciones.
- Dificultad Técnica: Alta (Requiere integración con APIs, manejo de criptografía y estrictas validaciones XSD).
Nota Final: Este es un esquema básico. La implementación real requiere pruebas en ambiente DIAN, manejo de errores y posible integración con un proveedor tecnológico homologado.
Respuesta Detallada sobre la Conexión Directa a la DIAN mediante API (Colombia):
La DIAN (Dirección de Impuestos y Aduanas Nacionales) establece reglas estrictas para la facturación electrónica en Colombia. A continuación, aclaro el panorama legal y técnico:
1. ¿Permite la DIAN la Conexión Directa mediante API?
Sí, pero solo bajo estas condiciones:
- Para Proveedores Tecnológicos Homologados:
La DIAN autoriza únicamente a los Proveedores Tecnológicos (PT) homologados (Lista oficial aquí) para conectarse directamente a sus servidores mediante API. Estos PT actúan como intermediarios entre tu sistema (WordPress/WooCommerce) y la DIAN. - Para Empresas No Homologadas:
No es posible conectarse directamente a los servidores de la DIAN. Debes usar:
a) Un PT homologado (Ej: Facturador electrónico como Alegra, Siigo, o un desarrollo propio homologado).
b) La plataforma web de la DIAN (Subida manual de XML).
2. Base Legal
- Resolución 000042 de 2022 (Artículo 2.2.1.9.5.4):
Establece que la transmisión de facturas electrónicas debe realizarse a través de un canal tecnológico seguro, el cual solo pueden proveer los PT homologados. - Decreto 2242 de 2015 (Artículo 5):
Exige que los documentos electrónicos cumplan con los estándares de la DIAN, incluida la firma digital y la validación previa.
3. ¿Qué Sucede si te Conectas Directamente sin Homologación?
- Invalidez Legal: Las facturas generadas no tendrán validez ante la DIAN.
- Sanciones: Multas por incumplimiento de obligaciones tributarias (Artículo 651-3 del Estatuto Tributario).
- Rechazo Técnico: La DIAN bloquea las peticiones que no provengan de IPs autorizadas de PT homologados.
4. Alternativas para WooCommerce/WordPress
a) Usar un Proveedor Tecnológico Homologado
- Pasos:
- Contratar un PT (Ej: Habemus, Efact).
- Integrar su API con WooCommerce mediante plugins o snippets PHP.
- El PT se encarga de:
- Generar el XML según estándares DIAN.
- Firmar digitalmente.
- Transmitir a la DIAN.
- Gestionar respuestas y contingencia.
- Ejemplo de Snippet para Integración con API de PT:
“`php
add_action(‘woocommerce_payment_complete’, ‘enviar_factura_pt_homologado’);
function enviar_factura_pt_homologado($order_id) {
$order = wc_get_order($order_id);
$payload = array(
‘cliente’ => array(
‘nit’ => get_post_meta($order_id, ‘_billing_nit’, true),
‘total’ => $order->get_total()
),
‘items’ => array()
);// Agregar items foreach ($order->get_items() as $item) { $payload['items'][] = array( 'nombre' => $item->get_name(), 'precio' => $item->get_subtotal() ); } // Enviar a PT (Ej: Habemus) $response = wp_remote_post('https://api.pt-homologado.com/facturas', array( 'headers' => array('Authorization' => 'Bearer TU_API_KEY'), 'body' => json_encode($payload) )); // Guardar respuesta update_post_meta($order_id, '_respuesta_pt', $response['body']);
}
“`
b) Usar la Plataforma Web de la DIAN
- Pasos:
- Generar el XML manualmente en WooCommerce (usando los snippets previos).
- Descargar el XML firmado.
- Subirlo manualmente al portal de validación DIAN:
5. ¿Cómo Homologar tu Propio Software como PT?
Si quieres evitar intermediarios y conectarte directamente, debes:
- Registrarte como PT:
- Diligenciar el formulario en Registro PT DIAN.
- Presentar certificados de seguridad y pruebas técnicas.
- Cumplir Requisitos Técnicos:
- Implementar APIs SOAP/ REST según especificaciones DIAN.
- Usar firma XAdES y algoritmos SHA-384.
- Certificación:
- La DIAN evaluará tu software durante 30 días hábiles.
- Costo aproximado: $8-15 millones de COP (dependiendo de complejidad).
6. Conclusión
- Legalmente, solo los Proveedores Tecnológicos Homologados pueden conectarse directamente a la DIAN vía API.
- Para usuarios de WooCommerce, la opción viable es integrarse con un PT homologado mediante su API.
- Conectar WordPress directamente a la DIAN sin homologación es ilegal y técnicamente inviable.
Recomendación Final:
Usa un PT homologado para evitar riesgos legales y asegurar la validez de tus facturas. Si desarrollas tu propia solución, tramita la homologación ante la DIAN.