Example #1
0
function satxmlsv20($arr, $edidata = false, $dir = "./tmp/", $nodo = "", $addenda = "")
{
    // {{{  Parametros generales
    global $xml, $cadena_original, $conn, $sello;
    //error_reporting(E_ALL);
    //error_reporting(0);
    error_reporting(E_ALL & ~(E_WARNING | E_NOTICE));
    $cadena_original = '||';
    $noatt = array();
    $nufa = $arr['serie'] . $arr['folio'];
    // Junta el numero de factura   serie + folio
    // }}}
    // {{{  Datos generales del Comprobante
    $xml = new DOMdocument("1.0", "UTF-8");
    $root = $xml->createElement("Comprobante");
    $root = $xml->appendChild($root);
    if ($addenda == "detallista") {
        # 12/Mar/2009   Se agrega el namespace de detallista para futurama
        cargaAtt($root, array("xmlns" => "http://www.sat.gob.mx/cfd/2", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:detallista" => "http://www.sat.gob.mx/detallista", "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/2 http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd http://www.sat.gob.mx/detallista http://www.sat.gob.mx/sitio_internet/cfd/detallista/detallista.xsd"));
    } elseif ($addenda == "diconsa") {
        # 23/Oct/2009   Se agrega el namespace de Diconsa
        cargaAtt($root, array("xmlns" => "http://www.sat.gob.mx/cfd/2", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:Diconsa" => "http://www.diconsa.gob.mx/cfd", "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/2 http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd http://www.diconsa.gob.mx/cfd http://www.diconsa.gob.mx/cfd/diconsa.xsd"));
    } elseif ($addenda == "superneto") {
        # 26/Ago/2010   Se agrega el namespace de SuperNeto
        cargaAtt($root, array("xmlns" => "http://www.sat.gob.mx/cfd/2", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:ap" => "http://www.tiendasneto.com/ap", "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/2 http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd http://www.tiendasneto.com/ap addenda_prov.xsd"));
    } elseif ($addenda == "extra") {
        # 04/Ene/2012   Se agrega el namespace de Tiendas Extra
        cargaAtt($root, array("xmlns" => "http://www.sat.gob.mx/cfd/2", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:modelo" => "http://www.gmodelo.com.mx/CFD/Addenda/Receptor", "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/2 http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd http://www.gmodelo.com.mx/CFD/Addenda/Receptor https://femodelo.gmodelo.com/Addenda/ADDENDAMODELO.xsd"));
    } else {
        cargaAtt($root, array("xmlns" => "http://www.sat.gob.mx/cfd/2", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/2  http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd"));
    }
    cargaAtt($root, array("version" => "2.0", "serie" => $arr['serie'], "folio" => $arr['folio'], "fecha" => xml_fech($arr['fecha']), "sello" => "@", "noAprobacion" => $arr['noAprobacion'], "anoAprobacion" => $arr['anoAprobacion'], "tipoDeComprobante" => $arr['tipoDeComprobante'], "formaDePago" => $arr['formaDePago'], "noCertificado" => $arr['noCertificado'], "certificado" => "@", "subTotal" => $arr['subTotal'], "descuento" => "0", "total" => $arr['total']));
    // }}}
    // {{{ Datos del Emisor
    $emisor = $xml->createElement("Emisor");
    $emisor = $root->appendChild($emisor);
    cargaAtt($emisor, array("rfc" => $arr['Emisor']['rfc'], "nombre" => $arr['Emisor']['nombre']));
    $domfis = $xml->createElement("DomicilioFiscal");
    $domfis = $emisor->appendChild($domfis);
    cargaAtt($domfis, array("calle" => "CARLOS B. ZETINA", "noExterior" => "80", "noInterior" => "", "colonia" => "INDUSTRIAL XALOSTOC", "localidad" => "ECATEPEC DE MORELOS", "municipio" => "ECATEPEC", "estado" => "MEXICO", "pais" => "MEXICO", "codigoPostal" => "55348"));
    $expedido = $xml->createElement("ExpedidoEn");
    $expedido = $emisor->appendChild($expedido);
    cargaAtt($expedido, array("calle" => $arr['Emisor']['ExpedidoEn']['calle'], "noExterior" => $arr['Emisor']['ExpedidoEn']['noExterior'], "noInterior" => $arr['Emisor']['ExpedidoEn']['noInterior'], "localidad" => $arr['Emisor']['ExpedidoEn']['localidad'], "municipio" => $arr['Emisor']['ExpedidoEn']['municipio'], "estado" => $arr['Emisor']['ExpedidoEn']['estado'], "pais" => $arr['Emisor']['ExpedidoEn']['pais'], "codigoPostal" => $arr['Emisor']['ExpedidoEn']['codigoPostal']));
    // }}}
    // {{{ Datos del Receptor
    $receptor = $xml->createElement("Receptor");
    $receptor = $root->appendChild($receptor);
    cargaAtt($receptor, array("rfc" => $arr['Receptor']['rfc'], "nombre" => $arr['Receptor']['nombre']));
    $domicilio = $xml->createElement("Domicilio");
    $domicilio = $receptor->appendChild($domicilio);
    cargaAtt($domicilio, array("calle" => $arr['Receptor']['Domicilio']['calle'], "noExterior" => $arr['Receptor']['Domicilio']['noExterior'], "noInterior" => $arr['Receptor']['Domicilio']['noInterior'], "colonia" => $arr['Receptor']['Domicilio']['colonia'], "localidad" => $arr['Receptor']['Domicilio']['localidad'], "municipio" => $arr['Receptor']['Domicilio']['municipio'], "estado" => $arr['Receptor']['Domicilio']['estado'], "pais" => $arr['Receptor']['Domicilio']['pais'], "codigoPostal" => $arr['Receptor']['Domicilio']['codigoPostal']));
    // }}}
    // {{{ Detalle de los conceptos/produtos de la factura
    $conceptos = $xml->createElement("Conceptos");
    $conceptos = $root->appendChild($conceptos);
    for ($i = 1; $i <= sizeof($arr['Conceptos']); $i++) {
        $concepto = $xml->createElement("Concepto");
        $concepto = $conceptos->appendChild($concepto);
        cargaAtt($concepto, array("cantidad" => $arr['Conceptos'][$i]['cantidad'], "descripcion" => $arr['Conceptos'][$i]['descripcion'], "valorUnitario" => $arr['Conceptos'][$i]['valorUnitario'], "importe" => $arr['Conceptos'][$i]['importe']));
    }
    // }}}
    // {{{ Impuesto (IVA)
    $impuestos = $xml->createElement("Impuestos");
    $impuestos = $root->appendChild($impuestos);
    # 7/ago/2006  Ojoj, no confundir tasa 0 con excento
    if (isset($arr['Traslados']['importe'])) {
        $traslados = $xml->createElement("Traslados");
        $traslados = $impuestos->appendChild($traslados);
        $traslado = $xml->createElement("Traslado");
        $traslado = $traslados->appendChild($traslado);
        cargaAtt($traslado, array("impuesto" => $arr['Traslados']['impuesto'], "tasa" => $arr['Traslados']['tasa'], "importe" => $arr['Traslados']['importe']));
    }
    $impuestos->SetAttribute("totalImpuestosTrasladados", $arr['Traslados']['importe']);
    catCadena($arr['Traslados']['importe']);
    // }}}
    // {{{ Complmento si es detallista
    if ($addenda == "detallista") {
        $Complemento = $xml->createElement("Complemento");
        $Complemento = $root->appendChild($Complemento);
        $detallista = $xml->createElement("detallista:detallista");
        $detallista->SetAttribute("type", "SimpleInvoiceType");
        $detallista->SetAttribute("contentVersion", "1.3.1");
        $detallista->SetAttribute("documentStructureVersion", "AMC8.1");
        catCadena("AMC8.1");
        $detallista->SetAttribute("documentStatus", "ORIGINAL");
        $requestForPaymentIdentification = $xml->createElement("detallista:requestForPaymentIdentification");
        $entityType = $xml->createElement("detallista:entityType", "INVOICE");
        $entityType = $requestForPaymentIdentification->appendChild($entityType);
        $requestForPaymentIdentification = $detallista->appendChild($requestForPaymentIdentification);
        $orderIdentification = $xml->createElement("detallista:orderIdentification");
        $referenceIdentification = $xml->createElement("detallista:referenceIdentification", trim($arr['Complemento']['npec']));
        catCadena($arr['Complemento']['npec']);
        $referenceIdentification->SetAttribute("type", "ON");
        $referenceIdentification = $orderIdentification->appendChild($referenceIdentification);
        $ReferenceDate = $xml->createElement("detallista:ReferenceDate", xml_fix_fech($arr['Complemento']['fpec']));
        catCadena(xmL_fix_fech($arr['Complemento']['fpec']));
        $ReferenceDate = $orderIdentification->appendChild($ReferenceDate);
        $orderIdentification = $detallista->appendChild($orderIdentification);
        $AdditionalInformation = $xml->createElement("detallista:AdditionalInformation");
        $referenceIdentification = $xml->createElement("detallista:referenceIdentification", $arr['serie'] . $arr['folio']);
        $referenceIdentification->SetAttribute("type", "IV");
        $referenceIdentification = $AdditionalInformation->appendChild($referenceIdentification);
        $AdditionalInformation = $detallista->appendChild($AdditionalInformation);
        $buyer = $xml->createElement("detallista:buyer");
        $gln = $xml->createElement("detallista:gln", trim($arr['Complemento']['gln']));
        catCadena($arr['Complemento']['gln']);
        $gln = $buyer->appendChild($gln);
        $buyer = $detallista->appendChild($buyer);
        $seller = $xml->createElement("detallista:seller");
        $gln = $xml->createElement("detallista:gln", '0000000001867');
        catCadena('0000000001867');
        $alternatePartyIdentification = $xml->createElement("detallista:alternatePartyIdentification", "01867");
        catCadena('01867');
        $alternatePartyIdentification->setAttribute("type", "SELLER_ASSIGNED_IDENTIFIER_FOR_A_PARTY");
        $tmp = $seller->appendChild($gln);
        $tmp = $seller->appendChild($alternatePartyIdentification);
        $tmp = $detallista->appendChild($seller);
        for ($i = 1; $i <= sizeof($arr['Conceptos']); $i++) {
            $lineItem = $xml->createElement("detallista:lineItem");
            $lineItem->SetAttribute("type", "SimpleInvoiceLineItemType");
            $lineItem->SetAttribute("number", $i);
            $tradeItemIdentification = $xml->createElement("detallista:tradeItemIdentification");
            $gtin = $xml->createElement("detallista:gtin", trim($arr['Conceptos'][$i]['gtin']));
            $gtin = $tradeItemIdentification->appendChild($gtin);
            $tradeItemIdentification = $lineItem->appendChild($tradeItemIdentification);
            $tradeItemDescriptionInformation = $xml->createElement("detallista:tradeItemDescriptionInformation");
            $tradeItemDescriptionInformation->SetAttribute("language", "ES");
            $longText = $xml->createElement("detallista:longText", $arr['Conceptos'][$i]['descripcion']);
            $longText = $tradeItemDescriptionInformation->appendChild($longText);
            $tradeItemDescriptionInformation = $lineItem->appendChild($tradeItemDescriptionInformation);
            $invoicedQuantity = $xml->createElement("detallista:invoicedQuantity", $arr['Conceptos'][$i]['cantidad']);
            $invoicedQuantity->SetAttribute("unitOfMeasure", "CS");
            $invoicedQuantity = $lineItem->appendChild($invoicedQuantity);
            $grossPrice = $xml->createElement("detallista:grossPrice");
            $Amount = $xml->createElement("detallista:Amount", $arr['Conceptos'][$i]['prun']);
            $Amount = $grossPrice->appendChild($Amount);
            $grossPrice = $lineItem->appendChild($grossPrice);
            $netPrice = $xml->createElement("detallista:netPrice");
            $Amount = $xml->createElement("detallista:Amount", $arr['Conceptos'][$i]['neto'] / $arr['Conceptos'][$i]['cantidad']);
            $Amount = $netPrice->appendChild($Amount);
            $netPrice = $lineItem->appendChild($netPrice);
            $tradeItemTaxInformation = $xml->createElement("detallista:tradeItemTaxInformation");
            $taxTypeDescription = $xml->createElement("detallista:taxTypeDescription", "VAT");
            $taxTypeDescription = $tradeItemTaxInformation->appendChild($taxTypeDescription);
            $tradeItemTaxAmount = $xml->createElement("detallista:tradeItemTaxAmount");
            $taxPercentage = $xml->createElement("detallista:taxPercentage", $arr['Conceptos'][$i]['poim']);
            $taxPercentage = $tradeItemTaxAmount->appendChild($taxPercentage);
            $taxAmount = $xml->createElement("detallista:taxAmount", $arr['Conceptos'][$i]['impu']);
            $taxAmount = $tradeItemTaxAmount->appendChild($taxAmount);
            $tradeItemTaxAmount = $tradeItemTaxInformation->appendChild($tradeItemTaxAmount);
            $taxCategory = $xml->createElement("detallista:taxCategory", "TRANSFERIDO");
            $taxCategory = $tradeItemTaxInformation->appendChild($taxCategory);
            $tradeItemTaxInformation = $lineItem->appendChild($tradeItemTaxInformation);
            $totalLineAmount = $xml->createElement("detallista:totalLineAmount");
            $netAmount = $xml->createElement("detallista:netAmount");
            $Amount = $xml->createElement("detallista:Amount", $arr['Conceptos'][$i]['importe']);
            $Amount = $netAmount->appendChild($Amount);
            $netAmount = $totalLineAmount->appendChild($netAmount);
            $totalLineAmount = $lineItem->appendChild($totalLineAmount);
            $lineItem = $detallista->appendChild($lineItem);
        }
        $totalAmount = $xml->createElement("detallista:totalAmount");
        $Amount = $xml->createElement("detallista:Amount", $arr['total']);
        catCadena($arr['total']);
        $Amount = $totalAmount->appendChild($Amount);
        $totalAmount = $detallista->appendChild($totalAmount);
        $detallista = $Complemento->appendChild($detallista);
    }
    // }}}
    // {{{ Addenda si se requiere
    if ($edidata || $addenda == "diconsa" || $addenda == "imss") {
        $Addenda = $xml->createElement("Addenda");
        if ($edidata != "") {
            if (substr($edidata, 0, 5) == "<?xml") {
                // Es XML por ejemplo Soriana
                $smp = simplexml_load_string($edidata);
                $Documento = dom_import_simplexml($smp);
                $Documento = $xml->importNode($Documento, true);
            } else {
                if ($nodo == "") {
                    // Va el EDIDATA directo sin nodo adiconal. por ejemplo Corvi
                    $Documento = $xml->createTextNode(utf8_encode($edidata));
                } else {
                    // Va el EDIDATA dentro de un nodo. por ejemplo Walmart
                    $Documento = $xml->createElement($nodo, utf8_encode($edidata));
                }
            }
            $Documento = $Addenda->appendChild($Documento);
        }
        if ($addenda == "diconsa") {
            $Agregado = $xml->createElement("Diconsa:Agregado");
            $Agregado->SetAttribute("nombre", "PROVEEDOR");
            $Agregado->SetAttribute("valor", $arr['diconsa']['proveedor']);
            $Agregado = $Addenda->appendChild($Agregado);
            $AgregadoProv = $xml->createElement("Diconsa:AgregadoProv");
            $AgregadoProv->SetAttribute("almacen", $arr['diconsa']['almacen']);
            $AgregadoProv->SetAttribute("negociacion", $arr['diconsa']['negociacion']);
            $AgregadoProv->SetAttribute("pedido", $arr['diconsa']['pedido']);
            $AgregadoProv = $Addenda->appendChild($AgregadoProv);
        }
        if ($addenda == "imss") {
            $Proveedor_IMSS = $xml->createElement("Proveedor_IMSS");
            $Proveedor = $xml->createElement("Proveedor");
            $Proveedor->SetAttribute("noProveedor", $arr['imss']['proveedor']);
            $Proveedor = $Proveedor_IMSS->appendChild($Proveedor);
            $Proveedor_IMSS = $Addenda->appendChild($Proveedor_IMSS);
            $Delegacion = $xml->createElement("Delegacion");
            $UnidadNegocio = $xml->createElement("UnidadNegocio");
            $UnidadNegocio->SetAttribute("unidad", $arr['imss']['delegacion']);
            $UnidadNegocio = $Delegacion->appendChild($UnidadNegocio);
            $Delegacion = $Addenda->appendChild($Delegacion);
            $Concepto = $xml->createElement("Concepto");
            $NumeroConcepto = $xml->createElement("NumeroConcepto");
            $NumeroConcepto->SetAttribute("concepto", $arr['imss']['concepto']);
            $NumeroConcepto = $Concepto->appendChild($NumeroConcepto);
            $Concepto = $Addenda->appendChild($Concepto);
            $Pedido = $xml->createElement("Pedido");
            $NumeroPedido = $xml->createElement("NumeroPedido");
            $NumeroPedido->SetAttribute("pedido", $arr['imss']['pedido']);
            $NumeroPedido = $Pedido->appendChild($NumeroPedido);
            $Pedido = $Addenda->appendChild($Pedido);
            $Recepcion = $xml->createElement("Recepcion");
            $Recepcion1 = $xml->createElement("Recepcion1");
            $Recepcion1->SetAttribute("numero_recepcion", $arr['imss']['recepcion']);
            $Recepcion1 = $Recepcion->appendChild($Recepcion1);
            $Recepcion = $Addenda->appendChild($Recepcion);
        }
        $Addenda = $root->appendChild($Addenda);
    }
    // }}}
    // {{{ Calculo de sello
    $cadena_original .= "|";
    // termina la cadena original con el doble ||
    $certificado = $arr['noCertificado'];
    $maquina = trim(`uname -n`);
    $ruta = $maquina == "www.fjcorona.com.mx" ? "/home/httpd/sat/" : "./";
    $file = $ruta . $certificado . ".key.pem";
    // Ruta al archivo
    // Obtiene la llave privada del Certificado de Sello Digital (CSD),
    //    Ojo , Nunca es la FIEL/FEA
    $pkeyid = openssl_get_privatekey(file_get_contents($file));
    // Si la fecha (anio) del documento es mayor del 2011 ....
    if ((int) substr($arr['fecha'], 0, 4) >= 2011) {
        openssl_sign($cadena_original, $crypttext, $pkeyid, OPENSSL_ALGO_SHA1);
    } else {
        openssl_sign($cadena_original, $crypttext, $pkeyid, OPENSSL_ALGO_MD5);
    }
    openssl_free_key($pkeyid);
    $sello = base64_encode($crypttext);
    // lo codifica en formato base64
    $root->setAttribute("sello", $sello);
    $file = $ruta . $certificado . ".cer.pem";
    // Ruta al archivo de Llave publica
    $datos = file($file);
    $certificado = "";
    $carga = false;
    for ($i = 0; $i < sizeof($datos); $i++) {
        if (strstr($datos[$i], "END CERTIFICATE")) {
            $carga = false;
        }
        if ($carga) {
            $certificado .= trim($datos[$i]);
        }
        if (strstr($datos[$i], "BEGIN CERTIFICATE")) {
            $carga = true;
        }
    }
    // El certificado coo base64 lo agrega al XML para simplificar la validacion
    $root->setAttribute("certificado", $certificado);
    // }}}
    // {{{ Genera un archivo de texto con el mensaje XML + EDI  O lo guarda en clcfdxml
    $xml->formatOutput = true;
    $todo = $xml->saveXML();
    $paso = $todo;
    // echo "despues de save = "; var_dump($todo); echo "\n";
    if ($dir != "/dev/null") {
        $xml->formatOutput = true;
        $xml->save($dir . $nufa . ".xml");
        $encfd = $conn->GetOne("Select count(*) from clcfdxml WHERE cfdxdocu = '{$nufa}'");
        if ($encfd == 0) {
            $conn->replace("clcfdxml", array("cfdxdocu" => $nufa, "cfdxcade" => $cadena_original, "cfdxlxml" => $paso), "cfdxdocu", true);
        }
    } else {
        $encfd = $conn->GetOne("Select count(*) from clcfdxml WHERE cfdxdocu = '{$nufa}'");
        if ($encfd == 0) {
            $conn->replace("clcfdxml", array("cfdxdocu" => $nufa, "cfdxcade" => $cadena_original, "cfdxlxml" => $paso), "cfdxdocu", true);
        }
    }
    // }}}
    // echo "antes de return = $todo\n";
    return $todo;
}
Example #2
0
function satxmls($arr, $edidata = false, $dir = "./tmp/", $nodo = "")
{
    // {{{  Parametros generales
    global $xml, $cadena_original, $conn;
    error_reporting(E_ALL);
    $cadena_original = '||';
    $noatt = array();
    $nufa = $arr['serie'] . $arr['folio'];
    // Junta el numero de factura   serie + folio
    // }}}
    // {{{  Datos generales del Comprobante
    $xml = new DOMdocument("1.0", "UTF-8");
    $root = $xml->createElement("Comprobante");
    $root = $xml->appendChild($root);
    cargaAtt($root, array("version" => "1.0", "serie" => $arr['serie'], "folio" => $arr['folio'], "fecha" => xml_fech($arr['fecha']), "sello" => "@", "noAprobacion" => $arr['noAprobacion']));
    // }}}
    // {{{ Datos del Emisor
    $emisor = $xml->createElement("Emisor");
    $emisor = $root->appendChild($emisor);
    cargaAtt($emisor, array("rfc" => $arr['Emisor']['rfc'], "nombre" => $arr['Emisor']['nombre']));
    $domfis = $xml->createElement("DomicilioFiscal");
    $domfis = $emisor->appendChild($domfis);
    cargaAtt($domfis, array("calle" => $arr['Emisor']['DomicilioFiscal']['calle'], "noExterior" => $arr['Emisor']['DomicilioFiscal']['noExterior'], "municipio" => $arr['Emisor']['DomicilioFiscal']['municipio'], "estado" => $arr['Emisor']['DomicilioFiscal']['estado'], "pais" => $arr['Emisor']['DomicilioFiscal']['pais'], "codigoPostal" => $arr['Emisor']['DomicilioFiscal']['codigoPostal']));
    // }}}
    // {{{ Datos del Receptor
    $receptor = $xml->createElement("Receptor");
    $receptor = $root->appendChild($receptor);
    cargaAtt($receptor, array("rfc" => $arr['Receptor']['rfc'], "nombre" => $arr['Receptor']['nombre']));
    $domicilio = $xml->createElement("Domicilio");
    $domicilio = $receptor->appendChild($domicilio);
    cargaAtt($domicilio, array("calle" => $arr['Receptor']['Domicilio']['calle'], "colonia" => $arr['Receptor']['Domicilio']['colonia'], "municipio" => $arr['Receptor']['Domicilio']['municipio'], "estado" => $arr['Receptor']['Domicilio']['estado'], "pais" => $arr['Receptor']['Domicilio']['pais']));
    // }}}
    // {{{ Detalle de los conceptos/produtos de la factura
    $conceptos = $xml->createElement("Conceptos");
    $conceptos = $root->appendChild($conceptos);
    for ($i = 1; $i <= sizeof($arr['Conceptos']); $i++) {
        $concepto = $xml->createElement("Concepto");
        $concepto = $conceptos->appendChild($concepto);
        cargaAtt($concepto, array("cantidad" => $arr['Conceptos'][$i]['cantidad'], "descripcion" => $arr['Conceptos'][$i]['descripcion'], "valorUnitario" => $arr['Conceptos'][$i]['valorUnitario'], "importe" => $arr['Conceptos'][$i]['importe']));
    }
    // }}}
    // {{{ Impuesto (IVA)
    $impuestos = $xml->createElement("Impuestos");
    $impuestos = $root->appendChild($impuestos);
    if ($arr['Traslados']['importe'] != 0) {
        $traslados = $xml->createElement("Traslados");
        $traslados = $impuestos->appendChild($traslados);
        $traslado = $xml->createElement("Traslado");
        $traslado = $traslados->appendChild($traslado);
        cargaAtt($traslado, array("impuesto" => $arr['Traslados']['impuesto'], "importe" => $arr['Traslados']['importe']));
    }
    // }}}
    // {{{ Calculo de sello
    $cadena_original .= "|";
    // termina la cadena original con el doble ||
    $utf8 = utf8_encode($cadena_original);
    // la codififica en utf8
    // +-------------------------------------------------------------------------------+
    // | Por lo pronto uso una llave de pruebas generada con OpenSSL sera              |
    // |   proporcionada por el SAT al pedir los folios                                |
    // +-------------------------------------------------------------------------------+
    $sellos = array("XA" => array("certificado" => "00001000000000255445", "aprobacion" => 107, "nombre" => "xal"), "AC" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "aca"), "AG" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "ags"), "CH" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "chi"), "CO" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "cor"), "CU" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "cul"), "DG" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "dgo"), "GD" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "gda"), "HE" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "her"), "IR" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "ira"), "ME" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "mer"), "MX" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "mxi"), "MY" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "mty"), "MO" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "mor"), "OA" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "oax"), "TA" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "tap"), "TU" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "tux"), "AL" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "tam"), "VI" => array("certificado" => "00001000000000255444", "aprobacion" => 107, "nombre" => "vil"));
    $indi = substr($arr['serie'], 0, 2);
    $certificado = $sellos[$indi]['certificado'];
    $aprobacion = $sellos[$indi]['aprobacion'];
    $bode = $sellos[$indi]['nombre'];
    $bode = "AAA010101AAA";
    // Ahora que use 'siempre' el certificado de pruebas del SAT
    $certificado = "00001000000000000114";
    // POr lo pronto el numero de certificado es el de pruebas
    // Otros certificados de pruebas
    $bode = "13";
    // Ahora que use 'siempre' el certificado de pruebas del SAT
    $certificado = "00001000000000000113";
    // POr lo pronto el numero de certificado es el de pruebas
    $file = "/home/httpd/sat/{$bode}.key.pem";
    // Hay una llave (sello) por cada localidad
    $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("file", "/tmp/open.log", "a"));
    $cmd = "openssl dgst -md5 -sign {$file}";
    $process = proc_open($cmd, $descriptorspec, $pipes);
    if (is_resource($process)) {
        fwrite($pipes[0], $utf8);
        // Mande la cadena original en utf-8 al comando openssl
        fclose($pipes[0]);
        $crypttext = stream_get_contents($pipes[1]);
        // Le el sello
        fclose($pipes[1]);
        proc_close($process);
    }
    $sello = base64_encode($crypttext);
    // lo codifica en formato base64
    $root->setAttribute("sello", $sello);
    $root->setAttribute("noCertificado", $certificado);
    // }}}
    // {{{ Addenda si se requiere
    if ($edidata) {
        $Addenda = $xml->createElement("Addenda");
        $Addenda = $root->appendChild($Addenda);
        if (substr($edidata, 0, 5) == "<?xml") {
            // Es XML por ejemplo Soriana
            $smp = simplexml_load_string($edidata);
            $Documento = dom_import_simplexml($smp);
            $Documento = $xml->importNode($Documento, true);
        } else {
            if ($nodo == "") {
                // Va el EDIDATA directo sin nodo adiconal. por ejemplo Corvi
                $Documento = $xml->createTextNode(utf8_encode($edidata));
            } else {
                // Va el EDIDATA dentro de un nodo. por ejemplo Walmart
                $Documento = $xml->createElement($nodo, utf8_encode($edidata));
            }
        }
        $Documento = $Addenda->appendChild($Documento);
    }
    // }}}
    // {{{ Genera un archivo de texto con el mensaje XML + EDI
    $xml->formatOutput = false;
    $xml->save($dir . $nufa . ".xml");
    // }}}
    // {{{ Guarda el mensaje XML y la cadena original en una tabla del ERP para su procesamiento  posterior
    $conn->replace("cfdsello", array("selldocu" => $nufa), "selldocu", true);
    $where = " selldocu = '{$nufa}'";
    $conn->UpdateBlob("cfdsello", "sellcade", $utf8, $where, 'TEXT');
    $todo = $xml->saveXML();
    $conn->UpdateBlob("cfdsello", "sellxml", $todo, $where, 'TEXT');
    //$conn->execute("update cfdsello set sellcade = '$utf8', sellxml = '$todo' where $where");
    // }}}
    return $todo;
}