Nesse vídeo demonstraremos a utilização do comando WsService, que serve para criar um WebService do tipo SOAP.
Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:
//Bibliotecas
#Include "TOTVS.ch"
#Include "APWebSrv.ch"
/*/{Protheus.doc} WsService zWSClientes
Exemplo de WebService usando SOAP
@author Atilio
@since 07/04/2022
@version 1.0
@see https://tdn.totvs.com/display/tec/WSSERVICE
@obs
**** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/
WsService zWSClientes Description "WebService com funcoes de clientes"
//Atributos
WsData cViewRece as String
WsData cViewSend as String
WsData cNewRece as String
WsData cNewSend as String
//Métodos
WsMethod ViewCli Description "Metodo para visualizar clientes"
WsMethod NewCli Description "Metodo para incluir clientes"
EndWsService
/*/{Protheus.doc} WsMethod ViewCli
Visualiza as informações de um cliente
@author Atilio
@since 03/06/2022
@param cViewRece, Caractere, Estrutura xml com o código do cliente ou cnpj / cpf
@obs Será retornado um XML com os dados do cadastro
/*/
WsMethod ViewCli WsReceive cViewRece WsSend cViewSend WsService zWSClientes
Local aArea := FWGetArea()
Local lRet := .T.
Local cBusca := Alltrim(::cViewRece)
Local nIndice := 0
Local cCGC := ""
Local cMascCPF := "@R 999.999.999-99"
Local cMascCNPJ := "@R 99.999.999/9999-99"
//Retira pontos, hífens e barras da busca (para o caso se o usuário digitou o cpf ou cnpj com esses caracteres)
cBusca := StrTran(cBusca, ".", "")
cBusca := StrTran(cBusca, "/", "")
cBusca := StrTran(cBusca, "-", "")
//Se o tamanho da busca for de 14 caracteres, é um CNPJ. Ou se for 11 caracteres, é um CPF
If Len(cBusca) == 14 .Or. Len(cBusca) == 11
nIndice := 3 //A1_FILIAL + A1_CGC
//Senão, irá usar o índice padrão, por código e loja do cliente
Else
nIndice := 1 //A1_FILIAL + A1_COD + A1_LOJA
EndIf
//Tenta posicionar no cliente
DbSelectArea("SA1")
SA1->(DbSetOrder(nIndice))
If SA1->(MsSeek(FWxFilial("SA1") + cBusca))
cCGC := Alltrim(SA1->A1_CGC)
::cViewSend := '{' + CRLF
::cViewSend += ' "dados":{' + CRLF
::cViewSend += ' "status":"Cliente encontrado",' + CRLF
::cViewSend += ' "codigo":"' + SA1->A1_COD + SA1->A1_LOJA + '",' + CRLF
If Len(cCGC) == 14
::cViewSend += ' "cnpj":"' + Alltrim(Transform(cCGC, cMascCNPJ)) + '",' + CRLF
ElseIf Len(cCGC) == 11
::cViewSend += ' "cpf":"' + Alltrim(Transform(cCGC, cMascCPF)) + '",' + CRLF
EndIf
::cViewSend += ' "nome":"' + Alltrim(SA1->A1_NOME) + '",' + CRLF
::cViewSend += ' "email":"' + Alltrim(SA1->A1_EMAIL) + '",' + CRLF
::cViewSend += ' "site":"' + Alltrim(SA1->A1_HPAGE) + '"' + CRLF
::cViewSend += ' }' + CRLF
::cViewSend += '}' + CRLF
Else
::cViewSend := '{' + CRLF
::cViewSend += ' "dados":{' + CRLF
::cViewSend += ' "status":"Cliente nao encontrado com a chave fornecida"' + CRLF
::cViewSend += ' }' + CRLF
::cViewSend += '}' + CRLF
EndIf
FWRestArea(aArea)
Return lRet
/*/{Protheus.doc} WsMethod NewCli
Cadastra um novo cliente
@author Atilio
@since 03/06/2022
@param cNewRece, Caractere, XML com os campos obrigatórios do cadastro de clientes
@obs Será retornado um XML com a informação de sucesso ou falha na inclusão
/*/
WsMethod NewCli WsReceive cNewRece WsSend cNewSend WsService zWSClientes
Local aArea := FWGetArea()
Local lRet := .T.
Local jJsonRece
Local cError := ""
Local jResponse := JsonObject():New()
Local cDirLog := '\x_logs\'
Local nLinha
Local aDados := {}
Private lMsHelpAuto := .T.
Private lAutoErrNoFile := .T.
Private lMsErroAuto := .F.
//Recebe o texto e transforma em objeto
jJsonRece := JsonObject():New()
cError := jJsonRece:FromJson(::cNewRece)
//Se tiver algum erro no Parse, encerra a execução
IF ! Empty(cError) .Or. Len(::cNewRece) < 20
jResponse['errorId'] := 'NEW001'
jResponse['error'] := 'Parse do JSON'
jResponse['solution'] := 'Erro ao fazer o Parse do JSON'
Else
//Se algum dos campos estiver vazio
If Empty(jJsonRece:GetJsonObject('cod')) .Or. ;
Empty(jJsonRece:GetJsonObject('loja')) .Or. ;
Empty(jJsonRece:GetJsonObject('nome')) .Or. ;
Empty(jJsonRece:GetJsonObject('nreduz')) .Or. ;
Empty(jJsonRece:GetJsonObject('tipo')) .Or. ;
Empty(jJsonRece:GetJsonObject('end')) .Or. ;
Empty(jJsonRece:GetJsonObject('mun')) .Or. ;
Empty(jJsonRece:GetJsonObject('est'))
jResponse['errorId'] := 'NEW002'
jResponse['error'] := 'Campo(s) obrigatorio(s)'
jResponse['solution'] := 'Existem campos que nao foram enviados, revise a estrutura do seu JSON'
Else
//Adiciona no array
aAdd(aDados, {'A1_COD', jJsonRece:GetJsonObject('cod'), Nil})
aAdd(aDados, {'A1_LOJA', jJsonRece:GetJsonObject('loja'), Nil})
aAdd(aDados, {'A1_NOME', jJsonRece:GetJsonObject('nome'), Nil})
aAdd(aDados, {'A1_NREDUZ', jJsonRece:GetJsonObject('nreduz'), Nil})
aAdd(aDados, {'A1_TIPO', jJsonRece:GetJsonObject('tipo'), Nil})
aAdd(aDados, {'A1_END', jJsonRece:GetJsonObject('end'), Nil})
aAdd(aDados, {'A1_MUN', jJsonRece:GetJsonObject('mun'), Nil})
aAdd(aDados, {'A1_EST', jJsonRece:GetJsonObject('est'), Nil})
//Chama a inclusão automática
MsExecAuto({|x, y| CRMA980(x, y)}, aDados, 3)
//Se houve erro, gera um arquivo de log dentro do diretório da protheus data
If lMsErroAuto
//Monta o texto do Error Log que será salvo
cErrorLog := ''
aLogAuto := GetAutoGrLog()
For nLinha := 1 To Len(aLogAuto)
cErrorLog += aLogAuto[nLinha] + CRLF
Next nLinha
//Grava o arquivo de log
cArqLog := 'zWSClientes_New_' + dToS(Date()) + '_' + StrTran(Time(), ':', '-') + '.log'
MemoWrite(cDirLog + cArqLog, cErrorLog)
//Define o retorno para o WebService
jResponse['errorId'] := 'NEW003'
jResponse['error'] := 'Erro na inclusao do registro'
jResponse['solution'] := 'Nao foi possivel incluir o registro, foi gerado um arquivo de log em ' + cDirLog + cArqLog + ' '
//Senão, define a mensagem de retorno
Else
jResponse['note'] := 'Registro incluido com sucesso'
EndIf
EndIf
EndIf
//Agora pega o json da Resposta e joga para o retorno do WS
::cNewSend := jResponse:toJSON()
FWRestArea(aArea)
Return lRet
Bom pessoal, por hoje é só.
Abraços e até a próxima.