segunda-feira, 15 de setembro de 2014

Webservice no Protheus - Parte 2 - Montando uma aplicação básica

A partir deste post, você vera como testar uma aplicação básica

Montagem da classe do Webservice

Este Webservice terá a finalidade retornar os dados do cliente no Protheus, a aplicação .NET ira enviar uma solicitação que poderia ser no formato de um XML ou por passagem simples por parâmetros.
Para não complicar muito, o primeiro exemplo de passagem de parâmetros é mais indicado.

O resultado final é o retorno do Nome do cliente, endereço, bairro, cidade, uf e CEP.
A passagem de parâmetros será o código do cliente e a loja.

No exemplo abaixo, não fiz nenhum tipo de validação e não estou preocupado com isso neste momento, fica a cargo de meus leitores corrigir o programa.
Em meus projetos consulto usuários, bloqueio senhas, envio estruturas complexas de XML, etc.

Então, mão na massa.

Primeiro, crie um arquivo no seu projeto, no meu caso criei com o nome MeuPrimeiroWebService.PRW

#INCLUDE 'PROTHEUS.CH'
#INCLUDE "XMLXFUN.CH"
#INCLUDE "APWEBSRV.CH"
#include "topconn.ch"
#INCLUDE "RWMAKE.CH"
#INCLUDE "TBICONN.CH"
#INCLUDE "ERROR.CH"

// Estrutura de dados. Montagem do Array de retorno
// Não necessariamente retorna-se em um Array, pode ser possível retornar em uma string simples,
// neste caso não utilizaria uma Estrutura
WSSTRUCT AWSRTDados
    WSDATA ClienteNome     AS String
    WSDATA ClienteEndereco AS String
    WSDATA ClienteBairro   AS String
    WSDATA ClienteCidade   AS String
    WSDATA ClienteUF           AS String
    WSDATA ClienteCEP          As String
ENDWSSTRUCT 

// WebService
WSSERVICE MeuPrimeiroWebService DESCRIPTION "Descrição do meu primeiro WebService"
       // Passagem dos parâmetros de entrada
       WSDATA ClienteCodigo  AS string
       WSDATA ClienteLoja    AS string
      
       // Retorno de um array que deve retornar a COLUNA 1, COLUNA 2
       WSDATA aRetornoCliente AS ARRAY OF AWSRTDados

       // Descrição dos métodos que o WEBSERVICE pode possuir
       /*WSMETHOD ExcluiOrdem     DESCRIPTION "Efetua a exclusão de uma ordem de faturamento"
       WSMETHOD DeletaNfSaida   DESCRIPTION "Consulta ou exclui uma nota fiscal de vendas"
       WSMETHOD DeletaNfEntrada DESCRIPTION "Consulta ou exclui uma nota fiscal de compras"
       WSMETHOD AtualizaProduto DESCRIPTION "Inclui / Altera um produto no Microsiga SB1"
       WSMETHOD MeuXML          DESCRIPTION "Meu XML"
       WSMETHOD SenhaProtheus   DESCRIPTION "Teste se a senha esta Ok"*/
      
       WSMETHOD ConsultarCliente DESCRIPTION "Retorna os dados do cliente"
      
ENDWSSERVICE

/************************************************************************************
** Consulta os dados do cliente
** Abaixo, separei o que se refere do webservice da aplicação que realmente ira
** processar os dados. Lembrando que não é obrigatório
************************************************************************************/
WSMETHOD ConsultarCliente WSRECEIVE ClienteCodigo, ClienteLoja WSSEND aRetornoCliente WSSERVICE MeuPrimeiroWebService
Local aRetFuncao := {}

    aRetFuncao     := u_xxRtCliente(::ClienteCodigo,::ClienteLoja) // Passagem de parâmetros para rotina
  
    aAdd(::aRetornoCliente, WSClassNew("AWSRTDados") )
    ::aRetornoCliente[01]:ClienteNome    := aRetFuncao[1][1]
    ::aRetornoCliente[01]:ClienteEndereco:= aRetFuncao[2][1]
    ::aRetornoCliente[01]:ClienteBairro  := aRetFuncao[3][1]
    ::aRetornoCliente[01]:ClienteCidade  := aRetFuncao[4][1]
    ::aRetornoCliente[01]:ClienteUF      := aRetFuncao[5][1]
    ::aRetornoCliente[01]:ClienteCEP     := aRetFuncao[6][1]

Return .T.

/*************************************************************
** Retorna os dados do cliente
**************************************************************/
User Function xxRtCliente(pClienteCodigo, pClienteLoja)
Local aRetornoDados         := {}
Local aTables    := { "SA1","SM0" }

Conout(dtoc( Date() )+" "+Time()+ " == Abrindo ambiente TOP CONNECT =======")
RPCSetType( 3 )
RpcSetEnv ( "01", "01", Nil, Nil, "FAT", Nil, aTables )

SA1->(DbSetOrder(1))
SA1->(DbGoTop())

If SA1->(DbSeek(xFilial("SA1") + pClienteCodigo+ pClienteLoja))
         aAdd(aRetornoDados ,{SA1->A1_NOME                       })  // 1
         aAdd(aRetornoDados ,{SA1->A1_END                       })  // 2
         aAdd(aRetornoDados ,{SA1->A1_BAIRRO                     })  // 3
         aAdd(aRetornoDados ,{SA1->A1_MUN                        })       // 4
         aAdd(aRetornoDados ,{SA1->A1_EST                        })       // 5
         aAdd(aRetornoDados ,{SA1->A1_CEP                        })  // 6
