Files
MBS/PROYECTO/webfirma/firmarsakey_cert.4gl
T

522 lines
17 KiB
Plaintext

IMPORT os
IMPORT com
IMPORT XML
IMPORT util
DEFINE token,tokenxml,filexml,ruta,url STRING
MAIN
DEFINE doc xml.DomDocument,
encabezado VARCHAR(100),
rtoken,destino,nombreFile,codigo,respuesta,certificadop12,clave,f_tipos,filepath,
dir_file,mensaje,d_tipos,tipogenera STRING,
i INT,
arrfiles DYNAMIC ARRAY OF STRING
LET encabezado = "SOLUCION FIRMA DIGITAL XML FILES"
call ui.Interface.loadStyles("formularios")
OPEN WINDOW w1 WITH FORM "webfirma"
INPUT BY NAME certificadop12,clave,tipogenera WITHOUT DEFAULTS
BEFORE INPUT
LET clave = "Nata1010"
DISPLAY BY NAME encabezado,clave
ON ACTION show_password
CALL toggle_password("formonly.clave")
ON ACTION abrircert
LET d_tipos="p12"
LET f_tipos="*.p12"
LET mensaje=%"Elige Documento"
CALL ui.Interface.frontCall("standard","openfile", [dir_file,d_tipos,f_tipos,mensaje], [filepath] )
LET certificadop12 = filepath
DISPLAY filepath TO certificadop12
AFTER INPUT
IF int_flag THEN
EXIT PROGRAM
END IF
IF tipogenera IS NULL THEN
DISPLAY "TIPO GENERACION EN BLANCO" TO mensaje
NEXT FIELD tipogenera
END IF
EXIT INPUT
END INPUT
CALL buscatoken() RETURNING codigo, tokenxml
IF codigo <> "200" THEN
# DISPLAY "respuesta: ",tokenxml," ",codigo
EXIT PROGRAM
END IF
# 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("naceTokenString.xml")
CALL firmasemilla()
CALL validasemilla() RETURNING codigo,respuesta
LET doc = xml.DomDocument.Create()
CALL doc.loadFromString(respuesta)
CALL doc.save("naceRespuestaValida.xml")
CALL gettoken() RETURNING rtoken
DISPLAY rtoken TO token
DISPLAY respuesta TO mensaje
#DISPLAY "respuesta del token: ",respuesta
LET token = rtoken
{
LET nombrefile = os.Path.baseName(certificadop12)
LET nombrefile = nombrefile CLIPPED
LET destino = ".\\net6.0\\",nombrefile CLIPPED
CALL fgl_getfile(certificadop12,destino)
}
# PARA FIRMA CON SOLUCION C#
# CALL generafirma("naceTokenString.xml",nombrefile,clave) RETURNING codigo,respuesta
# IF codigo = 400 THEN
# DISPLAY "RESPUESTA: ",respuesta
# EXIT PROGRAM
# END IF
IF tipogenera = 'FT' THEN
#FRIMA CON GENERO
LET ruta = ".\\filesxml\\originales\\"
LET arrfiles[1] = '130337391E310000000001.xml'
LET arrfiles[2] = '130337391E310000000002.xml'
LET arrfiles[3] = '130337391E310000000003.xml'
LET arrfiles[4] = '130337391E310000000004.xml'
LET arrfiles[5] = '130337391E310000000005.xml'
FOR i = 1 TO arrfiles.getLength()
LET filexml = arrfiles[i]
CALL firmadocumento()
DISPLAY "otro Token: ",token
LET filexml = ".\\filesxml\\firmados\\",arrfiles[i] CLIPPED
CALL enviafiles(token,filexml) RETURNING codigo,respuesta
LET doc = xml.DomDocument.Create()
# CALL doc.loadFromString(respuesta)
# CALL doc.save("fileRespuesta.xml")
# LET filexml = "fileRespuesta.xml"
END FOR
END IF
IF tipogenera = 'APC' THEN
LET url ="https://ecf.dgii.gov.do/CerteCF/AprobacionComercial/api/AprobacionComercial"
LET ruta = ".\\filesxml\\aprobaciones\\"
LET arrfiles[1] = '131880681E310000000001.xml'
LET arrfiles[2] = '131880681E310000000002.xml'
LET arrfiles[3] = '131880681E310000000003.xml'
LET arrfiles[4] = '131880681E310000000004.xml'
LET arrfiles[5] = '131880681E310000000005.xml'
LET arrfiles[6] = '131880681E330000000001.xml'
LET arrfiles[7] = '131880681E340000000001.xml'
LET arrfiles[8] = '131880681E440000000002.xml'
LET arrfiles[9] = '131880681E450000000001.xml'
FOR i = 1 TO 1
LET filexml = arrfiles[i]
CALL firmadocumento()
LET filexml = ".\\filesxml\\firmados\\",arrfiles[i] CLIPPED
DISPLAY "token antes de env: ",token
CALL enviafiles(token,filexml) RETURNING codigo,respuesta
END FOR
END IF
CALL fgl_winmessage("INFO","PROCESO TERMINADO","INFO")
CLOSE WINDOW w1
END MAIN
FUNCTION firmadocumento()
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,
respcode,respuesta,saxevent,filefirmado 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)
LET filexml =ruta clipped ,filexml CLIPPED
TRY
CALL doc.load(filexml)
# Create rsa key
LET key = xml.CryptoKey.Create("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")
CALL key.loadPEM("onlyRSA.pem")
# Create an X509 certificate with the constructor of the CryptoX509 class.
LET cert = xml.CryptoX509.Create()
CALL cert.setFeature("X509Certificate",TRUE)
CALL cert.loadPEM("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)
LET filefirmado =".\\filesxml\\firmados\\",os.Path.baseName(filexml)
DISPLAY "file firmado: ",filefirmado
CALL doc.save(filefirmado)
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,
respcode,respuesta,saxevent 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)
LET filexml = "naceTokenstring.xml"
CALL doc.load(filexml)
CALL doc.save(filexml)
TRY
# Create rsa key
LET key = xml.CryptoKey.Create("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")
CALL key.loadPEM("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("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("naceSignature.xml")
CATCH
DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm
END TRY
END FUNCTION
FUNCTION buscatoken()
DEFINE urltoken,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 urltoken = "https://ecf.dgii.gov.do/CerteCF/autenticacion/api/autenticacion/semilla"
LET http_req = com.HTTPRequest.Create(urltoken)
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 validasemilla()
DEFINE urlsemilla,respuesta,btoken,codigo STRING,
http_req com.HttpRequest,
http_resp com.HTTPResponse
LET urlsemilla ="https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/ValidarSemilla"
# "https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/ValidarSemilla"
#"https://ecf.dgii.gov.do/TesteCF/Autenticacion/api/Autenticacion/ValidarSemilla"
LET http_req = com.HTTPRequest.Create(urlsemilla)
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("naceSignature.xml") THEN
CALL http_req.setHeader("Content-Disposition", "form-data; name=\"xml\"; filename=\"naceSignature.xml\"")
CALL http_req.doFileRequest("naceSignature.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 STRING,
http_req com.HttpRequest,
http_resp com.HTTPResponse
LET btoken =" Bearer ",btoken
# LET url ="https://ecf.dgii.gov.do/CerteCF/Recepcion/api/FacturasElectronicas"
# "https://ecf.dgii.gov.do/CerteCF/Autenticacion/api/Autenticacion/ValidarSemilla"
#"https://ecf.dgii.gov.do/TesteCF/Autenticacion/api/Autenticacion/ValidarSemilla"
LET http_req = com.HTTPRequest.Create(url)
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: ",archivo
LET contenido = "form-data; name=\"xml\"; filename=\\",archivo CLIPPED,"\\"
# 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()
DISPLAY "respuesta: ",respuesta
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 "error: ",codigo," ", respuesta
RETURN codigo, respuesta
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("naceRespuestaValida.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 toggle_password(f)
DEFINE f STRING -- field name
DEFINE n om.domnode
DEFINE w ui.window
LET w = ui.window.getCurrent()
LET n = w.findNode ("FormField", f)
LET n = n.getFirstChild ()
CASE n.getAttribute("isPassword")
WHEN "0"
CALL n.setAttribute ("isPassword", "1")
WHEN "1"
CALL n.setAttribute ("isPassword", "0")
END CASE
END FUNCTION