Pular para o conteúdo principal

Consultar CNPJ com ADVPL (Protheus)

· Leitura de 5 minutos
Carlos Tirabassi

O sistema Protheus da Totvs é o ERP líder do mercado brasileiro e pode ser integrado com a API do CNPJ.ws de maneira fácil e simples para consultar clientes ou fornecedores através do CNPJ.

O Protheus utiliza a linguagem proprietária da Totvs, o ADVPL (Advanced Protheus Language), que é uma linguagem de programação padrão xBase (Clipper, Visual Objects e depois Fivewin).

Para essa integração vamos construir uma classe genérica de comunicação que poderá ser usada em diversos tipos de projeto. Você também pode encontrar esse projeto no GitHub.

Lembrando que você pode usar nossa API gratuita para consultar CNPJ, mas com uma limitação de 3 consultas por minuto ou pode adquirir um dos nossos planos comerciais.

Com a integração podemos usar a API para consultar o endereço, inscrição estadual, situação cadastral, CNAE e muitas outras informações que podem ser importantes no momento do cadastro do cliente ou fornecedor, pessoa jurídica, através do CNPJ.

Integração CNPJ.ws com o ERP Totvs Protheus

Vamos começar, abaixo a declaração da classe:

/src/cnpjws.prw
#include 'totvs.ch'
#include 'protheus.ch'

class CNPJws
data lVerb as Logical
data cURL as String
data cToken as String
data cErro as String
data cRet as String
data oRet as String
data aHeaders as Array
data lRet as Logical

method new() CONSTRUCTOR
method consoleLog(cMsg,lErro)
method setError(oRest)
method consultarCNPJ(cCNPJ)
method getResponse()
method getError()
endClass

Teremos 6 métodos na nossa classe:

  • new: Responsável por instanciar a classe;
  • setError: Método interno para geração dos erros;
  • consultarCNPJ: Responsável por fazer a consulta do CNPJ junto a API do CNPJ.ws;
  • getResponse: Retorna a resposta da API em formato JSON;
  • getError: Retorna a mensagem de erro;

Agora vamos desenvolver o método new, que é o nosso método construtor. Veja que esse método recebe o parâmetro lTest (o valor default é falso) e sim, vamos fazer testes com a nossa classe de integração.

Veja também que temos um parâmetro CN_TOKEN, devemos criá-lo caso estejamos usando a API Comercial (sem restrições) e preenchê-lo com o Token que foi enviado no seu e-mail.

/src/cnpjws.prw
method new(lTest) class CNPJws

default lTest:= .f.

::cToken := if(lTest, '', superGetMV('CN_TOKEN',.f.,''))
::cURL := if(empty(::cToken),'https://publica.cnpj.ws','https://comercial.cnpj.ws')
::lVerb := if(lTest, .t., superGetMV('CN_VERBO',.f.,.t.)) //Indica se ira imprimir todas as msgs no console
::cErro := ''
::cRet := ''
::oRet := nil
::lRet := .t.
::aHeaders:= {"Content-Type: application/json; charset=utf-8"}

if !empty(::cToken)
aAdd(::aHeaders,'x_api_token: ' + allTrim(::cToken))
endif

::consoleLog('Classe instanciada com sucesso!')

return Self

No método new nós usamos o método consoleLog, então vamos desenvolver ele agora. Esse método visa padronizar as mensagens emitidas pela classe.

Caso o parâmetro CN_VERBO esteja como .T. a classe irá imprimir todas as mensagens no console.log do Protheus.

/src/cnpjws.prw
method consoleLog(cMsg,lErro) class CNPJws
local cLog:= ''
default cMsg := ''
default lErro:= .f.

if ::lVerb .or. lErro
cLog:= '[' + dtoc(date()) + ']'
cLog+= '[' + time() + ']'
cLog+= '[' + ProcName(1) + ']'
cLog+= '[' + cValToChar(ProcLine(1)) + ']'
cLog+= '['+allTrim(cMsg)+']'
if lErro
::cErro:= cLog
::lRet := .f.
endif
if ::lVerb .or. lErro
conout(cLog)
endif
endif

