Mudanças entre as edições de "PHSYS API"
| Linha 1: | Linha 1: | ||
| − | ===''' | + | ==='''Introducao'''=== |
| − | |||
| − | + | Este exemplo mostra como configurar um unico endpoint de API para executar varios procedimentos internos, usando o campo MetodoScript no body da requisicao. | |
| − | + | A proposta e ter um endpoint unico, por exemplo: | |
| − | + | <code>http://localhost:211/api/solicitacoes</code> | |
| − | + | e dentro do script, direcionar a execucao para: | |
| − | |||
| − | + | * Cadastrar | |
| − | + | * Consultar | |
| + | * Cancelar | ||
| − | + | Esse modelo e util quando os procedimentos pertencem ao mesmo contexto funcional e compartilham a mesma autenticacao e URL de integracao. | |
| − | + | ==='''Modelo de Integracao Personalizado'''=== | |
| − | |||
| − | |||
| − | |||
| − | + | No cadastro do endpoint no PHServerConf: | |
| − | + | * Modelo de integracao: Personalizado | |
| + | * Classe: script especifico | ||
| + | * Procedimento: GetMetodo | ||
| + | * Exige token: Sim (opcional, recomendado) | ||
| − | + | Com isso, toda requisicao ao endpoint passa pelo procedimento GetMetodo, que decide qual acao executar com base no body. | |
| − | + | ==='''Cabecalhos Necessarios'''=== | |
| − | + | * Content-Type: application/json | |
| − | + | * Authorization: Bearer <access_token> (quando OAuth2 estiver habilitado) | |
| − | + | ==='''Estrutura da Requisicao'''=== | |
| − | + | URL: | |
| − | |||
| − | : | + | <code>http://<servidor>:<porta>/api/solicitacoes</code> |
| − | |||
| − | |||
| − | : | + | Metodo HTTP: |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | <code>POST</code> | |
| − | + | Body base: | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | <pre> | |
| − | + | { | |
| − | : | + | "MetodoScript": "Cadastrar | Consultar | Cancelar", |
| − | + | "...": "demais campos conforme cada metodo" | |
| − | + | } | |
| − | + | </pre> | |
| − | |||
| − | |||
| − | |||
| − | + | ==='''Exemplo de Bodies'''=== | |
| − | |||
| − | + | ==='''1) Cadastrar'''=== | |
| − | |||
| − | + | <pre> | |
| + | { | ||
| + | "MetodoScript": "Cadastrar", | ||
| + | "Cliente": "2", | ||
| + | "Solicitante": "2", | ||
| + | "TiposSolicitacao": "3", | ||
| + | "Requisito": "2", | ||
| + | "Prioridade": "2", | ||
| + | "DescricaoResumida": "Solicitacao de exemplo", | ||
| + | "Descricao": "Descricao detalhada da solicitacao" | ||
| + | } | ||
| + | </pre> | ||
| − | + | ==='''2) Consultar'''=== | |
| − | + | <pre> | |
| − | + | { | |
| − | + | "MetodoScript": "Consultar", | |
| − | + | "SolicitacaoID": "150" | |
| − | + | } | |
| − | + | </pre> | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | ==='''3) Cancelar'''=== | |
| − | + | <pre> | |
| − | + | { | |
| + | "MetodoScript": "Cancelar", | ||
| + | "SolicitacaoID": "150", | ||
| + | "Motivo": "Solicitacao aberta em duplicidade" | ||
| + | } | ||
| + | </pre> | ||
| − | + | ==='''Exemplo de Script'''=== | |
| − | + | <pre> | |
| + | procedure GetMetodo; | ||
| + | var | ||
| + | Metodo: String; | ||
| + | begin | ||
| + | Metodo := UpperCase(ObterMetodoFromBody); | ||
| − | ''' | + | if (Metodo = 'CADASTRAR') then |
| + | Cadastrar | ||
| + | else if (Metodo = 'CONSULTAR') then | ||
| + | Consultar | ||
| + | else if (Metodo = 'CANCELAR') then | ||
| + | Cancelar | ||
| + | else | ||
| + | ErroValidacao('Processo invalido. Metodo informado: ' + Metodo); | ||
| + | end; | ||
| − | + | function ObterMetodoFromBody: String; | |
| + | var | ||
| + | Body: String; | ||
| + | JsonObj: TPHJson; | ||
| + | begin | ||
| + | Body := Trim(GetBody); | ||
| − | + | if (Body = '') then | |
| − | + | ErroValidacao('Faltou informar o body da requisicao.'); | |
| − | + | JsonObj := TPHJson.Create; | |
| + | try | ||
| + | JsonObj.LerJson(Body); | ||
| + | Result := Trim(JsonObj.ElementoDoNome('MetodoScript').Texto); | ||
| + | finally | ||
| + | JsonObj.Free; | ||
| + | end; | ||
| + | end; | ||
| − | + | function MontarRetornoSucesso(const Detalhes: String): String; | |
| + | begin | ||
| + | Result := | ||
| + | '{' + | ||
| + | '"status":"sucesso",' + | ||
| + | '"detalhes":"' + Detalhes + '"' + | ||
| + | '}'; | ||
| + | end; | ||
| − | = | + | function MontarRetornoErro(const Detalhes: String): String; |
| − | + | begin | |
| + | Result := | ||
| + | '{' + | ||
| + | '"status":"erro",' + | ||
| + | '"detalhes":"' + Detalhes + '"' + | ||
| + | '}'; | ||
| + | end; | ||
| − | = | + | procedure Cadastrar; |
| + | var | ||
| + | Body: String; | ||
| + | JsonObj: TPHJson; | ||
| + | SolicitacaoObj: TPHServerClass; | ||
| + | Msg: String; | ||
| + | begin | ||
| + | Body := Trim(GetBody); | ||
| − | = | + | JsonObj := TPHJson.Create; |
| − | + | try | |
| − | + | JsonObj.LerJson(Body); | |
| − | |||
| − | |||
| − | |||
| − | ==== | + | SolicitacaoObj := NewPHServerClass('SOLICITACOES'); |
| − | : | + | try |
| − | : | + | IniciarTransacao; |
| − | : | + | try |
| + | SolicitacaoObj.NovoRegistro; | ||
| + | SolicitacaoObj.CampoDoNome('PESSOA').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Cliente').Texto); | ||
| + | SolicitacaoObj.CampoDoNome('SOLICITANTE').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Solicitante').Texto); | ||
| + | SolicitacaoObj.CampoDoNome('TIPOSOLICITACAO').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('TiposSolicitacao').Texto); | ||
| + | SolicitacaoObj.CampoDoNome('REQUISITO').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Requisito').Texto); | ||
| + | SolicitacaoObj.CampoDoNome('NIVELPRIORIDADE').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Prioridade').Texto); | ||
| + | SolicitacaoObj.CampoDoNome('NOME').AsString := JsonObj.ElementoDoNome('DescricaoResumida').Texto; | ||
| + | SolicitacaoObj.CampoDoNome('DESCRICAOPROBLEMA').AsString := JsonObj.ElementoDoNome('Descricao').Texto; | ||
| + | SolicitacaoObj.Salvar; | ||
| − | + | ConfirmarTransacao; | |
| + | Msg := | ||
| + | '{' + | ||
| + | '"status":"sucesso",' + | ||
| + | '"detalhes":"Solicitacao cadastrada.",' + | ||
| + | '"SolicitacaoID":"' + IntToStr(SolicitacaoObj.CampoDoNome('ID').AsLargeInt) + '"' + | ||
| + | '}'; | ||
| + | except | ||
| + | CancelarTransacao; | ||
| + | Msg := MontarRetornoErro('Erro ao cadastrar solicitacao: ' + ExceptionMessage); | ||
| + | end; | ||
| + | finally | ||
| + | SolicitacaoObj.Free; | ||
| + | end; | ||
| + | finally | ||
| + | JsonObj.Free; | ||
| + | end; | ||
| + | ParamByName('Result').AsString := Msg; | ||
| + | end; | ||
| − | + | procedure Consultar; | |
| + | var | ||
| + | Body: String; | ||
| + | JsonObj: TPHJson; | ||
| + | Q: TPHQuery; | ||
| + | SolicitacaoID: String; | ||
| + | Msg: String; | ||
| + | begin | ||
| + | Body := Trim(GetBody); | ||
| − | + | JsonObj := TPHJson.Create; | |
| + | try | ||
| + | JsonObj.LerJson(Body); | ||
| + | SolicitacaoID := JsonObj.ElementoDoNome('SolicitacaoID').Texto; | ||
| + | |||
| + | Q := NewPHQuery; | ||
| + | try | ||
| + | Q.Add('SELECT ID, NOME, DESCRICAOPROBLEMA, SITUACAO ' + | ||
| + | 'FROM SOLICITACOES ' + | ||
| + | 'WHERE ID = :ID'); | ||
| + | Q.ParamByName('ID').AsLargeInt := StrToInt(SolicitacaoID); | ||
| + | Q.Open; | ||
| + | |||
| + | if Q.Vazia then | ||
| + | Msg := MontarRetornoErro('Solicitacao nao encontrada.') | ||
| + | else | ||
| + | Msg := | ||
| + | '{' + | ||
| + | '"status":"sucesso",' + | ||
| + | '"Solicitacao":{' + | ||
| + | '"ID":"' + Q.FieldByName('ID').AsString + '",' + | ||
| + | '"NOME":"' + Q.FieldByName('NOME').AsString + '",' + | ||
| + | '"DESCRICAO":"' + Q.FieldByName('DESCRICAOPROBLEMA').AsString + '",' + | ||
| + | '"SITUACAO":"' + Q.FieldByName('SITUACAO').AsString + '"' + | ||
| + | '}' + | ||
| + | '}'; | ||
| + | finally | ||
| + | Q.Free; | ||
| + | end; | ||
| + | finally | ||
| + | JsonObj.Free; | ||
| + | end; | ||
| + | |||
| + | ParamByName('Result').AsString := Msg; | ||
| + | end; | ||
| + | |||
| + | procedure Cancelar; | ||
| + | var | ||
| + | Body: String; | ||
| + | JsonObj: TPHJson; | ||
| + | SolicitacaoObj: TPHServerClass; | ||
| + | Msg: String; | ||
| + | SolicitacaoID: Int64; | ||
| + | begin | ||
| + | Body := Trim(GetBody); | ||
| + | |||
| + | JsonObj := TPHJson.Create; | ||
| + | try | ||
| + | JsonObj.LerJson(Body); | ||
| + | SolicitacaoID := StrToInt(JsonObj.ElementoDoNome('SolicitacaoID').Texto); | ||
| + | |||
| + | SolicitacaoObj := NewPHServerClass('SOLICITACOES'); | ||
| + | try | ||
| + | IniciarTransacao; | ||
| + | try | ||
| + | SolicitacaoObj.CampoDoNome('ID').AsLargeInt := SolicitacaoID; | ||
| + | SolicitacaoObj.LerRegistro; | ||
| + | |||
| + | if (SolicitacaoObj.CampoDoNome('ID').AsLargeInt = 0) then | ||
| + | ErroValidacao('Solicitacao nao encontrada para cancelamento.'); | ||
| + | |||
| + | SolicitacaoObj.CampoDoNome('SITUACAO').AsString := 'C'; | ||
| + | SolicitacaoObj.CampoDoNome('OBS').AsString := JsonObj.ElementoDoNome('Motivo').Texto; | ||
| + | SolicitacaoObj.Salvar; | ||
| + | |||
| + | ConfirmarTransacao; | ||
| + | Msg := MontarRetornoSucesso('Solicitacao cancelada com sucesso.'); | ||
| + | except | ||
| + | CancelarTransacao; | ||
| + | Msg := MontarRetornoErro('Erro ao cancelar solicitacao: ' + ExceptionMessage); | ||
| + | end; | ||
| + | finally | ||
| + | SolicitacaoObj.Free; | ||
| + | end; | ||
| + | finally | ||
| + | JsonObj.Free; | ||
| + | end; | ||
| + | |||
| + | ParamByName('Result').AsString := Msg; | ||
| + | end; | ||
| + | |||
| + | begin | ||
| + | end. | ||
| + | </pre> | ||
| + | |||
| + | ==='''Exemplo de Envio (cURL)'''=== | ||
| + | |||
| + | ==='''Cadastrar'''=== | ||
| + | |||
| + | <pre> | ||
| + | curl -X POST "http://localhost:211/api/solicitacoes" ^ | ||
| + | -H "Content-Type: application/json" ^ | ||
| + | -H "Authorization: Bearer <access_token>" ^ | ||
| + | -d "{\"MetodoScript\":\"Cadastrar\",\"Cliente\":\"2\",\"Solicitante\":\"2\",\"TiposSolicitacao\":\"3\",\"Requisito\":\"2\",\"Prioridade\":\"2\",\"DescricaoResumida\":\"Solicitacao de exemplo\",\"Descricao\":\"Descricao detalhada\"}" | ||
| + | </pre> | ||
| + | |||
| + | ==='''Consultar'''=== | ||
| + | |||
| + | <pre> | ||
| + | curl -X POST "http://localhost:211/api/solicitacoes" ^ | ||
| + | -H "Content-Type: application/json" ^ | ||
| + | -H "Authorization: Bearer <access_token>" ^ | ||
| + | -d "{\"MetodoScript\":\"Consultar\",\"SolicitacaoID\":\"150\"}" | ||
| + | </pre> | ||
| + | |||
| + | ==='''Cancelar'''=== | ||
| + | |||
| + | <pre> | ||
| + | curl -X POST "http://localhost:211/api/solicitacoes" ^ | ||
| + | -H "Content-Type: application/json" ^ | ||
| + | -H "Authorization: Bearer <access_token>" ^ | ||
| + | -d "{\"MetodoScript\":\"Cancelar\",\"SolicitacaoID\":\"150\",\"Motivo\":\"Duplicidade\"}" | ||
| + | </pre> | ||
| + | |||
| + | ==='''Resumo'''=== | ||
| + | |||
| + | Com esse padrao, um unico endpoint consegue atender varias operacoes de um mesmo dominio, mantendo: | ||
| + | |||
| + | * Uma URL unica para integracao | ||
| + | * Controle centralizado de autenticacao | ||
| + | * Flexibilidade para evoluir os procedimentos no script | ||
| + | |||
| + | Para respostas personalizadas, utilize sempre: | ||
| + | |||
| + | <code>ParamByName('Result').AsString := <texto ou JSON>;</code> | ||
Edição das 15h59min de 23 de julho de 2026
Índice
Introducao
Este exemplo mostra como configurar um unico endpoint de API para executar varios procedimentos internos, usando o campo MetodoScript no body da requisicao.
A proposta e ter um endpoint unico, por exemplo:
http://localhost:211/api/solicitacoes
e dentro do script, direcionar a execucao para:
- Cadastrar
- Consultar
- Cancelar
Esse modelo e util quando os procedimentos pertencem ao mesmo contexto funcional e compartilham a mesma autenticacao e URL de integracao.
Modelo de Integracao Personalizado
No cadastro do endpoint no PHServerConf:
- Modelo de integracao: Personalizado
- Classe: script especifico
- Procedimento: GetMetodo
- Exige token: Sim (opcional, recomendado)
Com isso, toda requisicao ao endpoint passa pelo procedimento GetMetodo, que decide qual acao executar com base no body.
Cabecalhos Necessarios
- Content-Type: application/json
- Authorization: Bearer <access_token> (quando OAuth2 estiver habilitado)
Estrutura da Requisicao
URL:
http://<servidor>:<porta>/api/solicitacoes
Metodo HTTP:
POST
Body base:
{
"MetodoScript": "Cadastrar | Consultar | Cancelar",
"...": "demais campos conforme cada metodo"
}
Exemplo de Bodies
1) Cadastrar
{
"MetodoScript": "Cadastrar",
"Cliente": "2",
"Solicitante": "2",
"TiposSolicitacao": "3",
"Requisito": "2",
"Prioridade": "2",
"DescricaoResumida": "Solicitacao de exemplo",
"Descricao": "Descricao detalhada da solicitacao"
}
2) Consultar
{
"MetodoScript": "Consultar",
"SolicitacaoID": "150"
}
3) Cancelar
{
"MetodoScript": "Cancelar",
"SolicitacaoID": "150",
"Motivo": "Solicitacao aberta em duplicidade"
}
Exemplo de Script
procedure GetMetodo;
var
Metodo: String;
begin
Metodo := UpperCase(ObterMetodoFromBody);
if (Metodo = 'CADASTRAR') then
Cadastrar
else if (Metodo = 'CONSULTAR') then
Consultar
else if (Metodo = 'CANCELAR') then
Cancelar
else
ErroValidacao('Processo invalido. Metodo informado: ' + Metodo);
end;
function ObterMetodoFromBody: String;
var
Body: String;
JsonObj: TPHJson;
begin
Body := Trim(GetBody);
if (Body = '') then
ErroValidacao('Faltou informar o body da requisicao.');
JsonObj := TPHJson.Create;
try
JsonObj.LerJson(Body);
Result := Trim(JsonObj.ElementoDoNome('MetodoScript').Texto);
finally
JsonObj.Free;
end;
end;
function MontarRetornoSucesso(const Detalhes: String): String;
begin
Result :=
'{' +
'"status":"sucesso",' +
'"detalhes":"' + Detalhes + '"' +
'}';
end;
function MontarRetornoErro(const Detalhes: String): String;
begin
Result :=
'{' +
'"status":"erro",' +
'"detalhes":"' + Detalhes + '"' +
'}';
end;
procedure Cadastrar;
var
Body: String;
JsonObj: TPHJson;
SolicitacaoObj: TPHServerClass;
Msg: String;
begin
Body := Trim(GetBody);
JsonObj := TPHJson.Create;
try
JsonObj.LerJson(Body);
SolicitacaoObj := NewPHServerClass('SOLICITACOES');
try
IniciarTransacao;
try
SolicitacaoObj.NovoRegistro;
SolicitacaoObj.CampoDoNome('PESSOA').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Cliente').Texto);
SolicitacaoObj.CampoDoNome('SOLICITANTE').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Solicitante').Texto);
SolicitacaoObj.CampoDoNome('TIPOSOLICITACAO').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('TiposSolicitacao').Texto);
SolicitacaoObj.CampoDoNome('REQUISITO').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Requisito').Texto);
SolicitacaoObj.CampoDoNome('NIVELPRIORIDADE').AsLargeInt := StrToInt(JsonObj.ElementoDoNome('Prioridade').Texto);
SolicitacaoObj.CampoDoNome('NOME').AsString := JsonObj.ElementoDoNome('DescricaoResumida').Texto;
SolicitacaoObj.CampoDoNome('DESCRICAOPROBLEMA').AsString := JsonObj.ElementoDoNome('Descricao').Texto;
SolicitacaoObj.Salvar;
ConfirmarTransacao;
Msg :=
'{' +
'"status":"sucesso",' +
'"detalhes":"Solicitacao cadastrada.",' +
'"SolicitacaoID":"' + IntToStr(SolicitacaoObj.CampoDoNome('ID').AsLargeInt) + '"' +
'}';
except
CancelarTransacao;
Msg := MontarRetornoErro('Erro ao cadastrar solicitacao: ' + ExceptionMessage);
end;
finally
SolicitacaoObj.Free;
end;
finally
JsonObj.Free;
end;
ParamByName('Result').AsString := Msg;
end;
procedure Consultar;
var
Body: String;
JsonObj: TPHJson;
Q: TPHQuery;
SolicitacaoID: String;
Msg: String;
begin
Body := Trim(GetBody);
JsonObj := TPHJson.Create;
try
JsonObj.LerJson(Body);
SolicitacaoID := JsonObj.ElementoDoNome('SolicitacaoID').Texto;
Q := NewPHQuery;
try
Q.Add('SELECT ID, NOME, DESCRICAOPROBLEMA, SITUACAO ' +
'FROM SOLICITACOES ' +
'WHERE ID = :ID');
Q.ParamByName('ID').AsLargeInt := StrToInt(SolicitacaoID);
Q.Open;
if Q.Vazia then
Msg := MontarRetornoErro('Solicitacao nao encontrada.')
else
Msg :=
'{' +
'"status":"sucesso",' +
'"Solicitacao":{' +
'"ID":"' + Q.FieldByName('ID').AsString + '",' +
'"NOME":"' + Q.FieldByName('NOME').AsString + '",' +
'"DESCRICAO":"' + Q.FieldByName('DESCRICAOPROBLEMA').AsString + '",' +
'"SITUACAO":"' + Q.FieldByName('SITUACAO').AsString + '"' +
'}' +
'}';
finally
Q.Free;
end;
finally
JsonObj.Free;
end;
ParamByName('Result').AsString := Msg;
end;
procedure Cancelar;
var
Body: String;
JsonObj: TPHJson;
SolicitacaoObj: TPHServerClass;
Msg: String;
SolicitacaoID: Int64;
begin
Body := Trim(GetBody);
JsonObj := TPHJson.Create;
try
JsonObj.LerJson(Body);
SolicitacaoID := StrToInt(JsonObj.ElementoDoNome('SolicitacaoID').Texto);
SolicitacaoObj := NewPHServerClass('SOLICITACOES');
try
IniciarTransacao;
try
SolicitacaoObj.CampoDoNome('ID').AsLargeInt := SolicitacaoID;
SolicitacaoObj.LerRegistro;
if (SolicitacaoObj.CampoDoNome('ID').AsLargeInt = 0) then
ErroValidacao('Solicitacao nao encontrada para cancelamento.');
SolicitacaoObj.CampoDoNome('SITUACAO').AsString := 'C';
SolicitacaoObj.CampoDoNome('OBS').AsString := JsonObj.ElementoDoNome('Motivo').Texto;
SolicitacaoObj.Salvar;
ConfirmarTransacao;
Msg := MontarRetornoSucesso('Solicitacao cancelada com sucesso.');
except
CancelarTransacao;
Msg := MontarRetornoErro('Erro ao cancelar solicitacao: ' + ExceptionMessage);
end;
finally
SolicitacaoObj.Free;
end;
finally
JsonObj.Free;
end;
ParamByName('Result').AsString := Msg;
end;
begin
end.
Exemplo de Envio (cURL)
Cadastrar
curl -X POST "http://localhost:211/api/solicitacoes" ^
-H "Content-Type: application/json" ^
-H "Authorization: Bearer <access_token>" ^
-d "{\"MetodoScript\":\"Cadastrar\",\"Cliente\":\"2\",\"Solicitante\":\"2\",\"TiposSolicitacao\":\"3\",\"Requisito\":\"2\",\"Prioridade\":\"2\",\"DescricaoResumida\":\"Solicitacao de exemplo\",\"Descricao\":\"Descricao detalhada\"}"
Consultar
curl -X POST "http://localhost:211/api/solicitacoes" ^
-H "Content-Type: application/json" ^
-H "Authorization: Bearer <access_token>" ^
-d "{\"MetodoScript\":\"Consultar\",\"SolicitacaoID\":\"150\"}"
Cancelar
curl -X POST "http://localhost:211/api/solicitacoes" ^
-H "Content-Type: application/json" ^
-H "Authorization: Bearer <access_token>" ^
-d "{\"MetodoScript\":\"Cancelar\",\"SolicitacaoID\":\"150\",\"Motivo\":\"Duplicidade\"}"
Resumo
Com esse padrao, um unico endpoint consegue atender varias operacoes de um mesmo dominio, mantendo:
- Uma URL unica para integracao
- Controle centralizado de autenticacao
- Flexibilidade para evoluir os procedimentos no script
Para respostas personalizadas, utilize sempre:
ParamByName('Result').AsString := <texto ou JSON>;