IMPORT os IMPORT com IMPORT XML IMPORT UTIL DEFINE url_semilla, url_validasemilla,url_anulacion, url_recepcion,url_consulta,url_consulta_timbre STRING DEFINE codigo,tokenxml,nombreFile,filexml,token,respuesta,ruta_firmados STRING DEFINE doc xml.DomDocument, xfacturainterna,gsucid,gbodega INT, goperacion VARCHAR(30) FUNCTION procesoEncf(fileporfirmar,ambiente,tiporecepcion,xsucid,xbodega,xoperacion) DEFINE fileporfirmar,rtoken,ambiente,tiporecepcion STRING, xhash VARCHAR(6),xfechafirmadigital VARCHAR(50), xsucid,xbodega INT, xoperacion CHAR(30) # LET ptipoRecepcion = tiporecepcion LET ruta_firmados = fgl_getenv("RUTA_XML_FIRMADOS") IF ambiente <> "certificacion" THEN IF ambiente <> "test" THEN LET respuesta = "no llego bien ",ambiente RETURN ' ',respuesta END IF END IF # LET xambiente = ambiente CALL urls(ambiente,tiporecepcion) CALL buscatoken() RETURNING codigo, tokenxml IF codigo <> "200" THEN LET respuesta = "respuesta buscatoken: ",tokenxml," ",codigo RETURN ' ',respuesta END IF LET gsucid = xsucid LET gbodega = xbodega LET goperacion = xoperacion # Create DomDocument object LET doc = xml.DomDocument.Create() # Notice that whitespaces are significant in cryptography, # therefore it is recommended to remove unnecessary ones CALL doc.setFeature("whitespace-in-element-content",FALSE) CALL doc.loadFromString(tokenxml) CALL doc.save(".\\filesXML\\marmotech\\mtechTokenString.xml") #FIRMA SEMILLA IF os.Path.exists(".\\filesXML\\marmotech\\mtechTokenString.xml") THEN CALL firmasemilla() ELSE LET respuesta = "NO PUDE CREAR SEMILLA" RETURN ' ',respuesta END IF IF os.Path.exists(".\\filesXML\\marmotech\\mtechSignature.xml") THEN CALL validasemilla() RETURNING codigo,respuesta ELSE LET respuesta = "NO ENCONTRE LA SEMILLA FIRMADA" RETURN ' ',respuesta END IF IF respuesta IS NOT NULL THEN LET doc = xml.DomDocument.Create() CALL doc.loadFromString(respuesta) CALL doc.save(".\\filesXMl\\marmotech\\RespuestaValida.xml") CALL gettoken() RETURNING rtoken LET token = rtoken ELSE LET respuesta = "NO TENEMOS RESPUESTA DE VALIDA SEMILLA" RETURN ' ',respuesta END IF LET filexml = fileporfirmar CALL firmadocumento(fileporfirmar) LET filexml = ruta_firmados CLIPPED,os.Path.baseName(fileporfirmar) #DISPLAY "file a enviar :",filexml IF tiporecepcion <> 'anular' THEN CALL enviafiles(token,filexml) RETURNING codigo,respuesta END IF # IF goperacion <> 'modificar' THEN CALL gethash() RETURNING xhash,xfechafirmadigital,xfacturainterna # ELSE # SELECT a.hash,a.fechaFirmaDigital INTO xhash,xfechafirmadigital # FROM vetb00002 a WHERE a.factura = xfacturainterna AND a.sucid = gsucid # END IF # ACTUALIZA FACTURA RETURN xhash,respuesta END FUNCTION FUNCTION firmadocumento(fileafirmar) DEFINE doc xml.DomDocument DEFINE doc2 xml.DomDocument DEFINE root xml.DomNode DEFINE node xml.DomNode DEFINE signNode xml.DomNode DEFINE sig xml.Signature DEFINE key xml.CryptoKey DEFINE cert xml.CryptoX509 DEFINE index INTEGER, fileafirmar STRING # Create DomDocument object LET doc = xml.DomDocument.Create() # Notice that whitespaces are significant in cryptography, # therefore it is recommended to remove unnecessary ones CALL doc.setFeature("whitespace-in-element-content",FALSE) #DISPLAY "file ",fileafirmar LET filexml = fileafirmar CALL doc.load(fileafirmar) TRY # Create rsa key LET key = xml.CryptoKey.Create("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") CALL key.loadPEM(".\\cert\\marmotech\\onlyRSA.pem") # Create an X509 certificate with the constructor of the CryptoX509 class. LET cert = xml.CryptoX509.Create() CALL cert.setFeature("X509Certificate",TRUE) # Load the X509 certificate associated to the RSA or DSA private key into the CryptoKey object. # CALL cert.loadPEM("cert509.crt") CALL cert.loadPEM(".\\cert\\marmotech\\onlyCert.pem") # Create signature object with the key to use LET sig = xml.Signature.Create() # Assign the CryptoKey object to the Signature object. CALL sig.setKey(KEY) # Assign the CryptoX509 object to the Signature object. CALL sig.setCertificate(cert) # Set XML node to be signed. In our case, the entire document # LET index = sig.createReference("", # "http://www.w3.org/2001/04/xmlenc#sha256") LET index = sig.createReference('""', "http://www.w3.org/2001/04/xmlenc#sha256") # Add enveloped method to not take the XML signature node into account # when computing the entire document. CALL sig.appendReferenceTransformation(index, "http://www.w3.org/2000/09/xmldsig#enveloped-signature",doc.getDocumentElement()) # Set canonicalization method on the XML fragment to be signed. # Compute enveloped signature CALL sig.compute(doc) # Retrieve signature document LET doc2=sig.getDocument() # Append the signature node to the original document to get # a valid enveloped signature # Notice that the enveloped signature can be added anywhere in the # original document LET signNode = doc2.getDocumentElement() # Get Signature node # Import it into the original document LET node = doc.importNode(signNode,true) # Retrieve the original document root node LET root = doc.getDocumentElement() # Append the signature node as last child of the original document CALL root.appendChild(node) # Save document with enveloped signature back to disk CALL doc.setFeature("format-pretty-print",TRUE) LET fileafirmar = ruta_firmados CLIPPED,os.Path.baseName(fileafirmar) CALL doc.save(fileafirmar) CATCH DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm END TRY END FUNCTION FUNCTION firmasemilla() DEFINE doc xml.DomDocument DEFINE doc2 xml.DomDocument DEFINE root xml.DomNode DEFINE node xml.DomNode DEFINE signNode xml.DomNode DEFINE sig xml.Signature DEFINE key xml.CryptoKey DEFINE cert xml.CryptoX509 DEFINE index INTEGER # Create DomDocument object LET doc = xml.DomDocument.Create() # Notice that whitespaces are significant in cryptography, # therefore it is recommended to remove unnecessary ones CALL doc.setFeature("whitespace-in-element-content",FALSE) LET filexml = ".\\filesXML\\marmotech\\mtechTokenString.xml" IF os.Path.exists(filexml) THEN CALL doc.load(filexml) ELSE DISPLAY "NO LO ENCONTRE" RETURN END IF TRY # Create rsa key LET key = xml.CryptoKey.Create("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") CALL key.loadPEM(".\\cert\\marmotech\\onlyRSA.pem") # Create an X509 certificate with the constructor of the CryptoX509 class. LET cert = xml.CryptoX509.Create() CALL cert.setFeature("X509Certificate",TRUE) # Load the X509 certificate associated to the RSA or DSA private key into the CryptoKey object. # CALL cert.loadPEM("cert509.crt") CALL cert.loadPEM(".\\cert\\marmotech\\onlyCert.pem") # Create signature object with the key to use LET sig = xml.Signature.Create() # Assign the CryptoKey object to the Signature object. CALL sig.setKey(KEY) # Assign the CryptoX509 object to the Signature object. CALL sig.setCertificate(cert) # Set XML node to be signed. In our case, the entire document # LET index = sig.createReference("", # "http://www.w3.org/2001/04/xmlenc#sha256") LET index = sig.createReference('""', "http://www.w3.org/2001/04/xmlenc#sha256") # Add enveloped method to not take the XML signature node into account # when computing the entire document. CALL sig.appendReferenceTransformation(index, "http://www.w3.org/2000/09/xmldsig#enveloped-signature",doc.getDocumentElement()) # Set canonicalization method on the XML fragment to be signed. # CALL sig.appendReferenceTransformation(index, # "http://www.w3.org/2001/10/xml-exc-c14n#") # Compute enveloped signature CALL sig.compute(doc) # Retrieve signature document LET doc2=sig.getDocument() # Append the signature node to the original document to get # a valid enveloped signature # Notice that the enveloped signature can be added anywhere in the # original document LET signNode = doc2.getDocumentElement() # Get Signature node # Import it into the original document LET node = doc.importNode(signNode,true) # Retrieve the original document root node LET root = doc.getDocumentElement() # Append the signature node as last child of the original document CALL root.appendChild(node) # Save document with enveloped signature back to disk CALL doc.setFeature("format-pretty-print",TRUE) CALL doc.save(".\\filesXML\\marmotech\\mtechSignature.xml") CATCH DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm END TRY END FUNCTION FUNCTION validasemilla() DEFINE respuesta,codigo STRING, http_req com.HttpRequest, http_resp com.HTTPResponse LET http_req = com.HTTPRequest.Create(url_validasemilla) CALL http_req.setMethod("POST") CALL http_req.setCharset("UTF-8") CALL http_req.setHeader("accept","application/xml") CALL http_req.setMultipartType("form-data",NULL,NULL) IF os.Path.exists(".\\filesXML\\marmotech\\mtechSignature.xml") THEN CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"naceSignature.xml\"") CALL http_req.doFileRequest(".\\filesXML\\marmotech\\mtechSignature.xml") ELSE DISPLAY "NO LO ENCUENTRO" RETURN 0,"FILE NO EXISTE" END IF # CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"naceSignature.xml\"") # CALL http_req.doFileRequest("naceSignature.xml") LET http_resp= http_req.getResponse() LET codigo = http_resp.getStatusCode() LET respuesta = http_resp.getTextResponse() IF http_resp.getStatusCode() != 200 THEN # DISPLAY "error: ",codigo," ", respuesta RETURN codigo, respuesta END IF # DISPLAY "valida semilla: ",codigo," ", respuesta RETURN codigo, respuesta END FUNCTION FUNCTION enviafiles(btoken,archivo) DEFINE respuesta,btoken,codigo,archivo,contenido,consultaResp STRING, http_req com.HttpRequest, http_resp com.HTTPResponse, xresp RECORD codigo,estado,mensajes,encf,secuenciaUtilizada STRING END RECORD LET btoken =" Bearer ",btoken LET http_req = com.HTTPRequest.Create(url_recepcion) CALL http_req.setMethod("POST") CALL http_req.setCharset("UTF-8") CALL http_req.setHeader("accept","application/json") CALL http_req.setHeader("Authorization",btoken) CALL http_req.setMultipartType("form-data",NULL,NULL) # "form-data; name=\"xml\"; filename=\"naceSignature.xml\"" IF os.Path.exists(archivo) THEN DISPLAY "archivo a enviar: ",archivo," url ",url_recepcion LET contenido = "form-data; name=\"xml\"; filename=",os.path.basename(archivo) # DISPLAY "contenido: ",contenido # CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"131880681E310000000001.xml\"") CALL http_req.setHeader("Content-Disposition", contenido CLIPPED) CALL http_req.doFileRequest(archivo) LET http_resp= http_req.getResponse() LET codigo = http_resp.getStatusCode() LET respuesta= http_resp.getTextResponse() IF http_resp.getStatusCode() != 200 THEN DISPLAY "error: ",codigo," ", respuesta RETURN codigo, respuesta END IF ELSE RETURN 0,"FILE NO EXISTE" END IF # CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"naceSignature.xml\"") # CALL http_req.doFileRequest("naceSignature.xml") DISPLAY "envia respuesta: ", respuesta.trimWhiteSpace() CALL util.JSON.parse(respuesta,xresp) CALL consultaResultado(btoken,respuesta) RETURNING consultaResp DISPLAY "responde consulta: ",consultaresp," ",xfacturainterna RETURN codigo, respuesta END FUNCTION FUNCTION consultaResultado(ctoken,data) DEFINE data,ctoken,mensaje_dgii STRING DEFINE crespuesta STRING, http_req com.HttpRequest, http_resp com.HTTPResponse DEFINE dtrackid RECORD trackId,error,mensaje STRING END RECORD CALL util.JSON.parse(data,dtrackid) DISPLAY "TRACK: ",data #SELECT a.urltoken INTO url FROM companias a #"https://ecf.dgii.gov.do/testecf/autenticacion/api/autenticacion/semilla" #"https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/Semilla" LET url_consulta = url_consulta CLIPPED,"?TrackId=",dtrackid.trackid CLIPPED LET http_req = com.HTTPRequest.Create(url_consulta) CALL http_req.setMethod("GET") CALL http_req.setCharset("UTF-8") CALL http_req.setConnectionTimeOut(10) CALL http_req.setHeader("accept","application/json") CALL http_req.setHeader("Authorization",ctoken) CALL http_req.doRequest() LET http_resp= http_req.getResponse() LET crespuesta = http_resp.getTextResponse() LET mensaje_dgii = "Trackid: ", dtrackid.trackid CLIPPED," respuesta: ",crespuesta # DISPLAY BY NAME mensaje_dgii RETURN crespuesta END FUNCTION FUNCTION gettoken() DEFINE i, l INTEGER DEFINE r om.XmlReader DEFINE e,tok String DEFINE a om.SaxAttributes # DISPLAY "filexml: ",filexml LET r = om.XmlReader.createFileReader(".\\filesXMl\\marmotech\\RespuestaValida.xml") LET l = 0 LET e = r.read() WHILE e IS NOT NULL CASE e WHEN "StartDocument" # DISPLAY "StartDocument:" WHEN "StartElement" LET l=l+1 #DISPLAY l SPACES, "StartElement:", r.getTagName() LET a = r.getAttributes() FOR i=1 to a.getLength() IF a.getName(i) = "token" THEN # DISPLAY l SPACES," ", # a.getName(i)," = ", # a.getValueByIndex(i) END IF END FOR WHEN "Characters" IF r.getTagName() = "token" THEN LET tok = r.getCharacters() # DISPLAY "token dentro de gettoken: ",tok EXIT CASE END IF WHEN "SkippedEntity" # DISPLAY "Entity:'",r.skippedEntity(),"'" WHEN "EndElement" # DISPLAY l SPACES, "EndElement:", r.getTagName() LET l=l-1 WHEN "EndDocument" # DISPLAY "EndDocument:" OTHERWISE # DISPLAY "Invalid event: ",e END CASE LET e=r.read() END WHILE RETURN tok END FUNCTION FUNCTION gethash() DEFINE i, l INTEGER DEFINE r om.XmlReader DEFINE e,tok STRING, phash VARCHAR(6), pfechafirmadigital VARCHAR(50), facturainterna INT DEFINE a om.SaxAttributes DISPLAY "filexml: ",filexml LET r = om.XmlReader.createFileReader(filexml) LET l = 0 LET e = r.read() WHILE e IS NOT NULL CASE e WHEN "StartDocument" # DISPLAY "StartDocument:" WHEN "StartElement" LET l=l+1 #DISPLAY l SPACES, "StartElement:", r.getTagName() LET a = r.getAttributes() FOR i=1 to a.getLength() IF a.getName(i) = "SignatureValue" THEN # DISPLAY l SPACES," ", # a.getName(i)," = ", # a.getValueByIndex(i) END IF END FOR WHEN "Characters" IF r.getTagName() = "SignatureValue" THEN LET phash = r.getCharacters() # DISPLAY "token dentro de gettoken: ",tok EXIT CASE END IF IF r.getTagName() = "FechaHoraFirma" THEN LET pfechafirmadigital = r.getCharacters() # DISPLAY "token dentro de gettoken: ",tok EXIT CASE END IF IF r.getTagName() = "NumeroFacturaInterna" THEN LET facturainterna = r.getCharacters() DISPLAY "factura interna: ",facturainterna EXIT CASE END IF WHEN "SkippedEntity" # DISPLAY "Entity:'",r.skippedEntity(),"'" WHEN "EndElement" # DISPLAY l SPACES, "EndElement:", r.getTagName() LET l=l-1 WHEN "EndDocument" # DISPLAY "EndDocument:" OTHERWISE # DISPLAY "Invalid event: ",e END CASE LET e=r.read() END WHILE RETURN phash,pfechafirmadigital,facturainterna END FUNCTION FUNCTION buscatoken() DEFINE respuesta STRING, http_req com.HttpRequest, http_resp com.HTTPResponse #SELECT a.urltoken INTO url FROM companias a #"https://ecf.dgii.gov.do/testecf/autenticacion/api/autenticacion/semilla" #"https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/Semilla" LET http_req = com.HTTPRequest.Create(url_semilla) CALL http_req.setMethod("GET") CALL http_req.setCharset("UTF-8") CALL http_req.setHeader("accept","application/xml") CALL http_req.doRequest() #CALL http_req.doTextRequest(url) LET http_resp= http_req.getResponse() IF http_resp.getStatusCode() != 200 THEN RETURN http_resp.getStatusCode(), http_resp.getTextResponse() END IF LET respuesta = http_resp.getTextResponse() RETURN http_resp.getStatusCode(),respuesta END FUNCTION FUNCTION urls(xambiente,ptipoRecepcion) DEFINE xambiente,ptipoRecepcion STRING IF xambiente = "produccion" THEN IF ptipoRecepcion = "normal" THEN LET url_recepcion ="https://ecf.dgii.gov.do/ecf/Recepcion/api/FacturasElectronicas" ELSE IF ptipoRecepcion = 'consumo' THEN LET url_recepcion ="https://fc.dgii.gov.do/ecf/RecepcionFC/api/Recepcion/ecf" END IF END IF IF ptipoRecepcion = 'normal32' THEN LET url_recepcion ="https://fc.dgii.gov.do/ecf/RecepcionFC/api/Recepcion/ecf" END IF LET url_semilla ="https://ecf.dgii.gov.do/ecf/autenticacion/api/autenticacion/semilla" LET url_validasemilla ="https://ecf.dgii.gov.do/ecf/Autenticacion/api/Autenticacion/ValidarSemilla" LET url_consulta = "https://ecf.dgii.gov.do/ecf/ConsultaResultado/api/consultas/estado" LET url_anulacion = "https://ecf.dgii.gov.do/eCF/anulacionrangos/api/operaciones/anularRango" END IF IF xambiente = "certificacion" THEN IF ptipoRecepcion = "normal" THEN LET url_recepcion ="https://ecf.dgii.gov.do/CerteCF/Recepcion/api/FacturasElectronicas" ELSE IF ptipoRecepcion = 'consumo' THEN LET url_recepcion ="https://fc.dgii.gov.do/testecf/RecepcionFC/api/Recepcion/ecf" END IF END IF IF ptipoRecepcion = 'normal32' THEN LET url_recepcion ="https://fc.dgii.gov.do/CerteCF/RecepcionFC/api/Recepcion/ecf" END IF LET url_semilla ="https://ecf.dgii.gov.do/CerteCF/autenticacion/api/autenticacion/semilla" LET url_validasemilla ="https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/ValidarSemilla" LET url_consulta = "https://ecf.dgii.gov.do/CerteCF/ConsultaResultado/api/consultas/estado" END IF IF xambiente = "test" THEN IF ptipoRecepcion = "normal" THEN LET url_recepcion ="https://ecf.dgii.gov.do/TesteCF/Recepcion/api/FacturasElectronicas" ELSE IF ptipoRecepcion = 'consumo' THEN LET url_recepcion ="https://fc.dgii.gov.do/TesteCF/RecepcionFC/api/Recepcion/ecf" END IF END IF IF ptipoRecepcion = 'normal32' THEN LET url_recepcion ="https://fc.dgii.gov.do/TesteCF/RecepcionFC/api/Recepcion/ecf" END IF LET url_semilla ="https://ecf.dgii.gov.do/TesteCF/autenticacion/api/autenticacion/semilla" LET url_validasemilla ="https://ecf.dgii.gov.do/TesteCF/Autenticacion/api/Autenticacion/ValidarSemilla" LET url_consulta = "https://ecf.dgii.gov.do/TesteCF/ConsultaResultado/api/consultas/estado" LET url_anulacion = "https://ecf.dgii.gov.do/TesteCF/anulacionrangos/api/operaciones/anularRango" END IF LET url_consulta_timbre ="https://ecf.dgii.gov.do/TesteCF/consultatimbre" DISPLAY url_recepcion TO act_url END FUNCTION