Для работы понадобилось провести в разрабатываемую программу интеграцию с системой хелпдеска GLPI. Поиск в интернете примеров на Delphi не принес приемлемых результатов и пришлось все писать с нуля. Вот решил поделиться примером создания заявки с прикреплением файла.
P.S. также рекомендую к прочтению вот эту статью, в ней описано GLPI настраивать для включения REST API
Глобальные переменные и константы:
const
AppToken = 'hAQiq39NeHWaQ25t6cTkV8762VcHL2Tds7qBuLR4';
userToken = 'pRHHulWPKXqSrL3xS8vlSCqGIsOu7HWb7rJ3ixI4';
var
session_token : string;
GlpiUser, GlpiPassword, GlpiRestUrl : string;
Начинаем все с подключения к GLPI и получения токена сессии:
Function Get_session_token : string;
var
IdHTTP: TIdHTTP;
Answer: string;
JSON : TJSONObject;
begin
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
IdHTTP.Request.ContentType := 'application/json';
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
IdHTTP.Request.ContentEncoding := 'utf-8';
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'user_token ' + userToken;
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
Answer := IdHTTP.Get(GlpiRestUrl + '/initSession/');
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
Result := JSON.Get('session_token').JsonValue.Value;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Также нам понадобиться функция для закрытия сессии:
Function KillSession (sToken: string) : boolean;
var
IdHTTP: TIdHTTP;
Answer: string;
begin
if sToken = '' then Exit;
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
IdHTTP.Request.ContentType := 'application/json';
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
IdHTTP.Request.ContentEncoding := 'utf-8';
IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
Answer := IdHTTP.Get(GlpiRestUrl + '/killSession/');
if IdHttp.ResponseCode = 200 then Result := true
else Result := false;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Ну и сама функция создания заявки с прикреплением файла:
Function CreateTiket (sToken : string): string;
var
IdHTTP: TIdHTTP;
Answer: string;
JSON, JSON2, JSON3 : TJSONObject;
JsonToSend: TMemoryStream;
jsontext : string;
doc_id, doc_prefix, doc_file : string;
MultiData : TIdMultiPartFormDataStream;
JSONArray : TJSONArray;
newticket_id : string;
begin
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
IdHTTP.Request.ContentType := 'multipart/form-data'; // Это для загрузки документов
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
Idhttp.Request.AcceptEncoding := 'gzip, identity;q=0';
IdHttp.Compressor := TIdCompressorZLib.Create(IdHttp);
Idhttp.Request.Accept := 'application/json';
Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
IdHTTP.Request.ContentEncoding := 'utf-8';
//Параметр user_token берётся из Ключ удалённого доступа настроек пользователя Администрирование -> Пользователи -> USERNAME -> Настройки
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'user_token ' + userToken;
//"Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
//"Session-Token" получаем в функции
IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
//Старт Загружаем файл
MultiData := TIdMultiPartFormDataStream.Create;
MultiData.AddFormField('uploadManifest', '{"input": {"name": "Документ заявки 0000", "_filename" : "DocName", "is_recursive" : true}}', 'utf-8', 'application/json').ContentTransfer := '8bit';
with MultiData.AddFile('filename[0]','c:\testpicture01.jpg','') do //добавляем файл
begin
HeaderCharset := 'utf-8';
HeaderEncoding := '8';
end;
//Конец Загружаем файл
//GlpiRestURL - путь к вашему GLPI. Например 'http://10.0.0.10/glpi/apirest.php';
Answer := IdHTTP.Post(GlpiRestURL + '/Document/', MultiData); // отправляем документ
MultiData.Free;
//Старт Разбираем полученный ответ
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
doc_id := JSON.Get('id').JsonValue.Value; // Получаем ID загруженного файла
JSON2 := TJSONObject(JSON.Get('upload_result').JsonValue);
JSONArray := TJSONArray(JSON2.Get(0).JsonValue);
JSON3 := TJSONObject(JSONArray.Get(0));
doc_file := JSON3.GetValue('name').Value; // Эти значения не нужны, это для примера разбора JSON
doc_prefix := JSON3.GetValue('prefix').Value; //Эти значения не нужны, это для примера разбора JSON
//Конец Разбираем полученный ответ
if (IdHttp.ResponseCode <> 200) and (IdHttp.ResponseCode <> 201) then Result := 'Ошибка при создании заявки (' + Answer + ')'
else
begin
// Старт Отправляем запрос на создание заявки
IdHTTP.Request.ContentType := 'application/json'; // Это отправки json
jsontext := '{"input": {"name": "Заявка тестовая", "content": "Описание","status":"1",' +
'"requesttypes_id":"8","_users_id_assign":"23","time_to_resolve":"2020-06-13 18:00:00",'+
'"itilcategories_id":"23","urgency":"3","priority":"3"}}';
JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);
Answer := IdHTTP.Post(GlpiRestURL + '/Ticket', JsonToSend);
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
newticket_id := JSON.Get('id').JsonValue.Value; //Получяаем ID созданной заявки
//Конец Отправляем запрос на создание заявки
// Старт Отправляем запрос на прикрепление файла к заявке
jsontext := '{"input": {"documents_id" : "' + doc_id + '", "items_id" : "' + newticket_id + '", "itemtype" : "Ticket" }}';
JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);
Answer := IdHTTP.Post(GlpiRestURL + '/Document_Item', JsonToSend);
//Конец Отправляем запрос на прикрепление файла к заявке
Result := 'Заявка создана'
end;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Используется например так:
procedure TForm1.Button1Click(Sender: TObject);
Begin
GlpiUser := 'GlpiUsername';
GlpiPassword := 'SuperPassword';
GlpiRestUrl := 'http://10.0.0.10/glpi/apirest.php';
session_token := Get_session_token;
ShowMessage(CreateTiket(session_token));
KillSession(session_token);
end;
P.S. также рекомендую к прочтению вот эту статью, в ней описано GLPI настраивать для включения REST API
Глобальные переменные и константы:
const
AppToken = 'hAQiq39NeHWaQ25t6cTkV8762VcHL2Tds7qBuLR4';
userToken = 'pRHHulWPKXqSrL3xS8vlSCqGIsOu7HWb7rJ3ixI4';
var
session_token : string;
GlpiUser, GlpiPassword, GlpiRestUrl : string;
Начинаем все с подключения к GLPI и получения токена сессии:
Function Get_session_token : string;
var
IdHTTP: TIdHTTP;
Answer: string;
JSON : TJSONObject;
begin
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
IdHTTP.Request.ContentType := 'application/json';
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
IdHTTP.Request.ContentEncoding := 'utf-8';
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'user_token ' + userToken;
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
Answer := IdHTTP.Get(GlpiRestUrl + '/initSession/');
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
Result := JSON.Get('session_token').JsonValue.Value;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Также нам понадобиться функция для закрытия сессии:
Function KillSession (sToken: string) : boolean;
var
IdHTTP: TIdHTTP;
Answer: string;
begin
if sToken = '' then Exit;
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
IdHTTP.Request.ContentType := 'application/json';
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
IdHTTP.Request.ContentEncoding := 'utf-8';
IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
Answer := IdHTTP.Get(GlpiRestUrl + '/killSession/');
if IdHttp.ResponseCode = 200 then Result := true
else Result := false;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Ну и сама функция создания заявки с прикреплением файла:
Function CreateTiket (sToken : string): string;
var
IdHTTP: TIdHTTP;
Answer: string;
JSON, JSON2, JSON3 : TJSONObject;
JsonToSend: TMemoryStream;
jsontext : string;
doc_id, doc_prefix, doc_file : string;
MultiData : TIdMultiPartFormDataStream;
JSONArray : TJSONArray;
newticket_id : string;
begin
try
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Request.Connection := 'Keep-Alive';
IdHTTP.Request.ContentType := 'multipart/form-data'; // Это для загрузки документов
idHttp.Request.BasicAuthentication := true;
idHttp.Request.Username := GlpiUser;
idHttp.Request.Password := GlpiPassword;
Idhttp.Request.AcceptEncoding := 'gzip, identity;q=0';
IdHttp.Compressor := TIdCompressorZLib.Create(IdHttp);
Idhttp.Request.Accept := 'application/json';
Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
IdHTTP.Request.ContentEncoding := 'utf-8';
//Параметр user_token берётся из Ключ удалённого доступа настроек пользователя Администрирование -> Пользователи -> USERNAME -> Настройки
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'user_token ' + userToken;
//"Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)
IdHTTP.Request.CustomHeaders.Values['App-Token'] := AppToken;
//"Session-Token" получаем в функции
IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
//Старт Загружаем файл
MultiData := TIdMultiPartFormDataStream.Create;
MultiData.AddFormField('uploadManifest', '{"input": {"name": "Документ заявки 0000", "_filename" : "DocName", "is_recursive" : true}}', 'utf-8', 'application/json').ContentTransfer := '8bit';
with MultiData.AddFile('filename[0]','c:\testpicture01.jpg','') do //добавляем файл
begin
HeaderCharset := 'utf-8';
HeaderEncoding := '8';
end;
//Конец Загружаем файл
//GlpiRestURL - путь к вашему GLPI. Например 'http://10.0.0.10/glpi/apirest.php';
Answer := IdHTTP.Post(GlpiRestURL + '/Document/', MultiData); // отправляем документ
MultiData.Free;
//Старт Разбираем полученный ответ
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
doc_id := JSON.Get('id').JsonValue.Value; // Получаем ID загруженного файла
JSON2 := TJSONObject(JSON.Get('upload_result').JsonValue);
JSONArray := TJSONArray(JSON2.Get(0).JsonValue);
JSON3 := TJSONObject(JSONArray.Get(0));
doc_file := JSON3.GetValue('name').Value; // Эти значения не нужны, это для примера разбора JSON
doc_prefix := JSON3.GetValue('prefix').Value; //Эти значения не нужны, это для примера разбора JSON
//Конец Разбираем полученный ответ
if (IdHttp.ResponseCode <> 200) and (IdHttp.ResponseCode <> 201) then Result := 'Ошибка при создании заявки (' + Answer + ')'
else
begin
// Старт Отправляем запрос на создание заявки
IdHTTP.Request.ContentType := 'application/json'; // Это отправки json
jsontext := '{"input": {"name": "Заявка тестовая", "content": "Описание","status":"1",' +
'"requesttypes_id":"8","_users_id_assign":"23","time_to_resolve":"2020-06-13 18:00:00",'+
'"itilcategories_id":"23","urgency":"3","priority":"3"}}';
JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);
Answer := IdHTTP.Post(GlpiRestURL + '/Ticket', JsonToSend);
JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
newticket_id := JSON.Get('id').JsonValue.Value; //Получяаем ID созданной заявки
//Конец Отправляем запрос на создание заявки
// Старт Отправляем запрос на прикрепление файла к заявке
jsontext := '{"input": {"documents_id" : "' + doc_id + '", "items_id" : "' + newticket_id + '", "itemtype" : "Ticket" }}';
JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);
Answer := IdHTTP.Post(GlpiRestURL + '/Document_Item', JsonToSend);
//Конец Отправляем запрос на прикрепление файла к заявке
Result := 'Заявка создана'
end;
finally
IdHTTP.Free;
end;
finally
end;
except
on E: Exception do
ShowMessage('Error: '+E.ToString);
end;
end;
Используется например так:
procedure TForm1.Button1Click(Sender: TObject);
Begin
GlpiUser := 'GlpiUsername';
GlpiPassword := 'SuperPassword';
GlpiRestUrl := 'http://10.0.0.10/glpi/apirest.php';
session_token := Get_session_token;
ShowMessage(CreateTiket(session_token));
KillSession(session_token);
end;