Bom dia. Não sei o que estou fazendo de errado estou aprendendo a codificar em ADVPL a utilização de APIs via REST. Inclui uma nova API e coloquei dois métodos um GET e um POST o método GET consegui fazer sem problemas em ADVPL. Porém o método POST esta aparecendo a mensagem no console do REST que não conseguiu encontrar o método da erro 404 - Not Found. Alguem poderia me ajudar com relação a isso? Segue arquivo desenvolvido.
User Funcion EREST_01 é a criação do API
User Function EREST_02 é a utilização do método GET
User Function EREST_03 é a utilização do método POST
Atenção: Esta publicação foi transferida automaticamente do fórum antigo, mas os anexos não foram incluídos.
Existem diversos problemas em seu exemplo, tais como:
Declaração de classe produtos no fonte, mas sem utilização.
Utilização da função FWJsonDeserialize, essa função está depreciada.
Utilização da função FWMVCRotAuto já tendo o modelo instanciado e pronto para ser trabalhado.
Criação do método POST esperando receber informações na URL: {Fields}, mas isso é uma inserção, ainda não existe nada pra ser acessado.
Abrir o ambiente dentro do método POST com o PREPARE ENVIRONMENT.
Na função getJson, a criação do json está sendo feita com um bloco de código: {|| JsonObject():New()}
Você pegou a área corrente antes de manipular a SB1 e restaurou a mesma, correto, porém você não fez o mesmo para a área da SB1, que é exatamente a tabela que você manipulou.
Includes sem utilização, como o tbiconn.ch.
Veja aqui um exemplo com as correções dos erro citados acima:
#include "protheus.ch"
#include "fwmvcdef.ch"
#include "restful.ch"
//-------------------------------------------------------------------
/*{Protheus.doc} Produtos1
API para inserção e consulta de produtos (SB1)
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
WSRESTFUL Produtos1 DESCRIPTION "Serviço REST para manipulação de Produtos"
WSDATA CodProduto As String
WSMETHOD GET DESCRIPTION "Retorna o produto informado na URL" WSSYNTAX "/PRODUTOS1"
WSMETHOD POST DESCRIPTION "Retorna o produto informado na URL" WSSYNTAX "/PRODUTOS1" PATH "/PRODUTOS1" PRODUCES APPLICATION_JSON
END WSRESTFUL
//-------------------------------------------------------------------
/*{Protheus.doc} GET
Retorna um json com os dados do produto consultado
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
WSMETHOD GET WSRECEIVE CodProduto WSSERVICE Produtos1
local aAreaSB1 as array
Local aObjProd as array
Local aArea as array
Local cCodProd as char
Local cStatus as char
Local cJson as char
Local jObjProd
cCodProd := Self:CodProduto
aArea := GetArea()
aAreaSB1 := SB1->( GetArea() )
::SetContentType("application/json")
DbSelectArea("SB1")
SB1->( DbSetOrder(1) )
if SB1->( DbSeek( xFilial("SB1") + PadR(cCodProd,15) ) )
aObjProd := {}
cStatus := Iif( SB1->B1_MSBLQL == "1", "Sim", "Nao" )
aAdd( aObjProd, JsonObject():New() )
aObjProd[1]["Produto" ] := cCodProd
aObjProd[1]["Descricao" ] := SB1->B1_DESC
aObjProd[1]["Unidade Medida"] := SB1->B1_UM
aObjProd[1]["Status" ] := cStatus
jObjProd := JsonObject():New()
jObjProd["PRODUTOS1"] := aObjProd
cJson := jObjProd:toJson()
::setResponse(cJson)
else
setRestFault(404)
endIf
RestArea(aAreaSB1)
RestArea(aArea)
return .T.
//-------------------------------------------------------------------
/*{Protheus.doc} POST
Efetua a inserção de um produto com base no JSON recebido
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
WSMETHOD POST WSSERVICE Produtos1
local jProduto
local cError as char
local cJson as char
local cAlias as char
local lOk as logical
local aAreaSB1 as array
Self:SetContentType("application/json")
jProduto := JsonObject():New()
cError := jProduto:fromJson( self:getContent() )
lOk := .F.
if Empty(cError)]
cAlias := Alias()
aAreaSB1 := SB1->( GetArea() )
if !SB1->( DbSeek( xFilial("SB1") + jProduto["CODPRODUTO"]) )
oModel := FwLoadModel("MATA010")
oModel:setOperation(MODEL_OPERATION_INSERT)
oModel:Activate()
oModel:setValue("SB1MASTER", "B1_COD", jProduto["CODPRODUTO"])
oModel:setValue("SB1MASTER", "B1_DESC", jProduto["PRODDESC"])
oModel:setValue("SB1MASTER", "B1_GRUPO", jProduto["CODGRUPO"])
oModel:setValue("SB1MASTER", "B1_TIPO", jProduto["PRODTIPO"])
oModel:setValue("SB1MASTER", "B1_UM", jProduto["PRODUM"])
oModel:setValue("SB1MASTER", "B1_LOCPAD", jProduto["PRODLOCPAD"])
oModel:setValue("SB1MASTER", "B1_ORIGEM", jProduto["PRODORIGEM"])
if oModel:VldData()
lOk := oModel:CommitData()
cJson := '{"CODPRODUTO":"' + SB1->B1_COD + '"';
+ ',"msg":"' + "Sucesso" + '"';
+'}'
::SetResponse(cJson)
else
ConErr(oModel:GetErrorMessage()[MODEL_MSGERR_MESSAGE])
SetRestFault(400)
endif
oModel:Destroy()
FreeObj(oModel)
else
SetRestFault(400, "Produto já cadastrado: " + SB1->B1_COD)
endif
RestAlias(aAreaSB1)
if !Empty(cAlias)
DBSelectArea(cAlias)
endif
else
ConErr(cError)
setRestFault(400)
endif
return lOk
//-------------------------------------------------------------------
/*{Protheus.doc} EREST_02
Função para testes do método GET da API Produtos1
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
user function EREST_02()
local oRestClient as object
local aHeader as array
oRestClient := FWRest():New("http://10.21.1.24:8093")
aHeader := {"CODPRODUTO:300001"}
oRestClient:setPath("/resty/PRODUTOS1")
if oRestClient:Get(aHeader)
ConOut("GET", oRestClient:GetResult())
else
ConOut("GET", oRestClient:GetLastError())
endif
FreeObj(oRestClient)
return
//-------------------------------------------------------------------
/*{Protheus.doc} EREST_03
Função para testes do método POST da API Produtos1
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
user function EREST_03()
Local aHeader as array
Local cResource as char
Local cServer as char
Local cPort as char
Local cURI as char
Local oRestClient as object
aHeader := {}
cResource := "/PRODUTOS1"
cServer := "10.21.1.24" // URL (IP) DO SERVIDOR
cPort := "8093" // PORTA DO SERVIÇO REST
cURI := "http://" + cServer + ":" + cPort + "/resty" // URI DO SERVIÇO REST
oRestClient := FwRest():New(cURI)
AAdd(aHeader, "Content-Type: application/json; charset=UTF-8")
AAdd(aHeader, "Accept: application/json")
AAdd(aHeader, "User-Agent: Chrome/65.0 (compatible; Protheus " + GetBuild() + ")")
oRestClient:setPath(cResource)
oRestClient:SetPostParams(getJson())
if oRestClient:Post(aHeader)
ConOut("POST", oRestClient:GetResult())
else
ConOut("POST", oRestClient:GetLastError())
endIf
FreeObj(oRestClient)
return
//-------------------------------------------------------------------
/*{Protheus.doc} getJson
Retorna um json (Char) para o cadastro de produtos
@return Char - Json de produto
@author Daniel Mendes
@since 06/07/2020
@version 1.0
*/
//-------------------------------------------------------------------
static Function getJson()
local jJson
jJson := JsonObject():New()
jJson["CODGRUPO"] := "001"
jJson["CODPRODUTO"] := "001323"
jJson["PRODDESC"] := "TESTE PRODUTO3 API REST"
jJson["PRODTIPO"] := "PA"
jJson["PRODUM"] := "UN"
jJson["PRODLOCPAD"] := "01"
jJson["PRODORIGEM"] := "0"
return jJson:ToJson()
O que foi feito:
Tipagem das variáveis.
Correção da URL do método POST.
Remoção da abertura do ambiente no meio do método.
Remoção da utilização da função FWMVCRotAuto, agora o modelo é ativo e seus valores são inseridos diretamente no mesmo, isso também gera ganho de performance.
Remoção da utilização da função FWJsonDeserialize, agora sempre é utilizada a JsonObject, que retorna um JSON e não um objeto.
Espero ter ajudado, desculpe por reescrever grande parte das coisas, mas acho que ficou mais fácil para exemplificar.
Obrigado. Ajudou bastante. Valeu mesmo. Os exemplo que peguei na internet devem estar desatualizados mesmo, por isso esta cheio de falhas e atrelado ai isso estou aprendendo a trabalhar com API e REST ai ate entender como funciona vou apanhar muito ainda.