Else
         aAdd(aRetornoDados ,{Nil})  // 1
         aAdd(aRetornoDados ,{Nil})  // 2
         aAdd(aRetornoDados ,{Nil})  // 3
         aAdd(aRetornoDados ,{Nil})  // 4
         aAdd(aRetornoDados ,{Nil})  // 5
         aAdd(aRetornoDados ,{Nil})  // 6     
Endif

Return aRetornoDados

Feito isto, vamos verificar se não existe nenhum erro na compilação pesquisando pelo o endereço ja configurado. A configuração expliquei na Parte 1

http://192.168.15.86:889/ws/WSINDEX.apw 



Ao clicar no link, aparece a configuração que deve ser utizada no Visual Studio ou qualquer outra aplicação


Vamos agora no Visual Studio...

Em adicionar referência, colar o link MEUPRIMEIROWEBSERVICE.apw?WSDL conforme figura abaixo :


No visual Studio vamos montar uma telinha


Agora, vamos montar um código simples, quero deixar claro que não sou especialista em c#, sou um mero fuçador.

private void button1_Click(object sender, EventArgs e)
        {
            // Instanciamos a nossa referência com o WebService do Protheus
            ClientWSProtheus.MEUPRIMEIROWEBSERVICESOAPClient aleksandro = new ClientWSProtheus.MEUPRIMEIROWEBSERVICESOAPClient();

            // Montamos uma ILIST, poderia ser uma string qualquer, existem diversas formas de fazer
            IList<AWSRTDADOS> aRetorno;

            // Chamo o método e retorno em um array
            aRetorno = aleksandro.CONSULTARCLIENTE(ParamCodigo.Text, ParamLoja.Text);

            // Jogo nos campos os dados da empresa
            textBox3.Text = aRetorno[0].CLIENTENOME.ToString();
            textBox4.Text = aRetorno[0].CLIENTEENDERECO.ToString();
            textBox5.Text = aRetorno[0].CLIENTEBAIRRO.ToString();
            textBox6.Text = aRetorno[0].CLIENTECIDADE.ToString();
            textBox7.Text = aRetorno[0].CLIENTECEP.ToString();
            textBox8.Text = aRetorno[0].CLIENTEUF.ToString();

        }

Executando o programa, vejamos o que o Protheus ira retornar


Pronto, a consulta foi feita unicamente pelo WEBSERVICE sem se conectar diretamente na base de dados.

Da mesma forma que podemos fazer uma consulta, também é possível fazer um programa EXECAUTO, ou rodar rotinas padrão do Protheus.

Esta foi uma forma de fazer, mas existem diversas maneiras. Queria somente ilustrar uma delas.



Webservice no Protheus - Parte 1 - Configurando o Protheus

Configurando o WebService no Protheus

Antes de iniciarmos o estudo do WebService, é imprescindível a configuração do serviço do Protheus.

Para isto devemos ter um serviço separado dos outros. A separação é recomendada mas não é obrigatória.

Não estou explicando de forma detalhada cada linha da configuração abaixo, devido a documentação estar disponível no portal TDN da Totvs. Estou focando no uso geral da aplicação WebService.

Abaixo, segue um modelo do WebService que utilizo


[WEBSERVICE]
SourcePath=E:\PROTHEUS11\APO\WEBSERVICE
RootPath=E:\PROTHEUS11\Protheus_Data
StartPath=\system\
x2_path=
RpoDb=Top
RpoLanguage=portuguese
RpoVersion=110
LocalFiles=ads
Trace=0
localdbextension=.dbf
PictFormat=AMERICAN
DateFormat=DEFAULT
RegionalLanguage=BRA

Note que no trecho acima, não tem nada de diferente do que utilizamos normalmente.

[192.168.14.33:82/ws]
ENABLE=1
PATH=e:\Protheus11\Protheus_Data\web\ws
ENVIRONMENT=WEBSERVICE
INSTANCENAME=Ws
RESPONSEJOB=JOB_WS_9901
DEFAULTPAGE=wsindex.apw

No trecho acima, estamos configurando o endereço, nome do ambiente, nome dos jobs e página de índice com os nomes dos serviços disponíveis do nosso WebService.

[JOB_WS_9901]
TYPE=WEBEX
ENVIRONMENT=WEBSERVICE
INSTANCES=1,80
SIGAWEB=WS
INSTANCENAME=Ws
ONSTART=__WSSTART
ONCONNECT=__WSCONNECT

No trecho acima, mencionamos o nome do Job, ambiente, quantidade de instâncias simultâneas.

[TopConnect]
DataBase=ORACLE
Server=NOMESERVIDOR
ALIAS=PROTHEUS
PROTHEUSONLY=0

[Drivers]
Active=TCP

[TCP]
TYPE=TCPIP
Port=1255

[General]
InstallPath=E:\PROTHEUS11

[LICENSECLIENT]
SERVER=SERVIDORLICENCA
port=5555

[HTTP]
enable=1
port=82
PATH=e:\PROTHEUS11\PROTHEUS_DATA\web\ws
ENVIRONMENT=WEBSERVICE

[MAIL]
Protocol=POP3

Montando a aplicação