Commit inicial: fuentes MBS ERP (Genero 6) + .gitignore + docs/SETUP_PC_MBS.md

This commit is contained in:
2026-08-18 20:59:52 -04:00
commit 454973e269
5978 changed files with 2664094 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
IMPORT com
IMPORT XML
FUNCTION aprobacion(req)
DEFINE req com.HttpServiceRequest
DEFINE doc xml.DomDocument,
archivo string
WHENEVER ERROR CONTINUE
LET doc = xml.DomDocument.Create()
CALL doc.setFeature("whitespace-in-element-content",FALSE)
LET doc = req.readXmlRequest()
IF STATUS = 0 THEN
CALL doc.save("acuserecibido.xml")
RETURN 200, "Satisfactorio"
ELSE
RETURN 400,"Insatisfactorio"
END IF
DISPLAY "filexml ",archivo
END FUNCTION
+51
View File
@@ -0,0 +1,51 @@
IMPORT com
IMPORT FGL recepcion
IMPORT FGL r_aprobar
IMPORT FGL recepcionget
MAIN
DEFINE ret INTEGER
DEFER INTERRUPT
CALL com.WebServiceEngine.RegisterRestService("recepcionget", "recepcion")
#CALL com.WebServiceEngine.RegisterRestService("recepcion", "recepcion")
# CALL com.WebServiceEngine.RegisterRestService("r_aprobar", "aprobacioncomercial")
DISPLAY "Server started"
CALL com.WebServiceEngine.Start()
WHILE TRUE
LET ret = com.WebServiceEngine.ProcessServices(-1)
CASE ret
WHEN 0
DISPLAY "Request processed."
WHEN -1
DISPLAY "Timeout reached."
WHEN -2
DISPLAY "Disconnected from application server."
EXIT PROGRAM # The Application server has closed the connection
WHEN -3
DISPLAY "Client Connection lost."
WHEN -4
DISPLAY "Server interrupted with Ctrl-C."
WHEN -9
DISPLAY "Unsupported operation."
WHEN -10
DISPLAY "Internal server error."
WHEN -23
DISPLAY "Deserialization error."
WHEN -35
DISPLAY "No such REST operation found."
WHEN -36
DISPLAY "Missing REST parameter."
OTHERWISE
DISPLAY "Unexpected server error " || ret || "."
EXIT WHILE
END CASE
IF int_flag<>0 THEN
LET int_flag=0
EXIT WHILE
END IF
END WHILE
DISPLAY "Server stopped"
END MAIN
+14
View File
@@ -0,0 +1,14 @@
IMPORT os
PUBLIC FUNCTION recepcion( fname STRING ATTRIBUTES(WSAttachment, WSMedia="text/xml") )
ATTRIBUTES (WSPost,
WSPath="/api/ecf")
RETURNS STRING ATTRIBUTE(WSMedia="text/plain")
DEFINE ret, new_fname STRING
DEFINE ok INTEGER
LET new_fname = os.Path.pwd()||os.Path.separator()||new_fname
LET ok = os.Path.rename(fname,new_fname)
LET ret = SFMT("Got file: %1",new_fname)
RETURN ret
END FUNCTION
+9
View File
@@ -0,0 +1,9 @@
PUBLIC FUNCTION recepcionget()
ATTRIBUTES(WSGet,
WSPath="/api/ecf",
WSDescription="Get de Recepcoon")
RETURNS INTEGER
DEFINE cnt INTEGER
RETURN 200
END FUNCTION
+501
View File
@@ -0,0 +1,501 @@
IMPORT util
IMPORT com
IMPORT os
IMPORT security
IMPORT XML
CONSTANT dpy_verb=TRUE -- send messages to standard output
TYPE reqInfoTyp RECORD
method STRING,
ctype STRING, # check the Content-Type
informat STRING, # short word for Content Type
caccept STRING, # check which format the client accepts
outformat STRING, # short word for Accept
path STRING,
query STRING, # the query string
items DYNAMIC ARRAY OF RECORD
name STRING,
value STRING
END RECORD
END RECORD
DEFINE m_reqInfo reqInfoTyp
DEFINE doc xml.DomDocument
DEFINE url,msg,method,headers,mensaje,filexml,tipoecf,rnc_e,rnc_c,e_ncf,fileacuse,resp,
ruta_firmados,fileafirmar_f STRING,
tout, n, x,rcode INTEGER,
start_time DATETIME YEAR TO SECOND
DEFINE d0 DATETIME YEAR TO SECOND
DEFINE a om.SaxAttributes
DEFINE out om.SaxDocumentHandler,
i INT,
fechaFirma DATETIME YEAR TO SECOND
MAIN
DEFINE ret INTEGER,
mensaje STRING
DEFINE req com.HTTPServiceRequest,
err RECORD
code INT,
DESC STRING
END RECORD
DEFER INTERRUPT
LET filexml = ".\\ArchRecibidos\\"
LET fileacuse = ".\\Acuses\\"
LET ruta_firmados = fgl_getenv("RUTA_XML_FIRMADOS")
# iNICIO SERVICIO SERVER
DISPLAY "Iniciando server..."
CALL com.WebServiceEngine.Start()
DISPLAY "The server is listening."
# Creacion del servidor
WHILE TRUE
TRY
LET req = com.WebServiceEngine.getHTTPServiceRequest(30)
# ... parse and process the request ...
CALL getReqInfo(req) RETURNING method,url
DISPLAY "metodo2 ",method," url ",url
CASE method
WHEN "GET"
CALL req.sendTextResponse(200,"","API SERVER para los e-NCF")
EXIT WHILE
WHEN "POST"
IF url = "http://ecf.fulldetord.com/gas/ws/r/fe/aprobacioncomercial/api/ecf" OR
url = "https://ecf.fulldetord.com/gas/ws/r/fe/aprobacioncomercial/api/ecf" THEN
LET ret = NULL
DISPLAY "metodo2 ",method," ",url
CALL aprobacion(req) RETURNING ret,mensaje
IF ret <> 200 THEN
LET ret = 400
# LET mensaje = "Invalido"
CALL req.sendTextResponse(ret,"",mensaje)
DISPLAY "enviar respuesta ",ret," ",url
ELSE
LET ret = 200
# LET mensaje="Valido"
CALL req.sendTextResponse(ret,"",mensaje)
END IF
END IF
EXIT CASE
OTHERWISE
LET err.code = -3
LET err.desc = mensaje
CALL req.sendTextResponse(400,"OK","Unknown request:\n" || url || "\n" || method)
END CASE
{ CATCH
LET ret = status
CASE ret
WHEN -15565
DISPLAY "Server process has been stopped by Ctrl-C"
WHEN -15575
DISPLAY "Server process has been disconnected by the GAS"
OTHERWISE
DISPLAY "[ERROR] " || ret
EXIT WHILE
END CASE
IF int_flag<>0 THEN
LET int_flag = 0
EXIT WHILE
END IF
}
END TRY
END WHILE
END MAIN
FUNCTION getReqInfo(req)
DEFINE req com.HTTPServiceRequest
DEFINE str, val base.StringTokenizer
DEFINE token,mensaje STRING
DEFINE i,rcode INT
INITIALIZE m_reqInfo TO NULL
LET m_reqInfo.ctype = getHeaderByName(req,"Content-Type")
IF m_reqInfo.ctype.getIndexOf("/xml",1) THEN
LET m_reqInfo.informat = "XML"
ELSE
LET m_reqInfo.informat = "JSON"
END IF
LET m_reqInfo.caccept = getHeaderByName(req,"accept")
IF m_reqInfo.caccept.getIndexOf("/xml",1) THEN
LET m_reqInfo.outformat = "XML"
ELSE
LET m_reqInfo.outformat = "JSON"
END IF
LET m_reqInfo.method = req.getMethod()
CALL parseUrl(req.getUrl()) RETURNING m_reqInfo.path, m_reqInfo.query
LET str = base.StringTokenizer.create(m_reqInfo.query,"&")
LET i=1
CALL m_reqInfo.items.clear()
WHILE str.hasMoreTokens()
LET token = str.nextToken()
LET val = base.StringTokenizer.create(token,"=")
IF val.hasMoreTokens() THEN LET m_reqInfo.items[i].name = val.nextToken() END IF
IF val.hasMoreTokens() THEN LET m_reqInfo.items[i].value = val.nextToken() END IF
LET i=i+1
END WHILE
RETURN m_reqInfo.method,m_reqInfo.path
END FUNCTION
FUNCTION parseUrl(url)
DEFINE url STRING
DEFINE i INT
LET i = url.getIndexOf("?",1)
IF i = 0 THEN
RETURN url, NULL
ELSE
RETURN url.subString(1,i), url.subString(i+1,url.getLength())
END IF
END FUNCTION
FUNCTION getHeaderByName(areq,hname)
DEFINE areq com.HTTPServiceRequest
DEFINE hname STRING
DEFINE aname STRING
DEFINE iname STRING
DEFINE i INT
DEFINE n INT
LET aname = hname.toLowerCase()
LET n = areq.getRequestHeaderCount()
FOR i=1 TO n
LET iname = areq.getRequestHeaderName(i)
IF aname.equals(iname.toLowerCase()) THEN
RETURN areq.getRequestHeaderValue(i)
END IF
END FOR
RETURN NULL
END FUNCTION
PUBLIC FUNCTION recepcion()
DEFINE req com.HttpServiceRequest
CALL read_request(req) RETURNING rcode,resp
IF rcode <> "200" THEN
CALL req.sendTextResponse(501,NULL,"No pudimos procesar el file")
ELSE
LET doc = xml.DomDocument.Create()
CALL doc.setFeature("format-pretty-print",TRUE)
CALL doc.load(fileafirmar_f)
CALL req.sendXmlResponse(200,NULL,doc)
# CALL req.sendTextResponse(200,NULL,resp)
END IF
END FUNCTION
FUNCTION check_utf8()
IF ORD("€") == 8364 AND LENGTH("€") == 1 THEN
RETURN 0, NULL
ELSE
RETURN -1, "Application locale must be UTF-8, with char length semantics"
END IF
END FUNCTION
FUNCTION show_verb(msg)
DEFINE msg STRING
IF dpy_verb THEN
DISPLAY msg
END IF
# IF log_verb THEN
# CALL errorlog(msg CLIPPED)
# END IF
END FUNCTION
FUNCTION getxmldata()
DEFINE i, l INTEGER
DEFINE r om.XmlReader
DEFINE e,tok STRING,
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() = "TipoeCF" THEN
LET tipoecf = r.getCharacters()
EXIT CASE
END IF
IF r.getTagName() = "FechaHoraFirma" THEN
LET pfechafirmadigital = r.getCharacters()
EXIT CASE
END IF
IF r.getTagName() = "RNCEmisor" THEN
LET rnc_e = r.getCharacters()
EXIT CASE
END IF
IF r.getTagName() = "eNCF" THEN
LET e_ncf = r.getCharacters()
EXIT CASE
END IF
IF r.getTagName() = "RNCComprador" THEN
LET rnc_c = 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 read_request(req)
# DEFINE doc xml.DomDocument
DEFINE req com.HttpServiceRequest
DEFINE cmd,recibido,tmpfile STRING,
p RECORD
oper STRING,
data RECORD
usuario STRING,
clave STRING,
codigo STRING
END RECORD
END RECORD
INITIALIZE cmd TO NULL
LET cmd = req.readFileRequest()
DISPLAY "request: ",cmd
# LET cmd = "cp ",cmd CLIPPED," /home/fourjs/gas/appdata/services/mbs/bin/tmp/recibido.xml"
LET cmd = "copy ",cmd CLIPPED, " C:\\ProgramData\\FourJs\\gas\\3.20.06-201906131721\\services\\ecf\\tmp\\recibido.xml"
RUN cmd
# LET tmpfile = "/home/fourjs/gas/appdata/services/mbs/bin/tmp/recibido.xml"
LET tmpfile = ".\\tmp\\recibido.xml"
LET recibido = filexml CLIPPED,"recibido.xml"
LET filexml = recibido
# TRY
LET doc = xml.DomDocument.Create()
CALL doc.setFeature("whitespace-in-element-content",FALSE)
IF os.Path.exists(tmpfile) THEN
CALL doc.load(tmpfile)
CALL doc.save(recibido)
CALL getxmldata()
LET filexml = filexml CLIPPED,rnc_e CLIPPED,e_ncf CLIPPED,".xml"
CALL doc.save(filexml)
CALL formaracuse() RETURNING filexml
CALL firmadocumento(filexml)
CALL doc.load(fileafirmar_f)
LET cmd = doc.saveToString()
RETURN 200,cmd
ELSE
RETURN 401,"Falla en el proceso del file"
END IF
# CATCH
# CALL show_err(SFMT("Unexpected HTTP request read exception: %1", STATUS))
# RETURN FALSE
# END TRY
END FUNCTION
FUNCTION show_err(msg)
DEFINE msg STRING
DISPLAY "ERROR:",msg
# CALL errorlog(msg CLIPPED)
END FUNCTION
FUNCTION formaracuse()
DEFINE chFechaFirma STRING
LET fileacuse = fileacuse CLIPPED,"acuse",rnc_c CLIPPED,".xml"
LET out=om.XmlWriter.createFileWriter(fileacuse)
LET a=om.SaxAttributes.create()
CALL out.startDocument()
CALL a.addAttribute("xmlns:xs","http://www.w3.org/2001/XMLSchema")
CALL out.startElement("ARECF",a)
CALL a.clear()
CALL out.startElement("DetalleAcusedeRecibo",a)
CALL out.startElement("Version",a)
CALL out.characters("1.0")
CALL out.endElement("Version")
CALL out.startElement("RNCEmisor",a)
CALL out.characters(rnc_e)
CALL out.endElement("RNCEmisor")
CALL out.startElement("RNCComprador",a)
CALL out.characters(rnc_c)
CALL out.endElement("RNCComprador")
CALL out.startElement("eNCF",a)
CALL out.characters(e_ncf)
CALL out.endElement("eNCF")
CALL out.startElement("Estado",a)
CALL out.characters("0")
CALL out.endElement("Estado")
LET chFechaFirma = util.Datetime.format(CURRENT, "%d-%m-%Y %H:%M:%S" )
DISPLAY "FECHA ",chFechaFirma
CALL out.startElement("FechaHoraAcuseRecibo",a)
CALL out.characters(chFechaFirma)
CALL out.endElement("FechaHoraAcuseRecibo")
CALL out.endElement("DetalleAcusedeRecibo")
CALL out.endElement("ARECF")
CALL out.endDocument()
RETURN fileacuse
END FUNCTION
FUNCTION limpiatmp()
DISPLAY "BORRANDO XML FILES..."
RUN 'rm /tmp/*.xml'
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,
codsecure VARCHAR(6)
# 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("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.
# 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)
LET fileafirmar_f = fileafirmar
CATCH
DISPLAY "Unable to create an enveloped signature :",status," ",sqlca.sqlerrm
END TRY
END FUNCTION