Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
web-service-descarga-masiva-sat [2026/07/07 20:46] |
web-service-descarga-masiva-sat [2026/07/07 20:51] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | <html>\\ | + | ====== Web Service de Descarga de CFDI del SAT – IEngine ====== |
| - | <head>\\ | + | |
| - | <style>\\ | + | |
| - | .box-url { background-color: #f4f6f7; border-left: 4px solid #3498db; padding: 10px; font-family: monospace; font-size: 14px; margin-bottom: 15px; word-break: break-all; }\\ | + | |
| - | .box-code { background-color: #2c3e50; color: #ffffff; padding: 12px; border-radius: 4px; font-family: monospace; font-size: 14px; overflow-x: auto; margin-bottom: 15px; white-space: pre; }\\ | + | |
| - | table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }\\ | + | |
| - | th, td { border: 1px solid #dddddd; padding: 8px; text-align: left; }\\ | + | |
| - | th { background-color: #f2f2f2; }\\ | + | |
| - | .alert-box { background-color: #e8f4f8; border-left: 4px solid #2980b9; padding: 10px; margin-bottom: 15px; }\\ | + | |
| - | </style>\\ | + | |
| - | </head>\\ | + | |
| - | <body> | + | |
| - | <h1>Web Service de Descarga de CFDI del SAT – IEngine</h1>\\ | + | ===== 1. Introducción ===== |
| - | \\ | + | |
| - | <h2>1. Introducción</h2>\\ | + | |
| - | <p>El presente documento describe el uso del Web Service <strong>IEngine – Descarga SAT</strong>, utilizado para solicitar la descarga de comprobantes fiscales digitales (CFDI) desde el SAT mediante los parámetros proporcionados.</p>\\ | + | |
| - | <p>El servicio permite consultar y descargar los XML asociados a un RFC emisor dentro de un rango de fechas determinado. Una vez obtenidos los comprobantes, el sistema envía cada XML descargado hacia un endpoint webhook configurado por el usuario.</p> | + | |
| - | <h2>2. Endpoint del Servicio</h2>\\ | + | El presente documento describe el uso del Web Service **IEngine – Descarga SAT**, utilizado para solicitar la descarga de comprobantes fiscales digitales (CFDI) desde el SAT mediante los parámetros proporcionados. |
| - | <p><strong>URL del Web Service:</strong></p>\\ | + | |
| - | <div class="box-url">https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php</div> | + | |
| - | <h2>3. Método de consumo</h2>\\ | + | El servicio permite consultar y descargar los XML asociados a un RFC emisor dentro de un rango de fechas determinado. Una vez obtenidos los comprobantes, el sistema envía cada XML descargado hacia un endpoint webhook configurado por el usuario. |
| - | <p>El servicio recibe parámetros mediante una solicitud <strong>HTTP GET</strong>.</p>\\ | + | |
| - | <p><strong>Ejemplo de estructura:</strong></p>\\ | + | |
| - | <div class="box-url">https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=RFC&TipoComprobante=N&callback=webhookUrl&fechaInicial=2025-10-22&fechaFinal=2025-10-24</div> | + | |
| - | <h2>4. Parámetros de entrada</h2>\\ | + | ===== 2. Endpoint del Servicio ===== |
| - | <table>\\ | + | |
| - | <thead>\\ | + | |
| - | <tr>\\ | + | |
| - | <th>Parámetro</th>\\ | + | |
| - | <th>Tipo</th>\\ | + | |
| - | <th>Requerido</th>\\ | + | |
| - | <th>Descripción</th>\\ | + | |
| - | </tr>\\ | + | |
| - | </thead>\\ | + | |
| - | <tbody>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>engine</strong></td>\\ | + | |
| - | <td>String</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>Nombre del motor a ejecutar. Para descarga SAT debe enviarse descagaSAT.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>RfcEmisor</strong></td>\\ | + | |
| - | <td>String</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>RFC del emisor del cual se desean descargar comprobantes.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>TipoComprobante</strong></td>\\ | + | |
| - | <td>String</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>Tipo de comprobante a consultar. Ejemplo: N para nómina. Ver catálogo al final.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>callback</strong></td>\\ | + | |
| - | <td>URL/String</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>Endpoint donde serán enviados los XML descargados.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>fechaInicial</strong></td>\\ | + | |
| - | <td>Date</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>Fecha inicial del rango de búsqueda. Formato: YYYY-MM-DD</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>fechaFinal</strong></td>\\ | + | |
| - | <td>Date</td>\\ | + | |
| - | <td>Sí</td>\\ | + | |
| - | <td>Fecha final del rango de búsqueda. Formato: YYYY-MM-DD</td>\\ | + | |
| - | </tr>\\ | + | |
| - | </tbody>\\ | + | |
| - | </table> | + | |
| - | <h2>5. Ejemplo de solicitud</h2>\\ | + | **URL del Web Service:** |
| - | <p><strong>Solicitud (GET):</strong></p>\\ | + | |
| - | <div class="box-url">https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=XAXX010101000&TipoComprobante=N&callback=https://midominio.com/webhook&fechaInicial=2025-10-22&fechaFinal=2025-10-24</div> | + | |
| - | <h2>6. Funcionamiento del servicio</h2>\\ | + | https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php |
| - | <p>El flujo de operación es el siguiente:</p>\\ | + | |
| - | <ul>\\ | + | |
| - | <li>El usuario realiza una petición al Web Service indicando:\\ | + | |
| - | <ul>\\ | + | |
| - | <li>RFC del emisor.</li>\\ | + | |
| - | <li>Tipo de comprobante.</li>\\ | + | |
| - | <li>Periodo de consulta.</li>\\ | + | |
| - | <li>URL del webhook receptor.</li>\\ | + | |
| - | </ul>\\ | + | |
| - | </li>\\ | + | |
| - | <li>El servicio consulta los CFDI disponibles en SAT.</li>\\ | + | |
| - | <li>Por cada XML encontrado, el servicio realiza una llamada HTTP al webhook registrado.</li>\\ | + | |
| - | <li>El webhook recibe el XML correspondiente.</li>\\ | + | |
| - | <li>El proceso se repite hasta enviar todos los XML encontrados.</li>\\ | + | |
| - | </ul> | + | |
| - | <h2>7. Webhook receptor</h2>\\ | + | ===== 3. Método de consumo ===== |
| - | <p><strong>Descripción:</strong> El webhook es un endpoint proporcionado por el usuario consumidor del servicio. Este endpoint será invocado <strong>N veces</strong>, donde N corresponde al número de XML descargados.</p>\\ | + | |
| - | <div class="alert-box">\\ | + | |
| - | <strong>Nota:</strong> Si SAT devuelve 100 XML, el webhook será llamado 100 veces de forma individual y cada llamada contendrá un XML diferente.\\ | + | |
| - | </div> | + | |
| - | <h2>8. Parámetros enviados al webhook</h2>\\ | + | El servicio recibe parámetros mediante una solicitud **HTTP GET**. |
| - | <p>El webhook recibe un parámetro vía POST:</p>\\ | + | |
| - | <table>\\ | + | |
| - | <thead>\\ | + | |
| - | <tr>\\ | + | |
| - | <th>Parámetro</th>\\ | + | |
| - | <th>Tipo</th>\\ | + | |
| - | <th>Descripción</th>\\ | + | |
| - | </tr>\\ | + | |
| - | </thead>\\ | + | |
| - | <tbody>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>xml</strong></td>\\ | + | |
| - | <td>String/XML</td>\\ | + | |
| - | <td>Contenido completo del CFDI descargado.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | </tbody>\\ | + | |
| - | </table> | + | |
| - | <p><strong>Ejemplo de payload recibido:</strong></p>\\ | + | **Ejemplo de estructura:** |
| - | <pre class="box-code">[\\ | + | |
| - | 'xml' => 'contenido_xml_del_cfdi'\\ | + | |
| - | ]</pre> | + | |
| - | <h2>9. Ejemplo de recepción del webhook</h2>\\ | + | https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=RFC&TipoComprobante=N&callback=webhookUrl&fechaInicial=2025-10-22&fechaFinal=2025-10-24 |
| - | <p><strong>Ejemplo en PHP:</strong></p>\\ | + | |
| - | <pre class="box-code"><?php | + | ===== 4. Parámetros de entrada ===== |
| + | |||
| + | ^Parámetro ^Tipo ^Requerido ^Descripción | | ||
| + | |**engine** |String |Sí |Nombre del motor a ejecutar. Para descarga SAT debe enviarse descagaSAT. | | ||
| + | |**RfcEmisor** |String |Sí |RFC del emisor del cual se desean descargar comprobantes. | | ||
| + | |**TipoComprobante** |String |Sí |Tipo de comprobante a consultar. Ejemplo: N para nómina. Ver catálogo al final. | | ||
| + | |**callback** |URL/String |Sí |Endpoint donde serán enviados los XML descargados. | | ||
| + | |**fechaInicial** |Date |Sí |Fecha inicial del rango de búsqueda. Formato: YYYY-MM-DD | | ||
| + | |**fechaFinal** |Date |Sí |Fecha final del rango de búsqueda. Formato: YYYY-MM-DD | | ||
| + | |||
| + | ===== 5. Ejemplo de solicitud ===== | ||
| + | |||
| + | **Solicitud (GET):** | ||
| + | |||
| + | https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=XAXX010101000&TipoComprobante=N&callback=https://midominio.com/webhook&fechaInicial=2025-10-22&fechaFinal=2025-10-24 | ||
| + | |||
| + | ===== 6. Funcionamiento del servicio ===== | ||
| + | |||
| + | El flujo de operación es el siguiente: | ||
| + | |||
| + | * El usuario realiza una petición al Web Service indicando: | ||
| + | * RFC del emisor. | ||
| + | * Tipo de comprobante. | ||
| + | * Periodo de consulta. | ||
| + | * URL del webhook receptor. | ||
| + | * El servicio consulta los CFDI disponibles en SAT. | ||
| + | * Por cada XML encontrado, el servicio realiza una llamada HTTP al webhook registrado. | ||
| + | * El webhook recibe el XML correspondiente. | ||
| + | * El proceso se repite hasta enviar todos los XML encontrados. | ||
| + | |||
| + | ===== 7. Webhook receptor ===== | ||
| + | |||
| + | **Descripción:** El webhook es un endpoint proporcionado por el usuario consumidor del servicio. Este endpoint será invocado **N veces**, donde N corresponds al número de XML descargados. | ||
| + | |||
| + | **Nota:** Si SAT devuelve 100 XML, el webhook será llamado 100 veces de forma individual y cada llamada contendrá un XML diferente. | ||
| + | |||
| + | ===== 8. Parámetros enviados al webhook ===== | ||
| + | |||
| + | El webhook recibe un parámetro vía POST: | ||
| + | |||
| + | ^Parámetro ^Tipo ^Descripción | | ||
| + | |**xml** |String/XML |Contenido completo del CFDI descargado. | | ||
| + | |||
| + | **Ejemplo de payload recibido:** | ||
| + | |||
| + | <code>[ | ||
| + | 'xml' => 'contenido_xml_del_cfdi' | ||
| + | ] | ||
| + | </code> | ||
| + | ===== 9. Ejemplo de recepción del webhook ===== | ||
| + | |||
| + | **Ejemplo en PHP:** | ||
| + | |||
| + | <code><?php | ||
| $xml = $_POST['xml'] ?? null; | $xml = $_POST['xml'] ?? null; | ||
| - | if ($xml) {\\ | + | if ($xml) { |
| - | // Procesar XML recibido\\ | + | // Procesar XML recibido |
| - | file_put_contents('cfdi.xml', $xml);\\ | + | file_put_contents('cfdi.xml', $xml); |
| - | echo "XML recibido correctamente";\\ | + | echo "XML recibido correctamente"; |
| - | } else {\\ | + | } else { |
| - | http_response_code(400);\\ | + | http_response_code(400); |
| - | echo "XML no recibido";\\ | + | echo "XML no recibido"; |
| } | } | ||
| - | ?></pre> | + | ?> |
| + | </code> | ||
| + | ===== 10. Recomendaciones para implementar el webhook ===== | ||
| + | |||
| + | * Aceptar solicitudes HTTP POST. | ||
| + | * Validar que el parámetro xml exista. | ||
| + | * Guardar o procesar el XML recibido. | ||
| + | * Responder rápidamente para evitar tiempos de espera (timeouts). | ||
| + | * Registrar errores de procesamiento. | ||
| + | |||
| + | **Respuesta recomendada:** HTTP 200 OK (Cuerpo: OK) | ||
| + | |||
| + | ===== 11. Manejo de múltiples XML ===== | ||
| + | |||
| + | * El webhook puede recibir múltiples llamadas consecutivas. | ||
| + | * Cada llamada representa un CFDI independiente. | ||
| + | * No debe asumir que todos los XML llegarán en una sola petición. | ||
| + | * Debe implementar almacenamiento temporal o procesamiento en cola si espera grandes volúmenes. | ||
| + | |||
| + | ===== 12. Consideraciones de seguridad ===== | ||
| + | |||
| + | * Utilizar HTTPS en el callback. | ||
| + | * Validar el origen de las solicitudes. | ||
| + | * Implementar autenticación adicional en la URL si el ambiente lo requiere. | ||
| + | * Evitar almacenar XML sin controles de acceso. | ||
| + | |||
| + | ===== 13. Resumen del flujo ===== | ||
| + | |||
| + | <code>Cliente | ||
| + | | | ||
| + | | Solicitud descarga SAT (GET) | ||
| + | v | ||
| + | IEngine Web Service | ||
| + | | | ||
| + | | Consulta CFDI SAT | ||
| + | v | ||
| + | XML encontrado | ||
| + | | | ||
| + | | POST webhook (N veces) | ||
| + | v | ||
| + | Sistema consumidor (Procesa y almacena) | ||
| + | </code> | ||
| + | ===== 14. Ejemplo completo ===== | ||
| + | |||
| + | **Solicitud:** | ||
| - | <h2>10. Recomendaciones para implementar el webhook</h2>\\ | + | https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=AAA010101AAA&TipoComprobante=N&callback=https://cliente.com/webhook/cfdi&fechaInicial=2025-10-22&fechaFinal=2025-10-24 |
| - | <ul>\\ | + | |
| - | <li>Aceptar solicitudes HTTP POST.</li>\\ | + | |
| - | <li>Validar que el parámetro xml exista.</li>\\ | + | |
| - | <li>Guardar o procesar el XML recibido.</li>\\ | + | |
| - | <li>Responder rápidamente para evitar tiempos de espera (timeouts).</li>\\ | + | |
| - | <li>Registrar errores de procesamiento.</li>\\ | + | |
| - | </ul>\\ | + | |
| - | <p><strong>Respuesta recomendada:</strong> HTTP 200 OK (Cuerpo: OK)</p> | + | |
| - | <h2>11. Manejo de múltiples XML</h2>\\ | + | **Resultado si existen 25 CFDI:** |
| - | <ul>\\ | + | |
| - | <li>El webhook puede recibir múltiples llamadas consecutivas.</li>\\ | + | |
| - | <li>Cada llamada representa un CFDI independiente.</li>\\ | + | |
| - | <li>No debe asumir que todos los XML llegarán en una sola petición.</li>\\ | + | |
| - | <li>Debe implementar almacenamiento temporal o procesamiento en cola si espera grandes volúmenes.</li>\\ | + | |
| - | </ul> | + | |
| - | <h2>12. Consideraciones de seguridad</h2>\\ | + | * El webhook será invocado 25 veces de forma independiente. |
| - | <ul>\\ | + | * Cada invocación recibirá: |
| - | <li>Utilizar HTTPS en el callback.</li>\\ | + | |
| - | <li>Validar el origen de las solicitudes.</li>\\ | + | |
| - | <li>Implementar autenticación adicional en la URL si el ambiente lo requiere.</li>\\ | + | |
| - | <li>Evitar almacenar XML sin controles de acceso.</li>\\ | + | |
| - | </ul> | + | |
| - | <h2>13. Resumen del flujo</h2>\\ | + | <code>[ |
| - | <pre class="box-code">Cliente\\ | + | 'xml' => '<cfdi:Comprobante ... > ... </cfdi:Comprobante>' |
| - | |\\ | + | ] |
| - | | Solicitud descarga SAT (GET)\\ | + | </code> |
| - | v\\ | + | ===== Tipos de comprobante CFDI soportados ===== |
| - | IEngine Web Service\\ | + | |
| - | |\\ | + | |
| - | | Consulta CFDI SAT\\ | + | |
| - | v\\ | + | |
| - | XML encontrado\\ | + | |
| - | |\\ | + | |
| - | | POST webhook (N veces)\\ | + | |
| - | v\\ | + | |
| - | Sistema consumidor (Procesa y almacena)</pre> | + | |
| - | <h2>14. Ejemplo completo</h2>\\ | + | El parámetro TipoComprobante permite indicar el tipo de CFDI que se desea consultar durante la descarga desde SAT. Los valores posibles corresponden al atributo oficial definido por la autoridad: |
| - | <p><strong>Solicitud:</strong></p>\\ | + | |
| - | <div class="box-url">https://pruebas-ifactura.itimbre.com/plugins/IEngine/IEngine.php?engine=descagaSAT&RfcEmisor=AAA010101AAA&TipoComprobante=N&callback=https://cliente.com/webhook/cfdi&fechaInicial=2025-10-22&fechaFinal=2025-10-24</div> | + | |
| - | <p><strong>Resultado si existen 25 CFDI:</strong></p>\\ | + | ^Valor ^Tipo de comprobante ^Descripción | |
| - | <ul>\\ | + | |**I** |Ingreso |Comprobantes emitidos por la prestación de servicios, venta de productos, arrendamientos u operaciones donde existe un ingreso. | |
| - | <li>El webhook será invocado 25 veces de forma independiente.</li>\\ | + | |**E** |Egreso |Comprobantes utilizados para devoluciones, descuentos, bonificaciones o ajustes relacionados con ingresos previamente registrados. | |
| - | <li>Cada invocación recibirá:</li>\\ | + | |**T** |Traslado |Comprobantes utilizados para acreditar el transporte o traslado de mercancías. | |
| - | </ul>\\ | + | |**N** |Nómina |Comprobantes fiscales digitales utilizados para registrar pagos de salarios y prestaciones a trabajadores. | |
| - | <pre class="box-code">[\\ | + | |**P** |Pago |Comprobantes utilizados para registrar la recepción de pagos relacionados con operaciones previamente facturadas. | |
| - | 'xml' => '<cfdi:Comprobante ... > ... </cfdi:Comprobante>'\\ | + | |
| - | ]</pre> | + | |
| - | <h2>Tipos de comprobante CFDI soportados</h2>\\ | + | **Ejemplos de uso rápidos:** |
| - | <p>El parámetro TipoComprobante permite indicar el tipo de CFDI que se desea consultar durante la descarga desde SAT. Los valores posibles corresponden al atributo oficial definido por la autoridad:</p> | + | |
| - | <table>\\ | + | * **Descargar CFDI de nómina:** TipoComprobante=N |
| - | <thead>\\ | + | * **Descargar facturas emitidas:** TipoComprobante=I |
| - | <tr>\\ | + | * **Descargar notas de crédito:** TipoComprobante=E |
| - | <th>Valor</th>\\ | + | * **Descargar comprobantes de traslado:** TipoComprobante=T |
| - | <th>Tipo de comprobante</th>\\ | + | * **Descargar complementos de pago:** TipoComprobante=P |
| - | <th>Descripción</th>\\ | + | |
| - | </tr>\\ | + | |
| - | </thead>\\ | + | |
| - | <tbody>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>I</strong></td>\\ | + | |
| - | <td>Ingreso</td>\\ | + | |
| - | <td>Comprobantes emitidos por la prestación de servicios, venta de productos, arrendamientos u operaciones donde existe un ingreso.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>E</strong></td>\\ | + | |
| - | <td>Egreso</td>\\ | + | |
| - | <td>Comprobantes utilizados para devoluciones, descuentos, bonificaciones o ajustes relacionados con ingresos previamente registrados.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>T</strong></td>\\ | + | |
| - | <td>Traslado</td>\\ | + | |
| - | <td>Comprobantes utilizados para acreditar el transporte o traslado de mercancías.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>N</strong></td>\\ | + | |
| - | <td>Nómina</td>\\ | + | |
| - | <td>Comprobantes fiscales digitales utilizados para registrar pagos de salarios y prestaciones a trabajadores.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | <tr>\\ | + | |
| - | <td><strong>P</strong></td>\\ | + | |
| - | <td>Pago</td>\\ | + | |
| - | <td>Comprobantes utilizados para registrar la recepción de pagos relacionados con operaciones previamente facturadas.</td>\\ | + | |
| - | </tr>\\ | + | |
| - | </tbody>\\ | + | |
| - | </table> | + | |
| - | <p><strong>Ejemplos de uso rápidos:</strong></p>\\ | + | **Consideraciones adicionales:** |
| - | <ul>\\ | + | |
| - | <li><strong>Descargar CFDI de nómina:</strong> TipoComprobante=N</li>\\ | + | |
| - | <li><strong>Descargar facturas emitidas:</strong> TipoComprobante=I</li>\\ | + | |
| - | <li><strong>Descargar notas de crédito:</strong> TipoComprobante=E</li>\\ | + | |
| - | <li><strong>Descargar comprobantes de traslado:</strong> TipoComprobante=T</li>\\ | + | |
| - | <li><strong>Descargar complementos de pago:</strong> TipoComprobante=P</li>\\ | + | |
| - | </ul> | + | |
| - | <p><strong>Consideraciones adicionales:</strong></p>\\ | + | * El valor enviado debe utilizar la letra correspondiente en mayúscula. |
| - | <ul>\\ | + | * La consulta se realizará únicamente para el tipo de comprobante indicado. |
| - | <li>El valor enviado debe utilizar la letra correspondiente en mayúscula.</li>\\ | + | * Para descargar diferentes tipos de CFDI se debe realizar una solicitud independiente por cada valor. |
| - | <li>La consulta se realizará únicamente para el tipo de comprobante indicado.</li>\\ | + | |
| - | <li>Para descargar diferentes tipos de CFDI se debe realizar una solicitud independiente por cada valor.</li>\\ | + | |
| - | </ul> | + | |
| - | </body>\\ | + | \\ |
| - | </html> | + | |