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:
#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.
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.
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:
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:
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:
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:
method getError() class CNPJws
return ::cErro
Legal, construímos nossa classe, agora é um bom momento para desenvolvermos uma rotina para utilizarmos nossa classe:
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!