Código: Selecionar todos
/* sefaz_tester.prg
Cliente de teste para SEFAZ Service API (FastAPI) em Harbour.
Não usa hbtip, hbssl, hbhttp, hbjson.
SOMENTE usa:
- RUN
- MemoRead / MemoWrit
- curl.exe
O curl está¡ presente no Windows 10/11.
*/
PROCEDURE Main()
LOCAL cBaseUrl := "http://127.0.0.1:8000"
LOCAL cXmlFile := "nfe_teste.xml"
LOCAL cOpt
DO WHILE .T.
CLS
? "=========================================="
? " SEFAZ SERVICE - CLIENTE DE TESTE"
? "=========================================="
? "Base URL atual : ", cBaseUrl
? "XML padrão : ", cXmlFile
?
? "[1] Validar Schema (/nfe/validar-schema)"
? "[2] XML Info (/nfe/xmlinfo)"
? "[3] Análise (/nfe/analise)"
? "[4] DANFE HTML (/danfe/html)"
? "[5] Status (/nfe/status)"
? "[6] Consulta Chave (/nfe/consulta)"
? "[7] Consulta GTIN (/nfe/gtin)"
? "-------------------------------------------"
? "[B] Alterar Base URL"
? "[X] Alterar XML padrão"
? "[0] Sair"
?
ACCEPT "Opção: " TO cOpt
cOpt := Upper(AllTrim(cOpt))
DO CASE
CASE cOpt == "1"
Test_ValidarSchema(cBaseUrl, @cXmlFile)
CASE cOpt == "2"
Test_XmlInfo(cBaseUrl, @cXmlFile)
CASE cOpt == "3"
Test_Analise(cBaseUrl, @cXmlFile)
CASE cOpt == "4"
Test_DanfeHtml(cBaseUrl, @cXmlFile)
CASE cOpt == "5"
Test_Status(cBaseUrl)
CASE cOpt == "6"
Test_ConsultaChave(cBaseUrl)
CASE cOpt == "7"
Test_Gtin(cBaseUrl)
CASE cOpt == "B"
cBaseUrl := Ask("Nova Base URL", cBaseUrl)
CASE cOpt == "X"
cXmlFile := Ask("Novo XML padrão", cXmlFile)
CASE cOpt == "0"
EXIT
ENDCASE
ENDDO
RETURN
/* ------------------------------------------
Helpers simples
--------------------------------------------- */
FUNCTION Ask(cPrompt, cDefault)
LOCAL cInp
ACCEPT cPrompt + " [" + cDefault + "]: " TO cInp
IF Empty(AllTrim(cInp))
RETURN cDefault
ENDIF
RETURN cInp
FUNCTION ReadFileOrEmpty(cFile)
IF File(cFile)
RETURN MemoRead(cFile)
ENDIF
? "Arquivo não encontrado:", cFile
RETURN ""
/* Escapa string para JSON */
FUNCTION JsonString(c)
LOCAL cOut := ""
LOCAL n, ch
cOut := '"'
FOR n := 1 TO Len(c)
ch := SubStr(c, n, 1)
DO CASE
CASE ch == '"'
cOut += '\"'
CASE ch == '\'
cOut += '\\'
CASE ch == Chr(13)
cOut += '\r'
CASE ch == Chr(10)
cOut += '\n'
CASE ch == Chr(9)
cOut += '\t'
OTHERWISE
cOut += ch
ENDCASE
NEXT
cOut += '"'
RETURN cOut
/* ------------------------------------------
HTTP com CURL (POST JSON)
--------------------------------------------- */
FUNCTION HttpPostJsonCurl( cUrl, cJson )
LOCAL cReq := "req.json"
LOCAL cResp := "resp.txt"
LOCAL cCode := "code.txt"
LOCAL cCmd
LOCAL cBody := ""
LOCAL cStatus := ""
LOCAL nH
// Grava JSON SEM ^Z no final
nH := FCreate( cReq )
IF nH != -1
FWrite( nH, cJson )
FClose( nH )
ELSE
? "Erro ao criar arquivo:", cReq
RETURN ""
ENDIF
cCmd := ;
'curl -s -o "' + cResp + '" -w "%{http_code}" ' + ;
'-X POST -H "Content-Type: application/json" ' + ;
'--data-binary "@' + cReq + '" "' + cUrl + '" > "' + cCode + '"'
RUN ( cCmd )
IF File( cResp )
cBody := MemoRead( cResp )
ENDIF
IF File( cCode )
cStatus := AllTrim( MemoRead( cCode ) )
ENDIF
? "----------------------------------------"
? "URL :", cUrl
? "Status HTTP:", cStatus
? "Resposta:"
?? cBody
? "----------------------------------------"
RETURN cBody
/* ------------------------------------------
HTTP com CURL (POST XML)
--------------------------------------------- */
FUNCTION HttpPostXmlCurl( cUrl, cXml )
LOCAL cReq := "req.xml"
LOCAL cResp := "resp.txt"
LOCAL cCode := "code.txt"
LOCAL cCmd
LOCAL cBody := ""
LOCAL cStatus := ""
LOCAL nH
// Grava XML SEM ^Z no final
nH := FCreate( cReq )
IF nH != -1
FWrite( nH, cXml )
FClose( nH )
ELSE
? "Erro ao criar arquivo:", cReq
RETURN ""
ENDIF
cCmd := ;
'curl -s -o "' + cResp + '" -w "%{http_code}" ' + ;
'-X POST -H "Content-Type: application/xml" ' + ;
'--data-binary "@' + cReq + '" "' + cUrl + '" > "' + cCode + '"'
RUN ( cCmd )
IF File( cResp )
cBody := MemoRead( cResp )
ENDIF
IF File( cCode )
cStatus := AllTrim( MemoRead( cCode ) )
ENDIF
? "----------------------------------------"
? "URL :", cUrl
? "Status HTTP:", cStatus
? "Resposta:"
?? cBody
? "----------------------------------------"
RETURN cBody
/* ------------------------------------------
ENDPOINTS
--------------------------------------------- */
PROCEDURE Test_ValidarSchema(cBase, cXmlFile)
LOCAL cArq := Ask("Arquivo XML", cXmlFile)
LOCAL cXml := ReadFileOrEmpty(cArq)
LOCAL cTipo := Ask("Tipo (nfe / leiauteNFe / nfeProc)", "nfe")
LOCAL cJson
IF Empty(cXml)
? "Abortado."
Inkey(0)
RETURN
ENDIF
cJson := ;
'{' + ;
'"xml":' + JsonString(cXml) + ',' + ;
'"tipo":' + JsonString(cTipo) + ;
'}'
HttpPostJsonCurl(cBase + "/nfe/validar-schema", cJson)
Inkey(0)
RETURN
PROCEDURE Test_XmlInfo(cBase, cXmlFile)
LOCAL cArq := Ask("XML p/ /nfe/xmlinfo", cXmlFile)
LOCAL cXml := ReadFileOrEmpty(cArq)
IF Empty(cXml)
RETURN
ENDIF
HttpPostXmlCurl(cBase + "/nfe/xmlinfo", cXml)
Inkey(0)
RETURN
PROCEDURE Test_Analise(cBase, cXmlFile)
LOCAL cArq := Ask("XML p/ /nfe/analise", cXmlFile)
LOCAL cXml := ReadFileOrEmpty(cArq)
IF Empty(cXml)
RETURN
ENDIF
HttpPostXmlCurl(cBase + "/nfe/analise", cXml)
Inkey(0)
RETURN
PROCEDURE Test_DanfeHtml(cBase, cXmlFile)
LOCAL cArq := Ask("XML p/ DANFE", cXmlFile)
LOCAL cXml := ReadFileOrEmpty(cArq)
LOCAL cOut := Ask("Salvar como", "danfe_teste.html")
LOCAL cResp
IF Empty(cXml)
RETURN
ENDIF
cResp := HttpPostXmlCurl(cBase + "/danfe/html", cXml)
IF !Empty(cResp)
MemoWrit(cOut, cResp)
? "HTML salvo em:", cOut
ENDIF
Inkey(0)
RETURN
PROCEDURE Test_Status(cBase)
LOCAL cUf := Ask("UF", "AC")
LOCAL cAmb := Ask("Ambiente (1/2)", "2")
LOCAL cCert := Ask("Caminho PFX", "C:\certificados\cert.pfx")
LOCAL cSenha := Ask("Senha", "")
LOCAL cJson := ;
'{' + ;
'"uf":' + JsonString(cUf) + ',' + ;
'"ambiente":' + JsonString(cAmb) + ',' + ;
'"certificado":' + JsonString(cCert) + ',' + ;
'"senha":' + JsonString(cSenha) + '}'
HttpPostJsonCurl(cBase + "/nfe/status", cJson)
Inkey(0)
RETURN
PROCEDURE Test_ConsultaChave(cBase)
LOCAL cUf := Ask("UF", "AC")
LOCAL cAmb := Ask("Ambiente (1/2)", "2")
LOCAL cCh := Ask("Chave NFe", "")
LOCAL cCert := Ask("Caminho PFX", "C:\certificados\cert.pfx")
LOCAL cSenha := Ask("Senha", "")
LOCAL cJson := ;
'{' + ;
'"uf":' + JsonString(cUf) + ',' + ;
'"ambiente":' + JsonString(cAmb) + ',' + ;
'"chNFe":' + JsonString(cCh) + ',' + ;
'"certificado":' + JsonString(cCert) + ',' + ;
'"senha":' + JsonString(cSenha) + '}'
HttpPostJsonCurl(cBase + "/nfe/consulta", cJson)
Inkey(0)
RETURN
PROCEDURE Test_Gtin(cBase)
LOCAL cGtin := Ask("GTIN", "7897062500066")
LOCAL cCert := Ask("Caminho PFX", "C:\certificados\cert.pfx")
LOCAL cSenha := Ask("Senha", "")
LOCAL cJson := ;
'{' + ;
'"gtin":' + JsonString(cGtin) + ',' + ;
'"certificado":' + JsonString(cCert) + ',' + ;
'"senha":' + JsonString(cSenha) + '}'
HttpPostJsonCurl(cBase + "/nfe/gtin", cJson)
Inkey(0)
RETURN