SEFAZCLASS em Python + FASTAPI

Fórum sobre outras linguagens de programação.

Moderador: Moderadores

Fernando queiroz
Usuário Nível 4
Usuário Nível 4
Mensagens: 783
Registrado em: 13 Nov 2014 00:41
Localização: Porto Alegre/RS

SEFAZCLASS em Python + FASTAPI

Mensagem 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/
HARBOUR 3.2, HWGUI 2.23 B7, SEFAZCLASS, PDFClass, ADO + MariaDB/MySQL, RMChart, Python + FASTAPI , Android Kotlin
Fernando queiroz
Usuário Nível 4
Usuário Nível 4
Mensagens: 783
Registrado em: 13 Nov 2014 00:41
Localização: Porto Alegre/RS

Re: SEFAZCLASS em Python + FASTAPI

Mensagem por Fernando queiroz »

sefaz-service.jpg
sefaz-service.jpg (108.35 KiB) Exibido 86 vezes
SWAGGER da SEFAZ-SERVICE
HARBOUR 3.2, HWGUI 2.23 B7, SEFAZCLASS, PDFClass, ADO + MariaDB/MySQL, RMChart, Python + FASTAPI , Android Kotlin
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20321
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Re: SEFAZCLASS em Python + FASTAPI

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Fernando queiroz
Usuário Nível 4
Usuário Nível 4
Mensagens: 783
Registrado em: 13 Nov 2014 00:41
Localização: Porto Alegre/RS

Re: SEFAZCLASS em Python + FASTAPI

Mensagem por Fernando queiroz »

nova rota para gerar direto em PDF
nova rota para gerar direto em PDF
sefaz-service.jpg (117.14 KiB) Exibido 77 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
HARBOUR 3.2, HWGUI 2.23 B7, SEFAZCLASS, PDFClass, ADO + MariaDB/MySQL, RMChart, Python + FASTAPI , Android Kotlin
Fernando queiroz
Usuário Nível 4
Usuário Nível 4
Mensagens: 783
Registrado em: 13 Nov 2014 00:41
Localização: Porto Alegre/RS

Re: SEFAZCLASS em Python + FASTAPI

Mensagem por Fernando queiroz »

Novas rotas incluidas e funcionando
sefaz-service.jpg
sefaz-service.jpg (93.11 KiB) Exibido 62 vezes
HARBOUR 3.2, HWGUI 2.23 B7, SEFAZCLASS, PDFClass, ADO + MariaDB/MySQL, RMChart, Python + FASTAPI , Android Kotlin
Responder