Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.
Informações
titleÍndice

Índice
maxLevel1
exclude.*.[IMPORTANTE!]//[Ou seja,]

Introdução


O desenvolvimento de APIs permite a exposição e o consumo de dados com o objetivo da integração (front-end, portais, customizações, etc) ao back-end do produto Datasul, de maneira segura e padronizada.

A estrutura de integração de APIs Datasul suporta o envio de requisições no estilo de arquitetura REST com o desenvolvimento da regra de negócio em Progress. 


Abaixo o fluxo das requisições via HTTP (DATASUL-REST) e formato de execução via Progress:



Esta funcionalidade está disponível para utilização conforme apresentado no quadro abaixo:

Informações
titleMatriz de Evolução


draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamereleases
simpleViewerfalse
width
diagramWidth926
revision4


Contextos


Expandir
titleClick para visualizar o conteúdo

Existem 2 contextos definidos que se aplicam tanto para a Antiga arquitetura (Jboss) quanto para a Nova arquitetura (Tomcat, Wildfly).

Estes contextos tem o objetivo de definir o acesso das requisições, ou seja, se são contextos de acessos internos (via menu) pelo contexto DTS/DATASUL-REST ou acessos externos (via APPs por exemplo) pelo contexto /API.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNamecontextos
simpleViewerfalse
width
diagramWidth935
revision2


Card documentos
InformacaoO contexto /api foi criado com autenticação via "Basic Authentication", para atender o guia de API TOTVS, sendo possível conexão com qualquer API que anteriormente era "dts/datasul-rest/resources/prg".
TituloIMPORTANTE!

Card documentos
InformacaoPara a Antiga Arquitetura, que utiliza o servidor de aplicação JBOSS, o contexto /api implementa o tipo de autenticação BASIC AUTHENTICATION, assim como para a Nova Arquitetura.
TituloOu seja,




Formato URL


Expandir
titleClique para visualizar o conteúdo

O Guia de Implementação de API TOTVS define que o formato das URIs dos endpoints devem conter o nome do produto, o módulo, a versão da API e o recurso alvo da
funcionalidade em questão.

Modelo de acesso aos Contextos:

/prg

Informações
iconfalse

Tomando como exemplo o endpoint de integração do recurso de "Usuários" do módulo de "Foundation" do produto "Datasul", a URI básica deste serviço deve ser: /prg/fnd/v1/users

Para o produto Datasul, o serviço responsável é implementado no contexto /dts/datasul-rest/

Desta forma, a URL final do serviço exemplo acima seria composta da seguinte maneira: 



Aviso

A URL definida pelo Padrão de API TOTVS segue o seguinte formato:

/dts/datasul-rest/resouces/prg/<módulo>/<versão API>/<recurso>/

Informações que forem passadas após o recurso, serão tratadas como parâmetros PATH.



/api

Informações
iconfalse

Para exemplo do funcionamento /api vamos utilizar o mesmo recurso de integração de usuário exemplificado anteriormente.

URI deste serviço deve ser: /api/fnd/v1/users

No geral o funcionamento do /api é igual ao /prg, com a ressalva de que o endpoint /api não esta dentro do contexto /dts/datasul-rest/



Aviso

A URL definida pelo Padrão de API TOTVS segue o seguinte formato:

/api/<módulo>/<versão API>/<recurso>/

Informações que forem passadas após o recurso, serão tratadas como parâmetros PATH.




Serviço Progress


Expandir
titleClique para visualizar o conteúdo

Para "publicar" a funcionalidade Progress ABL basta criar o programa (.p) com o seguinte caminho: fnd/api/v1/users.p (<módulo>/api/<versão API>/<recurso>.p). 

A sub-pasta "api" passa então a concentrar todas as funcionalidades de integração do módulo em questão:

Aviso

Os programas Progress disponibilizados, deverão seguir o padrão de localização abaixo e devem estar compilados, ou seja, é necessário o *.r:

<módulo>/api/<versão API>/<recurso>.r


