Histórico da Página
Objetivo
...
Apresentar os a documentação dos recursos da API Totvs-REST para serem utilizados por outras aplicações do Datasul. Ao oferecer de forma encapsulada esses recursos para que outras aplicações possam acessá-los, torná-se possível o Reuso, a Centralização e Integração:
- Reuso de lógicas, uma vez que ao expor um método ou uma função por exemplo, o código do respectivo não precisa ser duplicado no contexto da solução;
- Centralizar lógica (premissa para coesão) que viabiliza em um único ponto de uma solução o acesso a tal lógica;
- Viabilizar integração com outras aplicações quando se tata de uma integração em “baixo nível”, o que causa demanda de acesso a recursos internos da aplicação.
Para modelar a estrutura da documentação será utilizada a ferramentaSWAGGER
que, neste contexto faz uso do formatoYAML
de serialização de dados.
Semântica dos métodos HTTP
...
No universo REST, uma requisição HTTP pode-se dizer que é equivalente a uma chamada de uma 'procedure' progress.
...
- GET - método para recuperação de dados,
- POST - método para para inserir dados,
- PUT - método para alterar dados existentes e
- DELETE - método para apagar dados;
O API Manager (WSO2) junto ao produto Datasul funciona como um controlador dos serviços disponíveis no ERP; é ele quem efetua a exposição, o roteamento e a análise estatística de execuções e disponibilidade (SLA). O front-end, para consumo de um serviço, se comunica diretamente com o API Manager, efetuando a autenticação junto ao mesmo. Após se autenticar, todos os serviços solicitados são roteados ao back-end de destino para serem processados, no caso do produto Datasul, via DATASUL-REST / TOTVS-REST, conforme figura abaixo:
Para o processo de autenticação, o front-end ao executar uma requisição de serviço, caso não possua uma autenticação válida no API Manager (não possua um GUID válido), será redirecionado ao login configurado (Identity Server). São vários os formatos possíveis de autenticação passíveis de serem configurados, tais como LDAP, Fluig Identity, a base de usuários do produto, entre outros.
Já autenticado, ao solicitar a requisição, o API Manager fará a geração de um token JWT, gerado a partir de uma chave privada, que será anexado ao Header da requisição que será enviada ao back-end. No back-end, o token JWT será verificado, no caso do produto Datasul ou no TOTVS-LOGIN ou no JOSSO, liberando a requisição para ser processada no DATASUL-REST / TOTVS-REST. Na figura abaixo, é apresentado a sequencia dos eventos de autenticação:
O fluxo da requisição, partindo do fron-end, pode ser observado na figura abaixo, nele é descrito tanto o processo de autenticação, como o fluxo de processamento da requisição, em uma segunda visão:
A requisição a ser processada no back-end do produto Datasul (DATASUL-REST / TOTVS-REST) será encapsulada em um objeto JSON que poderá ser acessado no programa Progress que efetuará a execução efetiva do serviço. Neste objeto JSON, conterá informações completas da requisição, desde informações do HEADER, como QUERY PARAMs, PATH PARAMs, o próprio PAYLOAD e arquivos MULTIPART, como pode ser observado na figura abaixo:
...
Exemplo de Documentação para API Totvs-REST
...
O Parser SWAGGER realizará a leitura de um arquivo externo, em formato YAML e validará o conteúdo apontado para um arquivo PROGRESS. O resultado do "parseamento" será um arquivo em formato JSON.
Informações | ||||
---|---|---|---|---|
| ||||
O |
Para elucidar a utilização da API Totvs-Rest segue um exemplo de como realizar as chamadas utilizando o 'SWAGGER
' para gerar a documentação. Assim, o exemplo seguirá sempre o padrão: Bloco 'SWAGGER
' (do arquivo *.yml) seguido de seu bloco 'PROGRESS
' correspondente (do arquivo *.p), nesta sequência.
Para o exemplo prático foi utilizada uma simulação de "Manipulação de Pedidos".
Segue abaixo os blocos de códigos documentados:
INFO
Arquivo *.yml:
Inicialmente é informada a versão do Swagger
, na própria seção 'swagger'. Na seção 'info' estão as informações da descrição (description
), a versão da API (version
) e o título (title
).
Na seção basePath
colocamos o contexto da aplicação.
Na seção tags
se nomeia o serviço (name
), a descrição do serviço (description
) e os documentos externos (externaldocs
), caso existam, com a descrição e o link de acesso (url
).
A tag principal desse bloco é 'program'
e referencia o arquivo *.p que precisar ser documentado, ou seja, no exemplo abaixo o arquivo *.yml validará o arquivo PROGRESS
'pedido.p'.
Bloco de código | ||
---|---|---|
| ||
swagger: "2.0"
info:
description: "Este é um exemplo de aplicação de API no modelo Totvs-rest para um modelo de negocio referente a 'Pedidos'"
version: "1.0.0"
title: "Exemplo API Totvs-REST"
basePath: "/tstUn/v1/"
program: pedido.p
tags:
- name: "servicoConsultaPedido"
description: "Exemplopo de chamada para modelo de negócio 'Pedido'"
externalDocs:
description: "Mais informações em:"
url: "http://tdn.totvs.com"
schemes:
- "http"
paths:
/tstUniApiDatasul:
|
Arquivo *.p:
No bloco de código PROGRESS
abaixo (pedido.p), estão inicialmente as chamadas das includes progress
referente a padronização das ações dos métodos HTTP
. Este trecho não é correspondente ao YAML acima, porém complementa a construção da API TOTVS-REST.
Bloco de código | ||
---|---|---|
| ||
{utp/ut-api.i}
{utp/ut-api-action.i pi-get GET /~* }
{utp/ut-api-action.i pi-send GET /~*/SEND by=email,address=~* }
{utp/ut-api-action.i pi-post POST /~* oi=1}
{utp/ut-api-action.i pi-put PUT /~* }
{utp/ut-api-action.i pi-delete DELETE /~* }
{utp/ut-api-notfound.i}
|
GET
Arquivo *.yml:
A seguir a documentação referente ao método GET para listar os pedidos existentes. A documentação informa que o recurso acessado será "pedido".
Dentro da seção get
estão contidas todas a sub seções que compõem a modelagem do recurso desse método (podem haver mais recursos). Assim sendo, na seção tags
está definido o path do recurso 'pedido' para montagem da URI: .../tst/v1//tstUniApiDatasul/pedido
Ao enviar a requisição pode-se informar, como parâmentros (na sub seção parameters
), filtros do status do pedido dentro da sub seção items
.
O retorno da requisição, sub seção produces
, será um JSON contendo a lista filtrada dos pedidos existentes na base de dados junto com o status (responses
) 200 que informa que a operação foi executada com sucesso.
A validação neste método acontece na declaração da procedure progress, na tag 'procedure
', que neste caso é 'pi-get'.
Bloco de código | ||
---|---|---|
| ||
get:
procedure: pi-get
tags:
- "pedido"
summary: "Busca Dados dos pedidos existentes"
description: "Busca os dados dos pedidos cadastrados na base de dados"
operationId: "getPedido"
produces:
- "application/json"
parameters:
- name: "status"
in: "query"
description: "Valores de status que precisam ser considerados para o filtro dos pedidos. Ex: available, pending e/ou sold"
required: true
type: "array"
items:
type: "string"
enum:
- "available"
- "pending"
default: "available"
collectionFormat: "multi"
responses:
200:
description: "Operação executada com sucesso"
schema:
type: "array"
items:
$ref: "#/definitions/payloadDeRetornoPedido"
|
Arquivo *.p:
No arquivo progress a procedure correspondente apresenta a efetivação da ação com os dados de entrada e retorno da requisição em um objeto JSON.
Bloco de código | ||
---|---|---|
| ||
PROCEDURE pi-get:
DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
ASSIGN jsonOutput = jsonInput.
END.
|
POST
Arquivo *.yml:
A documentação seguinte refere-se ao cadastro de uma nova informação/registro na base e, para isso, utiliza o método POST.
No mesmo recurso "pedido", serão enviados os dados envelopados em um código JSON (sub seção consumes
) e o mesmo será retornado na resposta da requisição (sub seção produces
) como comprovação de que os dados foram gravados.
A validação neste método acontece na declaração da procedure progress, na tag 'procedure
', que neste caso é 'pi-post'.
Bloco de código | ||
---|---|---|
| ||
post:
procedure: pi-post
tags:
- "pedido"
summary: "Cadastro de um novo pedido"
description: "Envia dados de um novo cadastro de pedido para a base de dados utilizando o método POST"
operationId: "addPedido"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Parâmetros necessários enviados no 'payload' para adicionar o novo pedido"
required: true
schema:
$ref: "#/definitions/payloadEnvioPedido"
|
Arquivo *.p:
No arquivo progress a procedure correspondente, assim como no método GET, apresenta a efetivação da ação com os dados de entrada e retorno da requisição em um objeto JSON.
Bloco de código | ||
---|---|---|
| ||
PROCEDURE pi-post:
DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
ASSIGN jsonOutput = jsonInput.
END. |
PUT
Arquivo *.yml:
A próxima documentação apresenta o método PUT, quando há necessidade de alteração e/ou atualização de algum registro existente.
Assim como o método POST, também encapsula os dados em um código JSON para atualizar os dados desejados (sub seção consumes
), porém pode também informar essa atualização como parâmetros na URI.
A validação neste método acontece na declaração da procedure progress, na tag 'procedure
', que neste caso é 'pi-put'.
Bloco de código | ||
---|---|---|
| ||
put:
procedure: pi-put
tags:
- "pedido"
summary: "Atualiza um registro existente de pedido"
description: "Atualiza os dados de um registro de pedido existente na base de dados utilizando o método Put"
operationId: "putPedido"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Parâmetros necessários enviados no 'payload' para atualizar um pedido existente"
required: true
schema:
$ref: "#/definitions/payloadEnvioPedido" |
Arquivo *.p:
No arquivo progress a procedure correspondente, assim como no método GET e POST, apresenta a efetivação da ação com os dados de entrada e retorno da requisição em um objeto JSON (sub seção produces
).
Bloco de código | ||
---|---|---|
| ||
PROCEDURE pi-put:
DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
ASSIGN jsonOutput = jsonInput.
END. |
DELETE
Arquivo *.yml:
A documentação para o método DELETE informa que para executar a exclusão de um registro é preciso passar como parâmetro na URI uma chave na sub seção parameters
.
Como retorno, também apresenta um JSON contendo as informações do registro excluído na sub seção produces
.
A validação neste método acontece na declaração da procedure progress, na tag 'procedure
', que neste caso é 'pi-delete'.
Bloco de código | ||
---|---|---|
| ||
delete:
procedure: pi-delete
tags:
- "pedido"
summary: "Exclui um pedido existente"
description: "Realiza a exlusão de um pedido existente na base de dados utilizando o método PUT"
operationId: "deletePedido"
produces:
- "application/json"
parameters:
- name: "api_key"
in: "header"
required: false
type: "string"
- name: "petId"
in: "path"
description: "Parâmetros necessários enviados no 'payload' para exlcuir um pedido existente"
required: true
type: "integer"
format: "int64" |
Arquivo *.p:
No arquivo progress a procedure correspondente, assim como nos métodos anteriores, apresenta a efetivação da ação com os dados de entrada e retorno da requisição em um objeto JSON.
Bloco de código | ||
---|---|---|
| ||
PROCEDURE pi-delete:
DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
ASSIGN jsonOutput = jsonInput.
END. |
DEFINITIONS
Ainda no arquivo YAML existe a seção definitions
onde é realizada a definição do modelo de dados com os objetos, assim sendo, no exemplo abaixo, foram definidos objetos payload para envio e retorno de pedidos.
Dentro de cada objeto foi estabelecido o tipo (sub seção type
) e as propriedades (sub seção properties
) pertinentes a cada um.
Bloco de código | ||
---|---|---|
| ||
definitions:
payloadEnvioPedido:
type: "object"
required:
- "numeroPedido"
- "codigoCliente"
properties:
id:
type: "integer"
format: "int64"
numeroPedido:
type: "integer"
example: "ped123456879"
format: "int64"
codigoCliente:
type: "string"
description: "cliente1234"
descricaoCliente:
type: "string"
example: "Cliente de Teste"
payloadDeRetornoPedido:
type: "object"
properties:
id:
type: "integer"
format: "int64"
numeroPedido:
type: "integer"
example: "ped123456879"
format: "int64"
statusDoPedido:
type: "string"
description: "Pedido Aprovado"
enum:
- "Aprovado"
- "Reprovado"
|
Aviso | ||
---|---|---|
| ||
Comentários tanto em linha (#) com em bloco (/**/) não serão validados, ou seja, o parser realizará a leitura independente da existência ou não dos comentários. |