import os import com import xml import util TYPE tMensaje RECORD codigo STRING, valor STRING END RECORD TYPE tRespDGII RECORD codigo INTEGER, -- 1=OK, 2=Rechazado, etc. (cuando venga) estado STRING, -- "Aceptado" | "Rechazado" | etc. encf STRING, secuenciaUtilizada BOOLEAN, hash STRING, fechaFirmaDigital STRING, qrcodeurl STRING, trackId STRING, mensajes DYNAMIC ARRAY OF tMensaje END RECORD TYPE consultaRespuesta RECORD trackid, codigo, estado, rnc, encf, secuenciaUtilizada, fechaRecepcion STRING, mensajes DYNAMIC ARRAY OF tmensaje END RECORD TYPE dgiimensaje RECORD codigo,estado,ecf,secuenciaUtilizada STRING, mensajes DYNAMIC ARRAY OF tmensaje END RECORD DEFINE url_semilla, url_validasemilla,url_anulacion, url_recepcion,url_consulta,url_consulta_timbre STRING DEFINE codigo,tokenxml,nombreFile,filexml,token,respuesta,ruta_firmados,rutaSemilla,rutaCert STRING DEFINE doc xml.DomDocument, xfacturainterna,gsucid,gbodega INT, goperacion VARCHAR(30) FUNCTION procesoEncf(fileporfirmar,ambiente,tiporecepcion,xsucid,xbodega,xoperacion,krespuesta) DEFINE fileporfirmar,rtoken,ambiente,tiporecepcion,krespuesta STRING, xhash VARCHAR(6),xfechafirmadigital VARCHAR(50), xsucid,xbodega INT, xoperacion CHAR(30) DEFINE dtrackid RECORD trackId,error,mensaje STRING END RECORD, xfecha DATETIME YEAR TO minute CALL STARTLOG("procesoencf.txt") # LET ptipoRecepcion = tiporecepcion LET ruta_firmados = fgl_getenv("RUTA_XML_FIRMADOS") LET rutaSemilla = fgl_getenv("RUTA_SEMILLA") LET rutaCert = fgl_getenv("RUTA_CERT") IF ambiente <> "produccion" THEN IF ambiente <> "test" THEN LET respuesta = "no llego bien ",ambiente RETURN ' ',respuesta,'400' END IF END IF # LET xambiente = ambiente CALL urls(ambiente,tiporecepcion) { SELECT a.valor,a.fecha INTO rtoken,xfecha FROM token a DISPLAY "tiempos: ",xfecha," ",CURRENT HOUR TO MINUTE} # IF CURRENT HOUR TO MINUTE- xfecha > "0:44" THEN CALL buscatoken(url_semilla) RETURNING codigo, tokenxml IF codigo <> "200" THEN LET respuesta = "respuesta buscatoken: ",tokenxml," ",codigo RETURN ' ',respuesta,'400' 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") CALL doc.save(rutaSemilla||"/TokenString.xml") #FIRMA SEMILLA IF os.Path.exists(rutaSemilla||"/TokenString.xml") THEN CALL firmasemilla() ELSE LET respuesta = "NO PUDE CREAR SEMILLA" RETURN ' ',respuesta,'400' END IF IF os.Path.exists(rutaSemilla||"/Signature.xml") THEN CALL validasemilla(url_validasemilla) RETURNING codigo,respuesta IF codigo = 400 THEN RETURN ' ',respuesta,'400' END IF ELSE LET respuesta = "NO ENCONTRE LA SEMILLA FIRMADA" RETURN ' ',respuesta,'400' END IF IF respuesta IS NOT NULL THEN LET doc = xml.DomDocument.Create() CALL doc.loadFromString(respuesta) CALL doc.save(rutaSemilla||"/RespuestaValida.xml") CALL gettoken() RETURNING rtoken LET token = rtoken # UPDATE token SET valor = rtoken,fecha=getdate() ELSE LET respuesta = "NO TENEMOS RESPUESTA DE VALIDA SEMILLA" RETURN ' ',respuesta,'400' END IF # ELSE # DISPLAY "en validar semilla" # CALL validasemilla() RETURNING codigo,respuesta # IF codigo = 400 THEN # RETURN ' ',respuesta,'400' # END IF # END IF # CUANDO EL PROCESO NO ES FIRMAR EL DOCUMENTO IF xoperacion <> 'consultatrackid' AND xoperacion <> 'consultastatus' THEN LET filexml = fileporfirmar CALL firmadocumento(fileporfirmar) LET filexml = ruta_firmados CLIPPED,os.Path.baseName(fileporfirmar) #DISPLAY "file a enviar :",filexml CALL enviafiles(token,filexml) RETURNING codigo,respuesta CALL gethash(filexml) RETURNING xhash,xfechafirmadigital,xfacturainterna # UPDATE vetb00002 SET hash = xhash WHERE factura = xfacturainterna AND sucid = xsucid ELSE IF xoperacion = 'consultatrackid' THEN LET token = " Bearer ",token CALL consultaResultado(token,krespuesta) RETURNING codigo, respuesta END IF IF xoperacion = 'consultastatus' THEN LET token = " ApiKey ",token CALL obtenerStatus(token) END IF END IF RETURN xhash,respuesta,codigo 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 LET rutaCert = fgl_getenv("RUTA_CERT") LET ruta_firmados = fgl_getenv("RUTA_XML_FIRMADOS") # 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 = 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") CALL key.loadPEM(rutaCert clipped||"/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(rutaCert clipped||"/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 DISPLAY "aqui" 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 LET rutaSemilla = fgl_getenv("RUTA_SEMILLA") LET rutaCert = fgl_getenv("RUTA_CERT") # 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 = rutaSemilla||"/TokenString.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(rutaCert||"/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(rutaCert||"/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(rutaSemilla||"/Signature.xml") CATCH DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm END TRY END FUNCTION FUNCTION validasemilla(url_validasemilla1) DEFINE respuesta,codigo,url_validasemilla1 STRING, http_req com.HttpRequest, http_resp com.HTTPResponse LET rutaSemilla = fgl_getenv("RUTA_SEMILLA") LET http_req = com.HTTPRequest.Create(url_validasemilla1) 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) CALL http_req.setConnectionTimeOut(10) IF os.Path.exists(rutaSemilla||"/Signature.xml") THEN # CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"naceSignature.xml\"") CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"Signature.xml\"") # TRY CALL http_req.doFileRequest(rutaSemilla||"/Signature.xml") # CATCH -- Intentar obtener la # RETURN 400, "NO OBTUVE RESPUESTA DEL SERICIO AL VALIDAR SEMILLA" # END TRY -- Continuar con la ejecución normal si no se produjo una excepción LET http_resp = http_req.getResponse() LET codigo = http_resp.getStatusCode() LET respuesta = http_resp.getTextResponse() ELSE LET codigo=400 LET respuesta='NO ENCONTRE EL FILE PARA VALIDAR SEMILLA' END IF RETURN codigo, respuesta END FUNCTION FUNCTION enviafiles(btoken,archivo) DEFINE respuesta,btoken,codigo,archivo,contenido,consultaResp,body STRING, http_req com.HttpRequest, http_resp com.HTTPResponse, xresp RECORD codigo,estado,mensajes,encf,secuenciaUtilizada STRING END RECORD DEFINE api tRespDGII DEFINE r RECORD codigo INTEGER, estado STRING, mensajes DYNAMIC ARRAY OF RECORD codigo STRING, valor STRING END RECORD, encf STRING, secuenciaUtilizada BOOLEAN, hash STRING, fechaFirmaDigital STRING, qrcodeurl STRING, trackId STRING END RECORD DEFINE dummy INTEGER DEFINE drespuesta consultaRespuesta DEFINE otrosMensajes dgiimensaje LET btoken =" Bearer ",btoken DISPLAY "url: ",url_recepcion 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.setConnectionTimeOut(10) CALL http_req.setMultipartType("form-data",NULL,NULL) # "form-data; name=\"xml\"; filename=\"naceSignature.xml\"" IF os.Path.exists(archivo) THEN 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 body = http_resp.getTextResponse() DISPLAY "respuesta body: ",body LET codigo = http_resp.getStatusCode() CALL parse_dgii_response(body) RETURNING api.* DISPLAY "despues de parse_dgii_response: ",api.* IF api.estado IS NULL OR api.estado = "" THEN IF api.mensajes[1].codigo IS NOT NULL AND api.mensajes.getLength() > 0 THEN LET api.estado = "Rechazado" IF api.codigo IS NULL THEN LET api.codigo = 2 END IF # ELSE # LET api.estado = "Procesando" END IF END IF IF http_resp.getStatusCode() != 200 THEN RETURN http_resp.getStatusCode(), util.JSON.stringify(api) END IF IF (api.hash IS NULL OR api.hash = "") OR (api.qrcodeurl IS NULL OR api.qrcodeurl = "") THEN TRY CALL util.JSON.parse(body,otrosMensajes) LET api.codigo = otrosmensajes.codigo LET api.encf = otrosmensajes.ecf LET api.estado = otrosmensajes.estado LET api.secuenciaUtilizada = otrosmensajes.secuenciaUtilizada LET api.mensajes = otrosmensajes.mensajes CATCH CALL consultaResultado(btoken, util.JSON.stringify(api)) RETURNING dummy, consultaResp TRY CALL UTIL.JSON.parse(consultaResp,drespuesta) CATCH END TRY LET api.codigo = drespuesta.codigo LET api.encf = drespuesta.encf LET api.estado = drespuesta.estado LET api.fechaFirmaDigital = drespuesta.fechaRecepcion LET api.trackId = drespuesta.trackid LET api.secuenciaUtilizada = drespuesta.secuenciaUtilizada IF dummy = 200 AND consultaResp <> "" THEN RETURN 200, util.JSON.stringify(api) END IF END TRY END IF ELSE LET api.codigo=401 LET api.estado = "INPROG" LET api.mensajes[1].valor='NO ENCOENTRE EL FILE A ENVIAR' RETURN 401, util.JSON.stringify(api) END IF RETURN http_resp.getStatusCode(), util.JSON.stringify(api) END FUNCTION FUNCTION consultaResultado(ctoken,data) DEFINE data,ctoken,mensaje_dgii,message_err STRING DEFINE crespuesta STRING, http_req com.HttpRequest, http_resp com.HTTPResponse DEFINE dtrackid RECORD trackId,error,mensaje STRING END RECORD DISPLAY "consultatrackid: ",ctoken," || ",data TRY CALL util.JSON.parse(data,dtrackid) CATCH LET message_Err ='Error EN JSON CONSULTA RESULTADO: ',STATUS CALL errorlog(message_Err) END TRY 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) TRY CALL http_req.doRequest() LET http_resp= http_req.getResponse() LET crespuesta = http_resp.getTextResponse() LET mensaje_dgii = "Trackid: ", dtrackid.trackid CLIPPED," respuesta: ",crespuesta, " code: ",http_resp.getStatusCode() CATCH LET crespuesta = 'Servicio no responde, no consulta' RETURN 400,crespuesta END TRY RETURN http_resp.getStatusCode(),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(rutaSemilla||"/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(envfile) DEFINE i, l INTEGER DEFINE r om.XmlReader DEFINE e,envfile STRING, phash VARCHAR(6), pfechafirmadigital VARCHAR(50), facturainterna INT DEFINE a om.SaxAttributes LET r = om.XmlReader.createFileReader(envfile) 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 LET phash = r.getCharacters() # 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() 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(url_semilla1) DEFINE respuesta,url_semilla1 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_semilla1) CALL http_req.setMethod("GET") CALL http_req.setCharset("UTF-8") CALL http_req.setHeader("accept","application/xml") # CALL http_req.setConnectionTimeOut(10) # TRY CALL http_req.doRequest() LET http_resp= http_req.getResponse() LET respuesta = http_resp.getTextResponse() # CATCH # LET respuesta = 'No pude conseguir el token' # RETURN 400,respuesta # END TRY #DISPLAY "cod token ",http_resp.getTextResponse()," ",http_resp.getStatusCode() # IF http_resp.getStatusCode() != 200 THEN # RETURN http_resp.getStatusCode(), http_resp.getTextResponse() # END IF DISPLAY "busca token: ",respuesta 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://ecf.dgii.gov.do/ecf/Recepcion/api/FacturasElectronicas" 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" IF ptipoRecepcion = 'anular' THEN LET url_recepcion = url_anulacion END IF 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://ecf.dgii.gov.do/CerteCF/Recepcion/api/FacturasElectronicas" 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 IF ptipoRecepcion = 'anular' THEN LET url_Recepcion = "https://ecf.dgii.gov.do/TesteCF/anulacionrangos/api/operaciones/anularRango" 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 FUNCTION obtenerStatus(ctoken) DEFINE respuesta,btoken,codigo,archivo,contenido,consultaResp,ctoken STRING, http_req com.HttpRequest, http_resp com.HTTPResponse, xresp RECORD codigo,estado,mensajes,encf,secuenciaUtilizada STRING END RECORD LET http_req = com.HttpRequest.Create("https://statusecf.dgii.gov.do/api/estatusservicios/obtenerestatus") 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 respuesta = http_resp.getTextResponse() LET codigo = http_resp.getStatusCode() END FUNCTION FUNCTION parse_dgii_response(raw STRING) DEFINE s STRING, resp tRespDGII DEFINE w RECORD data1 tRespDGII END RECORD -- Último intento: levantar sólo los campos conocidos si vienen sueltos DEFINE m RECORD codigo INTEGER, estado STRING, encf STRING, hash STRING, qrcodeurl STRING, fechaFirmaDigital STRING END RECORD LET s = raw.trim() IF s IS NULL OR s = "" THEN RETURN resp.* END IF -- Si la raíz es un arreglo, envuélvelo para mapearlo a RESP.mensajes IF s.subString(1,1) = "[" THEN LET s = '{"mensajes":' || s || '}' END IF TRY CALL util.JSON.parse(s, resp) RETURN resp.* CATCH -- Algunos endpoints devuelven dentro de "data1" u otro contenedor. TRY CALL util.JSON.parse(s, w) LET resp = w.data1 RETURN resp.* CATCH TRY CALL util.JSON.parse(s, m) LET resp.codigo = m.codigo LET resp.estado = m.estado LET resp.encf = m.encf LET resp.hash = m.hash LET resp.qrcodeurl = m.qrcodeurl LET resp.fechaFirmaDigital = m.fechaFirmaDigital RETURN resp.* CATCH -- Si nada funcionó, deja 'resp' vacío: que el llamador trate el raw RETURN resp.* END TRY END TRY END TRY END FUNCTION