API demo para desenvolvimento do exemplo
Neste exemplo, será mostrado o envio de dados no formato JSON para serem consumidos por uma API criada especificamente para este propósito.
...
O arquivo executável será postado abaixo:
View file | ||
---|---|---|
|
Desenvolvendo o Script
O Script foi feito para ser utilizado em qualquer evento, de qualquer tabela, com o VsScripter, podendo ser executado ali mesmo diretamente do editor de scripts para efeitos didáticos.
Abaixo, segue o código a ser copiado/digitado no editor VsScripter:
Code Block | ||
---|---|---|
| ||
uses // units necessárias para o projeto. Todas são de inclusão manual uVsHttpRequest, uLkJson, Classes; const // constantes necessárias para o Login que baixará o token de autenticação |
...
User |
...
= 'admin'; Password = 'admin'; |
...
var |
...
|
...
|
...
|
...
// |
...
variáveis |
...
globais |
...
necessárias para |
...
efetivar os "requests http", de armazenamento // do token, de criação de um objeto JSON e do armazenamento do resultado (Response) // sequencialmente http : TVsHttp; cUrl : String; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
token |
...
: |
...
String; |
...
|
...
|
...
|
...
jsonO |
...
: TlkJSONobject; resultado: THttpResponse; dados: TStringList; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
// criando uma função para tratar |
...
os |
...
erros mais comuns nos "requests http" function RetornaErro(erro: Integer):String; begin |
...
case erro of 400: Result := IntToStr(erro)+' - |
...
Requisição |
...
ruim: |
...
A |
...
requisição |
...
não |
...
pôde |
...
ser '+ ' |
...
interpretada |
...
pelo |
...
servidor |
...
em razão de erros de formato/sintaxe.'; 401: Result := IntToStr(erro)+' - Não autorizado:'#13#13'A requisição requer '+ |
...
|
...
|
...
|
...
|
...
|
...
|
...
' |
...
autenticação por parte do cliente e |
...
as |
...
informações |
...
de '+ 'autenticação não foram localizadas ou não são |
...
válidas. |
...
' |
...
; |
...
|
...
|
...
|
...
|
...
|
...
|
...
403: Result := IntToStr(erro)+' - Indica que o servidor entendeu o pedido, '+ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
'mas se recusa a autorizá-lo. Esse status é semelhante ao 401, '+ |
...
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
'mas |
...
neste |
...
caso, |
...
a re-autenticação não fará diferença.'; 404: Result := IntToStr(erro)+' - A página não foi encontrada ou não existe '+ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
'mais. '#13#13'Entre as |
...
principais |
...
causas |
...
para aparecer o '+ ' |
...
problema |
...
estão: |
...
páginas |
...
removidas |
...
do |
...
site, |
...
modificação na '+ ' |
...
URL |
...
sem |
...
um |
...
redirecionamento e erros de digitação no navegador.'; 405: Result := IntToStr(erro)+' - |
...
Método |
...
não permitido:'#13#13'O método HTTP '+ ' |
...
utilizado |
...
não |
...
é |
...
permitido |
...
para |
...
o |
...
recurso |
...
identificado |
...
na URL.'; 422: Result |
...
:= IntToStr(erro)+' - Entidade não processável:'#13#13'O servidor '+ 'reconhece que as informações estão na sintaxe correta, mas ' |
...
+ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
'seu conteúdo |
...
está |
...
semanticamente incorreto.'; 500: Result := IntToStr(erro)+' - Indica problemas com a estrutura do site '+ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
'que o |
...
usuário |
...
deseja |
...
acessar, |
...
então |
...
não |
...
se |
...
trata |
...
de |
...
um |
...
bug '+ 'com o computador ou navegador, nem mesmo com a Internet do '+ 'usuário.'; 11001: Result := IntToStr(erro)+'Sem conexão com a Internet' else // caso o número do erro não esteja listado acima, será mostrado seu número |
...
// sem a |
...
devida descrição. |
...
|
...
|
...
Result |
...
:= |
...
'Erro retornado: '+IntToStr(erro); end; end; // Procedure para buscar o token de autenticação necessário para consumo da API Procedure PegaToken; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
begin // |
...
cria |
...
um |
...
objeto |
...
chamado |
...
http, do tipo TVsHttp, responsável pelos "requests" // http da API consumida http := TVsHttp.Create; try // |
...
informa ao |
...
método |
...
"POST" |
...
da |
...
requisição |
...
http |
...
que |
...
o |
...
conteúdo |
...
enviado |
...
é |
...
do // |
...
tipo |
...
JSON |
...
|
...
|
...
|
...
http.ContentType := 'application/json'; // |
...
URL |
...
da |
...
API |
...
a |
...
ser |
...
consumida |
...
|
...
|
...
|
...
|
...
cUrl |
...
:= 'http://127.0.0.1:2001/tms/auth/LoginService/Login'; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
// |
...
envio |
...
da |
...
requisição |
...
http, |
...
por meio do método |
...
"POST", para solicitar o // novo token de autenticação. As API's possuem tempos de validade do token // diferenciados. Cada provedor de serviços web saberá dizer de quanto em // quanto tempo o token deve ser renovado. Neste exemplo, ele sempre será // renovado |
...
no momento de sua execução, por meio desta "Procedure". // resultado é um objeto do tipo THttpResponse, que receberá toda a resposta // oriunda da requisição enviada por meio |
...
do |
...
objeto |
...
http. |
...
|
...
|
...
|
...
|
...
// |
...
cUrl |
...
é |
...
a |
...
URL |
...
da |
...
API |
...
definida |
...
acima. User e |
...
Password |
...
são |
...
os |
...
parâmetros // |
...
necessários |
...
ao Login dessa "Procedure" na API para baixar o token. |
...
|
...
|
...
|
...
|
...
resultado |
...
:= http.Post(cUrl, Format('{"User":"%s","Password":"%s"}', |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
[User, Password])); // verificando se o resultado recebido é um erro ou se deu certo o envio dos // dados por meio da propriedade |
...
resultado.StatusCode. Se o valor de StatusCode |
...
// for igual ou maior que 400, indica que houve um erro e ele será tratado pela // |
...
função RetornaErro. // |
...
caso |
...
o valor de StatusCode seja 200, isso indica que houve sucesso na requi- // sição http e o resultado será transformado em um objeto JSON para, aí, ser // atribuído a variável token. if resultado.StatusCode >= 400 then ShowMessage('Pega token: '+RetornaErro(resultado.StatusCode)) else if resultado.Statuscode = 200 then begin jsonO := TlkJSON.ParseText(resultado.Response) as TlkJSONObject; token := jsonO.Field['value'].value; end; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
finally |
...
|
...
|
...
|
...
|
...
// finaliza os dois objetos para liberar |
...
memória. |
...
|
...
http.Free; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
jsonO.Free; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
end; |
...
end; // criando a função EnviaDados Function EnviaDados(cDados: TStringList; geraToken: Boolean):THttpResponse; var // |
...
declarando |
...
o objeto |
...
obj para preparação do |
...
cabeçalho |
...
http |
...
|
...
|
...
obj: TCustomHeader; begin |
...
try |
...
|
...
|
...
|
...
// se foi passado |
...
true |
...
para o parâmetro geraToken, será gerado um novo token if geraToken then |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
PegaToken; // |
...
cria |
...
parâmetro |
...
do |
...
Head |
...
http |
...
chamado |
...
Authorization |
...
e |
...
envia |
...
o |
...
token |
...
para // |
...
autenticação |
...
para |
...
consumo |
...
da |
...
API |
...
|
...
|
...
|
...
|
...
|
...
|
...
obj := TCustomHeader.Create('Authorization', 'Bearer ' + token); |
...
|
...
|
...
|
...
|
...
// |
...
cria |
...
um objeto chamado http, do tipo TVsHttp, responsável pelos |
...
"requests" |
...
// http da API consumida http := TVsHttp.Create; // informa ao método "POST" da requisição http que o conteúdo |
...
enviado |
...
é do |
...
...
// |
...
tipo |
...
JSON |
...
|
...
|
...
|
...
|
...
|
...
http.ContentType := |
...
'application/json'; // adiciona autenticação criada no objeto obj ao cabeçalho customizado no // objeto http |
...
|
...
|
...
http.CustomHeaders. |
...
Add(obj); // URL da API a ser |
...
consumida |
...
|
...
|
...
|
...
cUrl := 'http://127.0.0.1:2001/tms/xdata/apiservice/enviarpedido'; // Result retorna o resultado vindo da API consumida. Se os dados foram // recebidos e processados, ou se houve erro e qual é o erro. Result := http.Post(cUrl, cDados.Text); finally |
...
// destrói |
...
o objeto http |
...
http.free; end; end; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
// execução do Script begin |
...
|
...
|
...
|
...
// |
...
cria |
...
objeto |
...
dados |
...
do |
...
tipo |
...
TStringList, |
...
que |
...
receberá |
...
os |
...
dados |
...
a |
...
serem |
...
en- // |
...
viados para a API, como "Body" da |
...
requisição |
...
http. |
...
|
...
|
...
|
...
|
...
dados |
...
:= TStringList.Create(); |
...
// |
...
início do ciclo de vida do script try // adiciona |
...
dados a TStringList dados, que serão enviados à função EnviaDados dados.Add('{'); dados.Add('"PedidoId":1,'); dados.Add('"ClienteID":"000456",'); dados.Add('"ClienteNome":"000456",'); dados.Add('"ProdutoID":"164756392300",'); dados.Add('"ProdutoQTD":100,'); dados.Add('"ProdutoValorUnt":12.5'); dados.Add('}'); // |
...
recebe o |
...
resultado |
...
vindo |
...
função |
...
EnviaDados, |
...
por |
...
meio |
...
de |
...
'http |
...
response' |
...
|
...
resultado |
...
:= EnviaDados(dados, true); // |
...
verificando |
...
se o |
...
resultado recebido |
...
é |
...
um |
...
erro |
...
ou |
...
se |
...
deu |
...
certo o envio dos // |
...
dados |
...
por |
...
meio da propriedade resultado.StatusCode. Se o valor de StatusCode |
...
|
...
// for igual ou maior que 400, indica que houve um erro e ele será tratado pela |
...
// |
...
função |
...
RetornaErro. |
...
...
|
...
|
...
|
...
// caso o valor de StatusCode seja 200, isso indica que houve sucesso na requi- // sição http e o resultado retornado |
...
será mostrato por meio do ShowMessage // |
...
que é exatamente o retorno da API que está programada para retornar o |
...
// |
...
mesmo |
...
JSON enviado. if resultado.StatusCode >= 400 then ShowMessage('Envio de dados: ' + RetornaErro(resultado.StatusCode)) else if resultado.Statuscode = 200 then ShowMessage('HTTP 200 OK'#13#13+ 'Esses foram os dados enviados:'#13#13 +resultado.Response); finally // destrói a TStringList dados para liberar memória. dados.free; end; end; |