quinta-feira, 19 de agosto de 2010

Consumindo um WebService usando ADVPL

Olá Pessoal, vou mostrar um exemplo de como consumir um webservice usando o advpl. Eu achei um site que possui alguns webservices que podem ser consumidos para teste. o site é http://www.webservicex.net/WCF/webServices.aspx. Este site possui vários webservices, eu escolhi para demonstrar a vocês um que converte byte em todas as outras unidades (Kilobyte, Gigabyte, TeraByte, PetaByte) ou vice-versa. O WebService que vamos usar chama-se ComputerUnit, veja http://www.webservicex.net/WCF/ServiceDetails.aspx?SID=68 para ver os detalhes. Nesta pagina ele mostra qual é o endereço para gerar o client deste serviço (http://www.webservicex.net/ConvertComputer.asmx?wsdl). Este WS recebe 3 parâmetros e retorna 1 parâmetro.
Primeiramente vamos gerar o client deste WS no TotvsDevStudio (IDE). Para isso crie um arquivo novo, vá até o menu Ferramentas - Gerar Cliente WebServices. Na janela que será exibida, informe o endereço do WSDL deste serviço que é http://www.webservicex.net/ConvertComputer.asmx?wsdl. O TotvsDevStudio criará automaticamente o client do WS, conforme abaixo.

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

/* ===============================================================================
WSDL Location    http://www.webservicex.net/ConvertComputer.asmx?wsdl
Gerado em        08/19/10 10:42:26
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 _ZJNIQRC ; Return  // "dummy" function - Internal Use

/* -------------------------------------------------------------------------------
WSDL Service WSComputerUnit
------------------------------------------------------------------------------- */

WSCLIENT WSComputerUnit

    WSMETHOD NEW
    WSMETHOD INIT
    WSMETHOD RESET
    WSMETHOD CLONE
    WSMETHOD ChangeComputerUnit

    WSDATA   _URL                      AS String
    WSDATA   nComputerValue            AS double
    WSDATA   oWSfromComputerUnit       AS ComputerUnit_Computers
    WSDATA   oWStoComputerUnit         AS ComputerUnit_Computers
    WSDATA   nChangeComputerUnitResult AS double

ENDWSCLIENT

WSMETHOD NEW WSCLIENT WSComputerUnit
::Init()
If !FindFunction("XMLCHILDEX")
    UserException("O Código-Fonte Client atual requer os executáveis do Protheus Build [7.00.090818P-20100630] ou superior. Atualize o Protheus ou gere o Código-Fonte novamente utilizando o Build atual.")
EndIf
If val(right(GetWSCVer(),8)) < 1.040504
    UserException("O Código-Fonte Client atual requer a versão de Lib para WebServices igual ou superior a ADVPL WSDL Client 1.040504. Atualize o repositório ou gere o Código-Fonte novamente utilizando o repositório atual.")
EndIf
Return Self

WSMETHOD INIT WSCLIENT WSComputerUnit
    ::oWSfromComputerUnit := ComputerUnit_COMPUTERS():New()
    ::oWStoComputerUnit  := ComputerUnit_COMPUTERS():New()
Return

WSMETHOD RESET WSCLIENT WSComputerUnit
    ::nComputerValue     := NIL
    ::oWSfromComputerUnit := NIL
    ::oWStoComputerUnit  := NIL
    ::nChangeComputerUnitResult := NIL
    ::Init()
Return

WSMETHOD CLONE WSCLIENT WSComputerUnit
Local oClone := WSComputerUnit():New()
    oClone:_URL          := ::_URL
    oClone:nComputerValue := ::nComputerValue
    oClone:oWSfromComputerUnit :=  IIF(::oWSfromComputerUnit = NIL , NIL ,::oWSfromComputerUnit:Clone() )
    oClone:oWStoComputerUnit :=  IIF(::oWStoComputerUnit = NIL , NIL ,::oWStoComputerUnit:Clone() )
    oClone:nChangeComputerUnitResult := ::nChangeComputerUnitResult
Return oClone

// WSDL Method ChangeComputerUnit of Service WSComputerUnit

WSMETHOD ChangeComputerUnit WSSEND nComputerValue,oWSfromComputerUnit,oWStoComputerUnit WSRECEIVE nChangeComputerUnitResult WSCLIENT WSComputerUnit
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<ChangeComputerUnit xmlns="http://www.webserviceX.NET/">'
cSoap += WSSoapValue("ComputerValue", ::nComputerValue, nComputerValue , "double", .T. , .F., 0 , NIL, .F.)
cSoap += WSSoapValue("fromComputerUnit", ::oWSfromComputerUnit, oWSfromComputerUnit , "Computers", .T. , .F., 0 , NIL, .F.)
cSoap += WSSoapValue("toComputerUnit", ::oWStoComputerUnit, oWStoComputerUnit , "Computers", .T. , .F., 0 , NIL, .F.)
cSoap += "ChangeComputerUnit>"

