Exemplo de Integração com ViaCEP usando FWRest

Hoje vou mostrar como consultar dados de um endereço diretamente do CEP usando o AdvPL e a função FWRest.

Pessoal, o grande Thiago Andrade (LinkedIn), fez uma integração recentemente com a API gratuita da ViaCEP, que retorna informações através de um CEP disponibilizado.

Essa integração usa o FWRest com GET, confira o exemplo abaixo desenvolvido buscando informações do CEP 03.062-010.

//=================================================================================
/*/{Protheus.doc} zViaCep
[API.VIACEP] [GET] Conecta na Api gratuita da ViaCep para retornar dados de um Endereço
a partir do CEP.
Documentação: https://viacep.com.br/
Campos Disponiveis na API:  
BAIRRO, CEP, COMPLEMENTO, GIA, IBGE, LOCALIDADE, LOGRADOURO, UF, UNIDADE
   
Uso: Incluir/Atualizar CC2 quando necessário
   
@author     Thiago.Andrrade
@since      24/07/2020
/*/
//=================================================================================
User Function zViaCep()
    Local aArea         := GetArea()
    Local aHeader       := {}
    Local cCep          := '03062010'
    Local cCodMun       := ''
    Local oRestClient   := FWRest():New("https://viacep.com.br/ws")
    Local oJsObj
   
    aadd(aHeader,'User-Agent: Mozilla/4.0 (compatible; Protheus '+GetBuild()+')')
    aAdd(aHeader,'Content-Type: application/json; charset=utf-8')
         
    ////////////////////////////////////////////////////////////////
    //[GET] Consulta Dados na Api
    oRestClient:setPath("/"+cCep+"/json/")
    If oRestClient:Get(aHeader)
        //Deserealiza o Json
        FWJsonDeserialize(oRestClient:CRESULT,@oJsObj)
   
        //Recebe Dados do Json
        cCodMun := SubStr(oJsObj:IBGE,3,5)
   
        /*oJsObj:BAIRRO
        oJsObj:CEP
        oJsObj:COMPLEMENTO
        oJsObj:GIA
        oJsObj:IBGE
        oJsObj:LOCALIDADE
        oJsObj:LOGRADOURO
        oJsObj:UF
        oJsObj:UNIDADE*/
   
        FreeObj(oJsObj)
    Else
        ConOut("Erro Api ViaCep: "+oRestClient:GetLastError())
    Endif
   
    RestArea(aArea)
Return

Update – Janeiro de 2022

Pessoal, o grande Súlivan Simões ( LinkedIn ), fez uma adaptação na rotina, para utilizar JsonObject, e já retornando todos os campos. Segue abaixo a função:

#Include 'Totvs.ch'
 