return

Abaixo o método setError usado pela classe para gerar as mensagens de erro:

/src/cnpjws.prw
method setError(oRest,cPath) class CNPJws
local cLog := ''
local cAux := ''
local cStatus := ''

default cPath := ''

::oRet := nil
::cRet:= oRest:GetResult()

if valType(::cRet) <> 'C'
::cRet:= ''
endif

if !empty(::cRet)
::cRet:= FWNoAccent(DecodeUtf8(::cRet))
if empty(::cRet)
::cRet:= FWNoAccent(oRest:GetResult())
endif
endif

cAux:= FWNoAccent(DecodeUtf8(oRest:GetLastError()))
if empty(cAux)
cAux:= FWNoAccent(oRest:GetLastError())
endif

cStatus:= oRest:GetHTTPCode()
cLog+= 'Host: ' + ::cURL + CRLF
cLog+= 'Operacao: ' + ProcName(1) + ' ' + cPath + CRLF
cLog+= 'HTTP Code: ' + cStatus + CRLF
cLog+= 'Erro: ' + cAux + CRLF
cLog+= 'Resultado: ' + ::cRet + CRLF

::consoleLog(cLog,.T.)

return

Agora sim, vamos desenvolver o método responsável por se comunicar com a API do CNPJ.ws, o método consultarCNPJ. Aqui vamos utilizar a classe FWREST para fazer a comunicação com a API, esse método receber o CNPJ como parâmetro e faz a consulta na API.

O método retorna um boolean, caso de tudo certo ele vai retornar true, caso ocorra um erro o retorno será falso, veja abaixo:

/src/cnpjws.prw
method consultarCNPJ(cCNPJ) class CNPJws
local oRest := FWRest():New(::cURL)
local cPath := ''

::cRet := ''
::oRet := nil
::lRet := .t.
::cErro:= ''

cPath+= allTrim(cCNPJ)
oRest:setPath(cPath)

if oRest:Get(::aHeaders)
if !empty(oRest:GetResult())
::cRet:= FWNoAccent(DecodeUtf8(oRest:GetResult()))
if empty(::cRet)
::cRet:= FWNoAccent(oRest:GetResult())
endif
::cRet:= strTran(::cRet,'\/','/')
::cRet:= strtran(::cRet,":null",': " "')
::cRet:= strtran(::cRet,'"self"','"_self"')
::oRet:= JsonObject():new()
::oRet:fromJson(::cRet)
::lRet := .t.
::cErro:= ''
else
::oRet := nil
::cErro:= ''
::lRet := .t.
endif
::consoleLog('Sucesso! ' + cPath)
else
::setError(oRest,cPath)
endif

FreeObj(oRest)

return ::lRet

Abaixo temos o método responsável por retornar o JSON que a API do CNPJ.ws retornou na consulta:

/src/cnpjws.prw
method getResponse() class CNPJws
return ::oRet

Abaixo temos o método responsável por retornar a mensagem de erro caso a consulta não obtenha sucesso:

/src/cnpjws.prw
method getError() class CNPJws
return ::cErro

Legal, construímos nossa classe, agora é um bom momento para desenvolvermos uma rotina para utilizarmos nossa classe:

/src/cnpjws.prw
user function tstCNPJ()
local oCNPJ:= nil
local oJSON:= nil

RpcSetType(3)
if !RpcSetEnv('99','01')
return
endif

oCNPJ:= CNPJws():new()//Instancia a classe

if oCNPJ:consultarCNPJ('40154884000153')
oJSON:= oCNPJ:getResponse()
endif

RPCClearEnv()

return

Caso precise de apoio para implementar essa integração na sua base, nós recomendamos a Apply System, nossa parceira, que possui consultores especializados na integração entre sistemas!

Esse post ficou grande, não é? Então vou deixar para fazer uma parte 2 utilizando o TL++ para criarmos um teste para a classe de integração, porém os fontes já estão no GitHub caso queira dar uma olhada!

Para saber mais sobre nossos planos e formas de pagamento acesse CNPJ.ws.

Até mais!