BlackTDN Search

segunda-feira, 20 de setembro de 2010

Protheus :: Exemplo de WebService para Consulta ao CEP

A dica de hoje é um exemplo de WebService em advpl para a consulta ao CEP (Código de Endereçamento Postal) baseado no site  Republica Virtual

#INCLUDE "APWEBSRV.CH"
#INCLUDE "PROTHEUS.CH"

#DEFINE STR0001 "Servico de Constulta ao Codigo de Enderacamento Postal"
#DEFINE STR0002 "Método para pesquisa do CEP"

/*/
 WSSERVICE: u_wsCEPInfo
 Autor:  Marinaldo de Jesus
 Data:  20/09/2010
 Descri‡…o: Servico de Constulta ao Codigo de Enderacamento Postal a partir da URL http://cep.republicavirtual.com.br/web_cep.php?cep=[cep]
 Uso:  Consulta ao CEP (Codigo de Enderecamento Postal)
/*/
WSSERVICE u_wsCEPInfo DESCRIPTION STR0001 NAMESPACE "http://localhost/naldo/ws/u_wscepinfo.apw" //"Servico de Constulta ao Codigo de Enderacamento Postal"

 WSDATA CEP    As String
 WSDATA XML    As String

 WSMETHOD CEPSearch  DESCRIPTION STR0002 //"Método para pesquisa do CEP"

ENDWSSERVICE

/*/
 WSMETHOD: CEPSearch
 Autor:  Marinaldo de Jesus
 Data:  20/09/2010
 Uso:  Consulta de CEP
 Obs.:  Metodo Para a Pesquisa do CEP
 Retorna: XML com a Consulta do CEP
 
/*/
WSMETHOD CEPSearch WSRECEIVE CEP WSSEND XML WSSERVICE u_wsCEPInfo

 Local cUrl  := ""
 Local lWsReturn := .T.

 DEFAULT CEP  := Self:CEP

 cUrl   := "http://cep.republicavirtual.com.br/web_cep.php?cep="+StrTran(CEP,"-","")+"&formato=xml"
 Self:XML  := HttpGet( cUrl )
 XML    := Self:XML

Return( lWsReturn )
Vamos consumi-lo usando um "Client" gerado pelo próprio Protheus.


#INCLUDE "PROTHEUS.CH"
#INCLUDE "APWEBSRV.CH"

/* ===============================================================================
WSDL Location    http://187.94.60.197:98/ws/U_WSCEPINFO.apw?WSDL
Gerado em        09/20/10 19:27:10
Observações      Código-Fonte gerado por ADVPL WSDL Client 1.090116
                 Alterações neste arquivo podem causar funcionamento incorreto
                 e serão perdidas caso o código-fonte seja gerado novamente.
=============================================================================== */

User Function _FTNRRNN ; Return  // "dummy" function - Internal Use 

/* -------------------------------------------------------------------------------
WSDL Service WSU_WSCEPINFO
------------------------------------------------------------------------------- */

WSCLIENT WSU_WSCEPINFO

 WSMETHOD NEW
 WSMETHOD INIT
 WSMETHOD RESET
 WSMETHOD CLONE
 WSMETHOD CEPSEARCH

 WSDATA   _URL                      AS String
 WSDATA   cCEP                      AS string
 WSDATA   cCEPSEARCHRESULT          AS string

ENDWSCLIENT

WSMETHOD NEW WSCLIENT WSU_WSCEPINFO
::Init()
If !FindFunction("XMLCHILDEX")
 UserException("O Código-Fonte Client atual requer os executáveis do Protheus Build [7.00.090818P-20100111] ou superior. Atualize o Protheus ou gere o Código-Fonte novamente utilizando o Build atual.")
EndIf
Return Self

WSMETHOD INIT WSCLIENT WSU_WSCEPINFO
Return