OBS: Outros caminhos e parâmetros podem ser adicionados a URL, mas sempre de acordo com o Guia de Implementação de APIs.


     O Guia de Implementação de API TOTVS define também que a troca de mensagens é feita (impreterivelmente) no formato JSON, e por conta disso, a troca de mensagens com as funcionalidades Progress também devem ser feitas nesse formato, mais especificamente por meio de um parâmetro de entrada e outro de saída do tipo LONGCHAR que devem ser devidamente tratados (parseados e formatados) pela funcionalidade utilizando as includes utilitárias disponibilizadas:

  • utp/ut-api.i: Faz o parser do parâmetro LONGCHAR de entrada e cria um objeto JsonObject chamado jsonInput.
  • utp/ut-api-action.i: Faz o roteamento do objecto jsonInput para uma procedure interna especificada pelo desenvolvedor.
  • utp/ut-api-notfound.i: Caso nenhuma procedure interna tenha sido encontrada, retorna uma mensagem "Method not found" com HTTP Status 400.

>>>>>Abaixo um exemplo de recurso desenvolvido em Progress ABL para ser utilizado junto ao serviço de API<<<<<<

Expandir
titleClique para visualizar o exemplo ...

No início do código estão todas as includes necessárias. O que vale ressaltar neste trecho é referente a include ut-api-action:

  • Nesta include são declaradas as procedures utilizadas na API, por exemplo: pi-send, pi-update.
  • Na mesma declaração é definido qual o método http aplicado, por exemplo: GET, POST, entre outros.
  • Em seguida é definido como o recurso será acessado pela URI, por exemplo: /~*/SEND
  • Isso significa que ao acessar a URI teremos algo como: http://host:port/dts/datasul-rest/resources/prg/fnd/v1/users/send onde:


 

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramDisplayName
lboxtrue
revision2
diagramNameestrutura
simpleViewerfalse
width600
linksauto
tbstyletop
diagramWidth785


Bloco de código
languageruby
themeEclipse
{utp/ut-api.i}
{utp/ut-api-action.i pi-send    GET /~*/SEND by=email,address=~* }
{utp/ut-api-action.i pi-update  POST /~* }
{utp/ut-api-action.i pi-find    GET /~* }
{utp/ut-api-action.i pi-default GET }
{utp/ut-api-notfound.i}
  
PROCEDURE pi-send:
    DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
    DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
     
    DEFINE VARIABLE aJsonArray  AS JsonArray  NO-UNDO.
    DEFINE VARIABLE oJsonObject AS JsonObject NO-UNDO.
 
    aJsonArray = NEW JSONArray().
 
    oJsonObject = NEW JSONObject().
    oJsonObject:ADD("teste", "teste").
    oJsonObject:ADD("teste1", "teste1").
    oJsonObject:ADD("teste2", "teste2").
    aJsonArray:ADD(oJsonObject).
 
    oJsonObject = NEW JSONObject().
    oJsonObject:ADD("teste", "teste").
    oJsonObject:ADD("teste1", "teste1").
    oJsonObject:ADD("teste2", "teste2").
    aJsonArray:ADD(oJsonObject).
 
    jsonOutput = JsonAPIResponseBuilder:ok(aJsonArray, false).
END.
  
PROCEDURE pi-update:
    DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
    DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.

    jsonOutput = NEW JSONObject().
    jsonOutput = jsonInput.
END.
 
PROCEDURE pi-find:
    DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
    DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
    
    jsonOutput = NEW JSONObject().
    jsonOutput:ADD("method", "GET").
    jsonOutput:ADD("procedure", "pi-find").
    jsonOutput:ADD("description", "Test").
END.

PROCEDURE pi-default:
    DEF INPUT PARAM jsonInput AS JsonObject NO-UNDO.
    DEF OUTPUT PARAM jsonOutput AS JsonObject NO-UNDO.
    
    jsonOutput = NEW JSONObject().
    jsonOutput:ADD("method", "GET").
    jsonOutput:ADD("procedure", "pi-default").
    jsonOutput:ADD("description", "Test").
END.


     No exemplo acima, temos as seguintes includes utilitárias:

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameutilitarios
simpleViewerfalse
width
diagramWidth1079
revision5



Informações

