Página 1 de 1

SEFAZCLASS em Python + FASTAPI

Enviado: 05 Dez 2025 17:20
por Fernando queiroz
Caros colegas
Estou desenvolvendo a nossa famosa SEFAZCLASS do Quintas em Python + FASTAPI criando um backend com rotas para varios serviços ,
segue endereço no GITHUB para quem tiver interesse em conhecer e testar:

https://github.com/queirozfernando/sefaz_service_python

quem quiser fazer teste utilize o Python 3.11

https://www.python.org/downloads/release/python-3110/

Re: SEFAZCLASS em Python + FASTAPI

Enviado: 07 Dez 2025 07:51
por Fernando queiroz
sefaz-service.jpg
sefaz-service.jpg (108.35 KiB) Exibido 95 vezes
SWAGGER da SEFAZ-SERVICE

Re: SEFAZCLASS em Python + FASTAPI

Enviado: 07 Dez 2025 08:57
por JoséQuintas
Na prática isso abre um leque de possibilidades infinitas.
Tudo pode ser feito com Phyton, e o aplicativo acessar pelo windows ou android ou outro.

Re: SEFAZCLASS em Python + FASTAPI

Enviado: 07 Dez 2025 10:15
por Fernando queiroz
nova rota para gerar direto em PDF
nova rota para gerar direto em PDF
sefaz-service.jpg (117.14 KiB) Exibido 86 vezes

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
Fonte de teste em HARBOUR dos endpoints

Re: SEFAZCLASS em Python + FASTAPI

Enviado: 07 Dez 2025 16:47
por Fernando queiroz
Novas rotas incluidas e funcionando
sefaz-service.jpg
sefaz-service.jpg (93.11 KiB) Exibido 71 vezes