WSMETHOD RESET WSCLIENT WSU_WSCEPINFO
 ::cCEP               := NIL 
 ::cCEPSEARCHRESULT   := NIL 
 ::Init()
Return

WSMETHOD CLONE WSCLIENT WSU_WSCEPINFO
Local oClone := WSU_WSCEPINFO():New()
 oClone:_URL          := ::_URL 
 oClone:cCEP          := ::cCEP
 oClone:cCEPSEARCHRESULT := ::cCEPSEARCHRESULT
Return oClone

// WSDL Method CEPSEARCH of Service WSU_WSCEPINFO

WSMETHOD CEPSEARCH WSSEND cCEP WSRECEIVE cCEPSEARCHRESULT WSCLIENT WSU_WSCEPINFO
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += ''
cSoap += WSSoapValue("CEP", ::cCEP, cCEP , "string", .T. , .F., 0 , NIL, .F.) 
cSoap += ""

oXmlRet := SvcSoapCall( Self,cSoap,; 
 "http://localhost/naldo/ws/u_wscepinfo.apw/CEPSEARCH",; 
 "DOCUMENT","http://localhost/naldo/ws/u_wscepinfo.apw",,"1.031217",; 
 "http://187.94.60.197:98/ws/U_WSCEPINFO.apw")

::Init()
::cCEPSEARCHRESULT   :=  WSAdvValue( oXmlRet,"_CEPSEARCHRESPONSE:_CEPSEARCHRESULT:TEXT","string",NIL,NIL,NIL,NIL,NIL,NIL) 

END WSMETHOD

oXmlRet := NIL
Return .T.

Através de um programa em Advpl onde informaremos o código do CEP.


#INCLUDE "PROTHEUS.CH"

#DEFINE STR0001 "Informe o CEP"
#DEFINE STR0002 "Consulta de CEP"
#DEFINE STR0003  "UF"
#DEFINE STR0004 "Cidade"
#DEFINE STR0005  "Bairro"
#DEFINE STR0006 "Tipo de Logradouro"
#DEFINE STR0007 "Logradouro"
#DEFINE STR0008 "Resultado da Consulta"
#DEFINE STR0009 "CEP"
#DEFINE STR0010 "Mensagem"
#DEFINE STR0011 "Consultar Novo CEP?"
#DEFINE STR0012 "Consultando CEP"
#DEFINE STR0013 "Aguarde..."