Algumas considerações sobre o uso da include de roteamento (ut-api-action):

  • Os roteamentos devem ser definidos do mais específico (detalhado) para o mais genérico (simples);
  • O utilitário faz uso da função MATCHES do Progress, que basicamente permite o uso do ponto "." (ponto) como coringa de uma determinada posição (1 caractere apenas) e o "*" (asterisco) para um conjunto de caracteres variáveis;
  • O caracter de escape "~" deve ser utilizado sempre que necessário, antecedendo caracteres especiais que comprometam a compilação do código progress;
  • Para definir mais de um parâmetro de pesquisa, utilize "," (vírgula) como separador. O processamento de mais de um parâmetro de pesquisa será sempre traduzido para usar o operador AND.
  • Permite o uso de todos métodos HTTP suportados pelo API Manager (GET, POST, PUT, DELETE, PATCH, ...)
Informações

A include ut-api.i precisa ser adicionada obrigatoriamente no início do programa Progress, visto que esta include faz uso da instrução USING para importação de classes. Portanto, devido a esta caraterística do Progress ABL, somente será possível adicionar outras includes depois da adição da ut-api.i e ut-api-notfound.i, respectivamente.



Classes utilitárias


Expandir
titleClique para visualizar o conteúdo

Com o objetivo de facilitar a manipulação dos objetos JsonObject recebidos e enviados pela API Progress foram desenvolvidas algumas classes de utilitários:

  • JsonAPIRequestParser - Extrai informações do objeto JSON recebido como parâmetro da requisição.
  • JsonAPIResponse - Trata a criação do objeto JSON de response da requisição.
  • JsonAPIResponseBuilder - Trata a criação do objeto JSON de response da requisição através de um builder.
  • JsonAPIUtils - Utilitário com métodos que facilitam a manipulação de informações relacionados a API



Formato Mensagem JSON


Expandir
titleClique para visualizar o conteúdo

O objeto JsonObject, recebido pela requisição no programa Progress conterá informações completas da requisição, desde informações do:

  • HEADER;
  • QUERY PARAMs;
  • PATH PARAMs;
  • o próprio PAYLOAD e;
  • arquivos MULTIPART.

Com esta mensagem, o desenvolvedor poderá efetuar os devidos filtros e classes utilitárias necessárias. 

Exemplo de mensagem:

Bloco de código
languageyml
themeEclipse
linenumberstrue
{ 
    uri: valor,
	method: GET,
    headers: {},
	pathParams: [ "param1", "param2" ],
	queryParams: { query1: [valor1, valor2], query2: [valor1]},
	payload: { },
	multyPartFile: [ {file: ...}, {file: ...}]
}



Login


Expandir
titleClique para visualizar o conteúdo

Na Antiga Arquitetura (Jboss) para realizar o login no DATASUL-REST, apesar de existir BASIC AUTHENTICATION com o contexto /api, ainda é possível passar como parâmetro usuário e senha na seguinte URL.

Dica
titleURL para Login

http://localhost:8180/dts/datasul-rest/resources/login?username=<USER>&password=<PASSWORD>

Para passagem da senha é necessário converte-la para SHA1, com este resultado realizar a conversão para BASE64. Tendo em vista que a conversão para BASE64 irá trazer caracteres incoerentes para passagem da URL, será necessário fazer a conversão para URL-ENCODE.

  • Senha: testPassword
  • BASE64(SHA1): i7YRj4/Wk1rQh2o740pxfTJwj/0=
  • URL-ENCODE: i7YRj4%2FWk1rQh2o740pxfTJwj%2F0%3D

Observe que por trazer os caracteres " / e = " na conversão de SHA1 e BASE64, é necessário o URL-ENCODE.

Bloco de código
languageruby
themeEclipse
titleExemplo de Conversão
linenumberstrue
DEFINE VARIABLE testPass AS CHARACTER NO-UNDO.
testPass = BASE64-ENCODE(SHA1-DIGEST(LC("testPassword"))).                 
// Utilize uma lógica de conversão URL-ENCODE para variavel testPass
Aviso
titleAviso importante!

Para realizar esse encode não se pode utilizar codificação em HEXADECIMAL!

Dica
titleExemplo de URL final

http://localhost:8180/dts/datasul-rest/resources/login?username=teste&password=i7YRj4%2FWk1rQh2o740pxfTJwj%2F0%3D