oXmlRet := SvcSoapCall(    Self,cSoap,;
    "http://www.webserviceX.NET/ChangeComputerUnit",;
    "DOCUMENT","http://www.webserviceX.NET/",,,;
    "http://www.webservicex.net/ConvertComputer.asmx")

::Init()
::nChangeComputerUnitResult :=  WSAdvValue( oXmlRet,"_CHANGECOMPUTERUNITRESPONSE:_CHANGECOMPUTERUNITRESULT:TEXT","double",NIL,NIL,NIL,NIL,NIL,NIL)

END WSMETHOD

oXmlRet := NIL
Return .T.


// WSDL Data Enumeration Computers

WSSTRUCT ComputerUnit_Computers
    WSDATA   Value                     AS string
    WSDATA   cValueType                AS string
    WSDATA   aValueList                AS Array Of string
    WSMETHOD NEW
    WSMETHOD CLONE
    WSMETHOD SOAPSEND
    WSMETHOD SOAPRECV
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT ComputerUnit_Computers
    ::Value := NIL
    ::cValueType := "string"
    ::aValueList := {}
    aadd(::aValueList , "Bit" )
    aadd(::aValueList , "Byte" )
    aadd(::aValueList , "Kilobyte" )
    aadd(::aValueList , "Megabyte" )
    aadd(::aValueList , "Gigabyte" )
    aadd(::aValueList , "Terabyte" )
    aadd(::aValueList , "Petabyte" )
Return Self

WSMETHOD SOAPSEND WSCLIENT ComputerUnit_Computers
    Local cSoap := ""
    cSoap += WSSoapValue("Value", ::Value, NIL , "string", .F. , .F., 3 , NIL, .F.)
Return cSoap

WSMETHOD SOAPRECV WSSEND oResponse WSCLIENT ComputerUnit_Computers
    ::Value := NIL
    If oResponse = NIL ; Return ; Endif
    ::Value :=  oResponse:TEXT
Return

WSMETHOD CLONE WSCLIENT ComputerUnit_Computers
Local oClone := ComputerUnit_Computers():New()
    oClone:Value := ::Value
Return oClone


Salve o arquivo com o nome que desejar, e compile este fonte.
Veja agora no exemplo abaixo como consumir este WS:


#include "protheus.ch"
User Function FUConsumirWS()
    // Criando o objeto Web Service
    _oWSTeste := WSComputerUnit():New()
    // A Variavel NCOMPUTERVALUE é o numero que deseja converter
    _oWSTeste:NCOMPUTERVALUE := 1000   
    // A Variavel _oWSTeste:oWSFROMCOMPUTERUNIT:VALUE é de qual medida deseja 
    // converter
    _oWSTeste:oWSFROMCOMPUTERUNIT:VALUE := "Gigabyte"                            
    // A Variavel _oWSTeste:oWSFROMCOMPUTERUNIT:VALUE é para qual medida deseja
    // converter
    _oWSTeste:oWSTOCOMPUTERUNIT:VALUE        := "Kilobyte"
    // Executa o metodo ChangeComputerUnit
    _oWSTeste:ChangeComputerUnit()       
    // Mostra o resultado
    MsgStop(_oWSTeste:NCHANGECOMPUTERUNITRESULT)
Return

Estas variáveis que utilizo na função acima foram criadas pelo client do WS, todos os clients gerados pelo Protheus seguem esse modelo, portanto voce poderá consumir o WS que desejar.

Qualquer duvida deixe seu recado.

Um abraço

8 comentários:

  1. Este comentário foi removido pelo autor.

    ResponderExcluir
  2. Tadeu você sabe me dizer se o advpl tem suporte para utilização do cabeçalho SOAP, ou seja autenticação via cabeçalho soap e tudo mais?
    abs!

    ResponderExcluir
  3. Ola #_FØX_ØF_ÑËT_#.

    Não tenho conhecimento que o ADVPL possui esse recurso. Vou pesquisar sobre isso

    ResponderExcluir
    Respostas
    1. Ola Tadeu,
      você conseguiu achar algo nesse sentido de autenticação via cabeçalho...
      att...

      Excluir
  4. Tadeu,
    Eu estou começando a estudar ADVPL e desenvolvimento para o Protheus.
    por acaso tem alguma versão do Protheus para desenvolvedores estudar e testar as rotinas criadas?

    ResponderExcluir
  5. Olá! td bem?
    O ADVPL aceita URL dinamica? Tenho um projeto que preciso consumir URL's dinamicas. O projeto que preciso consumir foi feito .net, através do REST, ele cria URL dinamicas.
    Ex: Pra eu atualizar clientes eu preciso fazer:
    http://sitedocliente.com.br/api/clientes/1014/atualizar
    Sendo que o 1014 é o código do cliente.
    Desde já obrigado!
    Abrs
    Fernando

    ResponderExcluir
  6. Boa Tarde
    Quando o DevStudio retorna o erro 405 Metodo nao permitido, o que pode causar isso ? No caso é um webservices nao protheus que preciso consumir.
    Obrigado
    Rafael
    rafaelnogueira.jf@gmail.com

    ResponderExcluir