/*/
 Funcao: CEPInfo
 Autor: Marinaldo de Jesus
 Data: 20/09/2010
 Uso: Consulta de CEP
 Obs.: Exemplo de Consumo do WEB Service u_wsCEPInfo para Consulta de CEP ao site da Republica Virtual
/*/
User Function CEPInfo()

 Local aPerg   := {}
 Local aResult  := {}
 
 Local bCEPSearch
 
 Local cXML

 Local cError  := ""
 Local cWarning  := ""

 Local cUF
 Local cCidade
 Local cBairro
 Local cMensagem
 Local cResultado
 Local cLogradouro
 Local cTpLogradouro

 Local oWSCEP
 Local oXML

 BEGIN SEQUENCE
 
  aAdd( aPerg , { 1 , STR0002 , Space(8) , "99999999" , ".T." , "" , ".T." , 8 , .T. } ) //"Informe o CEP"
  IF ParamBox( @aPerg , STR0002 , NIL , NIL , NIL , .T. )
   
   bCEPSearch := { ||           ; 
        oWSCEP   := WSU_WSCEPINFO():New(), ;
        oWSCEP:cCEP := MV_PAR01,    ;
        oWSCEP:CEPSEARCH()      ;
         } 

   MsgRun( STR0013 , STR0012 , bCEPSearch ) //"Aguarde"###"Consultando CEP"

   cXML  := oWSCEP:cCEPSEARCHRESULT
   oXML  := XmlParser( cXML , "_" , @cError , @cWarning )
 
   cResultado := oXml:_WebServiceCep:_Resultado:Text
   cMensagem := oXml:_WebServiceCep:_Resultado_Txt:Text
 
   IF ( cResultado == "1" )
 
    cUF    := oXml:_WebServiceCep:_UF:Text
    cCidade   := oXml:_WebServiceCep:_Cidade:Text
    cBairro   := oXml:_WebServiceCep:_Bairro:Text
    cLogradouro  := oXml:_WebServiceCep:_Logradouro:Text
    cTpLogradouro := oXml:_WebServiceCep:_Tipo_Logradouro:Text

    aAdd( aResult , { 1 , STR0009 , MV_PAR01  , "99999999" , ".T." , "" , ".F." , 08 , .F. } ) //"CEP"
    aAdd( aResult , { 1 , STR0003 , cUF      , "@"   , ".T." , "" , ".F." , 04  , .F. } ) //"UF"
    aAdd( aResult , { 1 , STR0004 , cCidade   , "@"   , ".T." , "" , ".F." , 100 , .F. } ) //"Cidade"
    aAdd( aResult , { 1 , STR0005 , cBairro   , "@"     , ".T." , "" , ".F." , 100 , .F. } ) //"Bairro"
    aAdd( aResult , { 1 , STR0006 , cTpLogradouro , "@"     , ".T." , "" , ".F." , 100 , .F. } ) //"Tipo de Logradouro"
    aAdd( aResult , { 1 , STR0007 , cLogradouro  , "@"   , ".T." , "" , ".F." , 100 , .F. } ) //"Logradouro"

   Else
   
    aAdd( aResult , { 1 , STR0009 , MV_PAR01  , "99999999"  , ".T." , "" , ".F." , 08 , .F. } ) //"CEP"
 
   EndIF

   ParamBox( @aResult , STR0008 + " : " + cMensagem , NIL , NIL , NIL , .T. ) //"Resultado da Consulta"


   IF !( MsgNoYes( "Consultar Novo CEP?" , ProcName() ) )
    BREAK
   EndIF
 
   U_CEPInfo()
 
  EndIF

 END SEQUENCE

Return( MBrChgLoop( .F. ) )
Dica: Um exemplo de uso da função XmlParser() pode ser visto no código acima.

Para testar:

Clique aqui e baixe todos os códigos fontes.

Compile o WebService, Gere e compile o Cliente.

Compile o Programa de Exemplo "u_CEPInfo.prg" e adicione a chamada ao Menu de algum módulo do SIGA (Obs.: Se for incluir no Menu do Configurador altere o módulo de 99 para 97 ou outro de sua preferência )

[]s
иαldσ dj

