Consumo de API REST Externa em ADVPL
- Eloy Vanço
- há 9 horas
- 3 min de leitura
Este documento descreve a função ADVPL `u_fConsomeAPIExterna`, contida no arquivo `consumo_api_externa.prw`, que tem como objetivo consumir um endpoint REST externo, tratar a resposta (incluindo o parsing de JSON) e retornar os dados de forma estruturada.
## Funcionalidade Principal
A função `u_fConsomeAPIExterna` realiza uma requisição HTTP GET para a URL pré-definida:
`http://a36a0bdb7c74.sn.mynetname.net:9004/Integracao/Exportar?tokenapi=6f08c62f1e2ad2ecfe743af04638b679be7e7e1d`
Ela utiliza a classe `FWRest` do Protheus para realizar a comunicação e a classe `JsonObject` para fazer o parse da resposta JSON.
## Estrutura do Retorno
A função retorna um array ADVPL com a seguinte estrutura:
* **Em caso de sucesso na requisição e no parse do JSON:**
```advpl
{
{"status", "OK"},
{"dados", oJsonData}, // oJsonData é um objeto JsonObject com os dados da API
{"http_code", nHttpCode} // nHttpCode é o código de status HTTP (ex: 200)
}
```
* **Em caso de erro (falha na requisição HTTP ou falha no parse do JSON):**
```advpl
{
{"status", "ERRO"},
{"mensagem", cMensagemErro}, // String com a descrição do erro
{"http_code", nHttpCode}, // Código de status HTTP (ex: 500, 404, etc.)
// Opcional, em caso de erro no parse:
// {"json_bruto", cJsonResponse} // String com o JSON bruto recebido, se houver erro no parse
}
```
## Como Utilizar
1. **Inclusão:** Certifique-se de que o arquivo `consumo_api_externa.prw` esteja compilado e acessível no RPO do seu ambiente Protheus.
2. **Chamada da Função:** Você pode chamar a função da seguinte maneira em seu código ADVPL:
```advpl
#INCLUDE "PROTHEUS.CH"
User Function MinhaRotina()
Local aRetornoAPI := u_fConsomeAPIExterna()
Local oDados := NIL
Local cMensagem := ""
If aRetornoAPI[1][2] == "OK"
oDados := aRetornoAPI[2][2] // Objeto JsonObject
ConOut("Sucesso! Status HTTP: " + AllTrim(Str(aRetornoAPI[3][2])))
// Para visualizar o JSON completo (pode ser grande):
ConOut("JSON Recebido: " + oDados:ToJson())
// Exemplo de como acessar um campo específico do JSON (adapte ao seu JSON):
// If oDados:HasProperty("nomeDoCampo")
// ConOut("Valor do campo 'nomeDoCampo': " + oDados:Get("nomeDoCampo"))
// Else
// ConOut("O campo 'nomeDoCampo' não existe no JSON.")
// EndIf
// ... processe os dados conforme necessário ...
Else
cMensagem := aRetornoAPI[2][2]
ConOut("Erro ao consumir API! Status HTTP: " + AllTrim(Str(aRetornoAPI[3][2])))
ConOut("Mensagem de Erro: " + cMensagem)
If Len(aRetornoAPI) > 3 .And. Upper(aRetornoAPI[4][1]) == "JSON_BRUTO"
ConOut("JSON Bruto (falha no parse): " + aRetornoAPI[4][2])
EndIf
EndIf
Return
```
## Detalhes do Código (`consumo_api_externa.prw`)
* **Includes:** `PROTHEUS.CH`, `FWMVCDEF.CH`, `TLPPCORE.CH`, `RESTFUL.CH` são incluídos para acesso às funcionalidades necessárias.
* **URL:** A URL do endpoint está definida na variável `cUrl`.
* **FWRest:** A classe `FWRest` é utilizada para criar o cliente REST e realizar a requisição `Get()`.
* **Tratamento de Resposta:**
* O código de status HTTP é obtido com `oRest:GetResultCode()`.
* O corpo da resposta (JSON string) é obtido com `oRest:GetResult()`.
* **Parsing de JSON:**
* A classe `JsonObject` é utilizada para converter a string JSON em um objeto ADVPL manipulável.
* `uJsonData:FromJson(cJsonResponse)` tenta realizar o parse.
* **Tratamento de Erros:**
* Verifica se a requisição HTTP foi bem-sucedida (`lRet` retornado por `oRest:Get()`).
* Verifica se o parse do JSON foi bem-sucedido.
* Retorna mensagens de erro detalhadas e o código de status HTTP.
* Em caso de falha no parse do JSON, o JSON bruto também é retornado para facilitar a depuração.
* **Ambiente RPC:** `RpcSetEnv()` e `RpcClearEnv()` são utilizados para garantir a execução no servidor, mas devem ser ajustados conforme a necessidade e o contexto de execução da função no seu ambiente Protheus.
## Observações Importantes
* **Erro 500 - "Invalid variant operation":** Ao testar o endpoint fornecido diretamente no navegador, foi observado um erro HTTP 500 com a mensagem `{"errorCode":500,"error":{"EVariantInvalidOpError":{"EVariantInvalidOpError":"Invalid variant operation"}}}`. Este erro origina-se no servidor da API e não no código ADVPL cliente. A função ADVPL está preparada para capturar esse tipo de erro HTTP e retornar as informações para tratamento.
* **Estrutura do JSON:** O código ADVPL assume que a API retorna um JSON válido. Se a estrutura do JSON for conhecida, você pode adicionar lógicas para acessar campos específicos do objeto `uJsonData` após o parse bem-sucedido.
* **Autenticação:** Neste exemplo, o token de API é passado diretamente na URL (`tokenapi=...`). Se a API exigir outros métodos de autenticação (como Headers de Autorização), o objeto `oRest` da classe `FWRest` possui métodos para configurar cabeçalhos (`oRest:SetHeaders()`).
* **Timeout:** Para requisições que podem demorar, considere configurar timeouts utilizando os métodos apropriados da classe `FWRest` ou `FWHttpClient`.
Este guia deve fornecer uma base sólida para utilizar e entender a função de consumo da API REST em ADVPL.
Comments