/*/{Protheus.doc} zViaCep
 
[API.VIACEP] [GET] Conecta na Api gratuita da ViaCep para retornar dados de um Endereço
a partir do CEP.
Documentação: https://viacep.com.br/
Campos Disponiveis na API:  
BAIRRO, CEP, COMPLEMENTO, GIA, IBGE, LOCALIDADE, LOGRADOURO, UF, UNIDADE
 
@type function
@author Thiago.Andrrade (autor da funcionalidade original)
@author Súlivan (resposável por adaptar o fonte)
@since 24/07/2020 [data da criação da rotina]
 
@example
    u_zViaCep('37600000')
    u_zViaCep('31015-104')
    u_zViaCep('31015.025')
    u_zViaCep('31010 514')
    u_zViaCep(FwFldGet('A1_CEP'))
 
    Exemplo para chamar em gatilhos do Protheus para preencher o código do municipio por exemplo
    Regra:   u_zViaCep(FwFldGet('A1_CEP'))['ibge']
 
      @obs : MANUTENÇÕES FEITAS NO CÓDIGO:
     --------------------------------------------------------------------------------------------                         
     Data: 26/01/2021
     Responsável: Súlivan
     Log: * Retirado o uso da função FWJsonDeserialize que está em deprecate
          * Rotina adaptada para receber parametros
          * Adicionado return para retornar as informações concedidas pela API               
          * Incluso mais logs na rotina.     
     --------------------------------------------------------------------------------------------
/*/
User Function zViaCep(cCep)
 
    Local aArea         := GetArea()
    Local aHeader       := {}    
    Local oRestClient   := FWRest():New("https://viacep.com.br/ws")
    Local oJson         := JsonObject():New()
     
    Default cCep        := ''
 
    fConOut("[U_zViaCep] - Entrou na função que consulta as informações do endereco pelo CEP")
 
    //Retira espaços,traços e pontos caso receba assim dos parametros
    cCep := StrTran(StrTran(StrTran(cCep," ",""),"-",""),".","")
 
    aadd(aHeader,'User-Agent: Mozilla/4.0 (compatible; Protheus '+GetBuild()+')')
    aAdd(aHeader,'Content-Type: application/json; charset=utf-8')
 
    //[GET] Consulta Dados na Api
    oRestClient:setPath("/"+cCep+"/json/")
    If oRestClient:Get(aHeader)
          
        oJson:FromJson(oRestClient:CRESULT)          
 
        //Se as keys não existirem, cria elas com conteudo vazio.
        oJson['cep']        := Iif( ValType(oJson['cep'])         != "U", oJson['cep']        , "")
        oJson['logradouro'] := Iif( ValType(oJson['logradouro'])  != "U", oJson['logradouro'] , "")
        oJson['complemento']:= Iif( ValType(oJson['complemento']) != "U", oJson['complemento'], "")
        oJson['bairro']     := Iif( ValType(oJson['bairro'])      != "U", oJson['bairro']     , "")
        oJson['localidade'] := Iif( ValType(oJson['localidade'])  != "U", oJson['localidade'] , "")
        oJson['uf']         := Iif( ValType(oJson['uf'])          != "U", oJson['uf']         , "")
        oJson['ibge']       := Iif( ValType(oJson['ibge'])        != "U", SubStr(oJson['ibge'],3,5), "")
        oJson['gia']        := Iif( ValType(oJson['gia'])         != "U", oJson['gia']        , "") 
        oJson['ddd']        := Iif( ValType(oJson['ddd'])         != "U", oJson['ddd']        , "")
        oJson['siafi']      := Iif( ValType(oJson['siafi'])       != "U", oJson['siafi']      , "")
 
        VarInfo("[U_zViaCep] - Resultado da consulta ->",oJson)
    Else
        fConOut("[U_zViaCep] - ** Erro Api ViaCep: "+oRestClient:GetLastError())
    Endif  
 
   oJson['erro']:=  Iif( ValType(oJson['cep']) == "U", "Api não retornou dados do cep: "+cValTochar(cCep) ,"")      
 
    fConOut("[U_zViaCep] - Finalizou na função que consulta as informações do endereco pelo CEP") 
 
    FreeObj(oRestClient)
    RestArea(aArea)
Return oJson
 
Static Function fConOut(cLog)
     
    Default cLog := "Log empty"
         
    FwLogMsg("INFO", /*cTransactionId*/, "fConOut", FunName(), "", "01", cLog, 0, 0, {})
              
Return

Update – Junho de 2023

Recentemente um aluno ficou com uma dúvida de como aplicar o fonte acima em uma validação de campo, então detalhamos no procedimento abaixo:

1. Criar uma função, por exemplo u_zTeste()
2. Colocar essa função na validação de usuário (X3_VLDUSER) do campo cep (como no A1_CEP)
3. Dentro dessa função, acione a busca do cep do exemplo de Janeiro de 2022
4. Ai você atualiza os campos conforme o retorno da função

Abaixo um exemplo dos passos acima:

User Function zTeste()
	Local aArea := FWGetArea()
	Local lOk   := .T.
	
	//Busca o CEP conforme o campo informado
	jJson := u_zViaCep(M->A1_CEP)
	
	//Se não veio erro, atualiza os outros campos
	If Type("jJson[erro]") == "U"
		M->A1_END := oJson['logradouro']
		//... Se for MVC, utilizar FWFldPut ou SetValue no Model
	EndIf

	FWRestArea(aArea)
Return lOk

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

6 Responses

  1. Felipe disse:

    Como atualizo o campo de CLientes na SA1 ?

  2. Súlivan disse:

    Grande artigo.
    Top!

  3. RENATO MARCHI MARINHEIRO disse:

    Olá pessoal, boa noite!! Fiz a consulta porém quando retorna letras com acento é como se o protheus trocasse o caracter.

Deixe uma resposta para SúlivanCancelar resposta

Terminal de Informação