35 comentários:

  1. Ola Naldo, muito bacana este seu tutorial, uso algo parecido para buscar umas outras informações num site.
    Parabens pelos seus posts, são muito explicativos e úteis.
    Aproveitando o gancho do meu post, você sabe como pode ser realizada a troca de ambiente (empresa) em tempo de execução de uma função?
    Exemplo, a função ConPad("SB1") chamada a consulta padrão da empresa que foi aberta no inicio da execução, existe alguma maneira de realizar a troca de empresa em tempo de execução?

    Obrigado e parabens pelo blog.

    ResponderExcluir
  2. Existe a função EmpOpenFile(). Vou Postar um Exemplo no Blog.

    []s
    иαldσ dj

    ResponderExcluir
  3. Primeiramente Parabens pelo blog ja add aqui aos favoritos, to com uma dúvida talvez você possa me ajudar tenho que acessar um node do XML que tem um atributo (exemplo: ), já tentei de tudo e não consegui, agradeco atenção, e novamente parabens pelo blog!

    ResponderExcluir
  4. boa tarde Naldo,
    Parabéns pelo seu blog... tenho aprendido bastante com suas dicas em ADVPL....
    gostaria de aproveitar e saber se vc já consumiu algum web service com uso de certificado digital, pois estou penando para gerar o privatekey e o passphrase que o WS (estou tentando consumir da serasa) solicita.

    ResponderExcluir
  5. Parabéns Naldo pelo blog e principalmente pela disponibilidade de coração em compartilhar estas informações. Apreciei muito e continue assim! Um grande Abraço.

    ResponderExcluir
  6. Ei Naldo, parabens pelo Blog...
    Estou com um problema para consumir meu WS...

    Utilizo o seguinte código para conexao:

    User Function Agent1()

    Local _oWSTeste, cSvcError , cSoapFCode ,cSoapFDescr

    _oWSTeste := WSSANSYNCH():New()
    _oWSTeste:cID := '12345'
    If _oWSTeste:GetTeste()
    MsgAlert('Conexão OK!')
    Else
    cError := IF( Empty( GetWscError(3) ) , GetWscError(1) , GetWscError(3) )
    MsgAlert(cError)
    Endif

    MsgAlert(_oWSTeste:cGETTESTERESULT)

    Return

    No teste de conexao me retorna o erro de: NÃO FOI POSSÍVEL POST.

    Podes de ajudar??

    ResponderExcluir
  7. GuUuto,

    Preciso de mais informações pra indentificar o motivo do seu WebService não estar executando corretamente.

    Me envie, se possível o "WebService" para que eu gere um "Client" e verifique, assim que tiver um tempinho, a causa do erro.

    []s

    ResponderExcluir
  8. Boa tarde,

    Implementei o exemplo e ao executar da a seguinte mensagen: WSCERR044 / Não foi possível POST : URL http://187.94.60.197:98/ws/U_WSCEPINFO.apw
    ADVPL WSDL Client 1.100812 / TOTVS Construção e Projetos Webservice on 20110110 16:02:38


    o que pode ser?

    parabens....

    ResponderExcluir
  9. O Problema é que você está usando o "Client" que disponibilizei no exemplo. Siga os Procedimentos do "post" e gere um novo "Client" com a sua url.


    []s
    иαldσ dj

    ResponderExcluir
  10. Ok, deu certo. Na verdade nao era isso, era configuração de proxy.

    Obrigado e parabens, continue assim compartilhando o conhecimento.

    ResponderExcluir
  11. Boa noite Naldo.

    Gostaria de saber se existe uma maneira de no momento do recebimento dos parametros (WSRECEIVE CEP no seu caso), passar diretamente um determinado array.

    Valeusss, abs.

    ResponderExcluir
  12. Talvane,

    É possível sim. No exemplo, a intenção foi simplificar o WS e mostrar o uso da XmlParser(). Outra forma de fazer seria criando a Estrutura do CEP no WS e carregando os dados com XmlParser() para retorno. E, no cliente, usar essa estrutura. Assim que tiver um tempinho vou reestruturar o exemplo para que retorne a estrutura de CEP e não mais o XML.

    []s
    иαldσ dj

    ResponderExcluir
  13. Boa tarde Naldo,

    No meu caso eu estou fazendo a integração entre duas empresas, uma das rotinas é realizar o MsExecAuto do MATA103 - Documento de entrada, o que eu queria fazer era no trecho WsReceive passar os arrays de xCab e xItens para usar na mesma, porém como passar esses parametros para o WsReceive ??? Obrigado pela ajuda Naldo.

    Falows, abs.

    ResponderExcluir
  14. Talvane,

    Neste caso, você poderá utilizar a "estrutura" TableView e, a partir dela, montar o seu array de cabeçalho e de Itens.

    []s
    иαldσ dj

    ResponderExcluir
  15. Bom dia mestre Naldo.

    Cara estou precisando de uma ajuda sua, please da um maozinha ai.
    É o seguinte:

    Tenho um webservice que tem duas WsStruct que são recebidas como parametro no WsReceive:

    WsStruct Itens

    WsData cCod As String ...

    EndWsStruct

    WsStruct Cab

    WsData ... As String ...
    WsData _Itens As Array of Itens

    EndWsStruct

    WsService ...

    WsData _Nf As Cab
    ...

    EndWsService

    Bem, o que eu não estou conseguindo fazer é após gerar o client através do IDE td bonitinho no momento em que vou consumir ele não consigo acessar os Itens, já tentei de tudo!!! Realmente tou precisando de uma ajuda. Qualquer coisa se vc poder me enviar um email: talvane.magalhaes@gmail.com

    Obrigado mesmo se poder ajudar Naldo.

    Falows, abs.

    ResponderExcluir
  16. Mestre иαldσ (rs) . Estou me sentindo "Bruce Lee".

    ResponderExcluir
  17. Talvane,

    Enviei a solução para o seu e-mail.

    []s
    иαldσ dj

    ResponderExcluir
    Respostas
    1. Poderia enviar a solução para mim também por favor.

      At.

      Luciano.
      luciano.aol@gmail.com

      Excluir
    2. Vc pode enviar para mim também por favor.

      At.

      Luciano
      luciano.aol@gmail.com

      Excluir
    3. Poderia enviar a solução para o e-mail marcsatiro@gmail.com

      Att

      Marcelo

      Excluir
    4. Naldo, sei que faz bastante tempo que você postou isso, mas poderia enviar me enviar também essa solução da array?

      nato.oliveira7@gmail.com

      Muito obrigado!

      Att,
      Renato Nogueira

      Excluir
    5. Naldo, se ainda for possível poderia me enviar a solução acima para meu email: pcf.vieira@globo.com
      Estou com o mesmo problema do Talvane. Desde já lhe sou grato pela atenção

      Excluir
  18. Simples, Mestre não há como não chamar de Mestre quem te ajuda e ainda não cobra nada por isso e ainda faz com a maior dedicação. Isso chama-se Marinaldo de Jesus mais conhecido como NaldoDj. :)

    Muito obrigado mesmo Mestre pela grande ajuda que você me enviou.

    Um grande abs.

    Talvane

    ResponderExcluir
  19. Naldo, bom dia. Primeiramente parabéns pelo "Black TDN", muito bom e as informações daqui estão sendo muito úteis.
    E estou precisando da sua ajuda, estou utilizando um cliente webservice, que pede a estrutura do XML, e não o xml propriamente dito. O pessoal da Totvs SP me disse que usando a função XMLParser eu consigo a estrutura, porém mesmo passando a estrutura, o comando WsSOAPValue não funciona, chega nele e "pula" direto para o fim. Você conhece este comando? seus parâmetros? estou fazendo algo de errado e não sei o que é. VocÊ poderia me ajudar?

    ResponderExcluir
  20. Respostas
    1. Naldo, enviei o string e removi do client os comandos soap e resolveu.
      Tenho um problema agora com o cancelamento de notas eletrônicas, envio o xml no padrão que o client criou sozinho, quando informei a url do webservice da prefeitura em questão. Porém, ele me retorna um erro em uma das tag's, o exemplo que eles me forneceram possui diversos pontos diferentes, url's e ambientes diferentes, confirmei com eles e elas afirmaram que geraram isso usando o meu xml num tal de SoapUI, testei nele e realmente deu certo, mas não sei onde altero as informações que meu xml via client cria.
      Vou postar os dois aqui:

      Meu XML:






      54
      87547675000133
      4302105

      E30






      XML deles:







      54
      87547675000133
      4302105

      E30






      Você consegue me ajudar?

      Excluir
    2. иαldσ dj, desculpe a falta de retorno, acabei enviando o xml e retirando os comandos de soapvalue dentro do client, daí deu certo.
      Meu problema agora é mais adiante:
      Enviei o arquivo de cancelamento de notas, e ele retorna um erro:

      javax.xml.bind.UnmarshalException: unexpected element
      (uri:"http://www.betha.com.br/e-nota-contribuinte-ws",local:"Pedido").
      Expected elements are <{}Pedido>

      Se você não se importar, te envio o link do post no fórum da empresa que está fornecendo o WS:
      http://forum.betha.com.br/phpbb/viewtopic.php?f=93&t=7216

      você sabe como altero estas informações no "envelopamento" do meu xml?

      Excluir
  21. Olá Naldo, vou novo no ADVPL, estou precisando aprender justamente para fazer umas integrações via WebService com outros aplicativos aqui na empresa.

    Eu não vi no post uma justificativa para criar o WebService e um Client, não daria para dar um XmlParse() direto retorno do HttpGet() ?

    ResponderExcluir
  22. mesmo eu gerando um client novo, ele retorna nada !

    me dá uma luz ?

    ResponderExcluir
  23. mesmo gerando o client novo, ele retorna nada !

    ResponderExcluir
  24. Boa noite... Parabens pelo Post.

    Por curiosidade, WS não é minha praia, mas estou tentando aprender com o objetivo de fazer uma consulta ao sintegra em lote, ou seja, apos seleção dos pedidos a serem faturados , fazer que consulte o sintegra de todos, sem ter que ir cliente por cliente acoes relacionadas > mashup > sintegra ... ( regras da empresa ) ... Porém a totvs não fornece a chamada ou se que o fonte do de consulta do sintegra.

    Vc saberia me dizer como funciona o mashup do sintegra?

    outra coisa...

    ao roda o fonte, tive o seguinte retorno:

    ERR_FORM

    Problema,:
    Existe um ERRO na formula digitada

    argument #0 erros, expected C->U, function XmlParser

    Solucao

    Digite uma expressao valida

    ResponderExcluir
  25. Boa noite...

    Por curiosidade, WS não é minha praia, mas estou tentando aprender com o objetivo de fazer uma consulta ao sintegra em lote, ou seja, apos seleção dos pedidos a serem faturados , fazer que consulte o sintegra de todos, sem ter que ir cliente por cliente acoes relacionadas > mashup > sintegra ... ( regras da empresa ) ... Porém a totvs não fornece a chamada ou se que o fonte do de consulta do sintegra.

    Vc saberia me dizer como funciona o mashup do sintegra?

    outra coisa...

    ao roda o fonte, tive o seguinte retorno:

    ERR_FORM

    Problema,:
    Existe um ERRO na formula digitada

    argument #0 erros, expected C->U, function XmlParser

    Solucao

    Digite uma expressao valida

    ResponderExcluir
  26. Boa noite...

    Por curiosidade, WS não é minha praia, mas estou tentando aprender com o objetivo de fazer uma consulta ao sintegra em lote, ou seja, apos seleção dos pedidos a serem faturados , fazer que consulte o sintegra de todos, sem ter que ir cliente por cliente acoes relacionadas > mashup > sintegra ... ( regras da empresa ) ... Porém a totvs não fornece a chamada ou se que o fonte do de consulta do sintegra.

    Vc saberia me dizer como funciona o mashup do sintegra?

    outra coisa...

    ao roda o fonte, tive o seguinte retorno:

    ERR_FORM

    Problema,:
    Existe um ERRO na formula digitada

    argument #0 erros, expected C->U, function XmlParser

    Solucao

    Digite uma expressao valida

    ResponderExcluir
  27. Bom dia Marinaldo, amigo estou precisando fazer uma CONSULTA e ENVIO.Por exemplo, temos uma empresa homologada SERASA da qual coloca e tira o protesto, eu precisava fazer o ENVIO de XML e O RECEBIMENTO, mas nao sei por onde comecar, por gentileza, voce poderia me dar uma LUZ?

    ResponderExcluir
    Respostas
    1. Bruno, Primeiro você deve entrar em contato com a SERASA para obter os WS disponíveis para tal fim e, depois, criar os correspondentes no Protheus para "consumi-los"

      []s

      Excluir