уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Сегодня было немного свободного времени и я решил снова немного поработать с API сервиса “Мегаплан”. В прошлый раз мы остановились на том, что научились правильно авторизовываться в сервисе, получать необходимые ключи (AccessId и SecretKey) и подписывать с помощью заголовков свои запросы к API.

Однако каждый раз при запросе вручную формировать необходимые заголовки не совсем удобно, поэтому сегодня продолжим начатую работу и напишем небольшой класс, используя который, можно достаточно просто и удобно отправлять самые распространенные запросы (Get и Post) на сервер.

Итак, определимся с тем, какие операции будут выполнятся классом?

  1. Рассчитывать подпись к запросу
  2. Отправлять GET-запрос и возвращать ответ в виде строки (string)
  3. Отправлять POST-запрос и возвращать ответ в виде строки (string)

Какие модули и библиотеки будет использовать в своей работе класс?

Я решил не изменять своим привычкам и вновь воспользоваться библиотекой Synapse. Из библиотеки нам будут необходимы следующие модули:

  1. httpsend – для отправки запросов
  2. synacode – для работы с MD5, HMAC-SHA1, Base64 и т.д.
  3. ssl_openssl – для поддержки безопасного HTTPS
  4. synautil – для работ со вспомогательными методами, например, для преобразования дат в формат RFC-822 и т.д.

Теперь создаем новый модуль Delphi, подключаем в uses необходимые модули Synapse и определяем новый класс:

type
  TMegaplanRequest = class
  private
    FAccessID: string; //ключ AccessId, полученный при авторизации
    FSecretKey: string; //ключ SecretKey, полученный при авторизации
    FData    : TStringStream;//даные для отправки с помощью POST
    procedure SetData(Str: string);
    function GetData:string;
    function CalcSignarure(const Method,URL: string; Date: TDateTime): string;
    function GetURI(const URL:string):string;
  public
    constructor Create(AccessID,SecretKey: string);
    destructor Destroy;
    function Get(const URL: string):string;
    function Post(const URL:string;Params:TStringList):string;
    property Data: string read GetData write SetData;
end;

Теперь рассмотрим методы, используемые при работе с классом.

Create — конструктор. Создает новый экземпляр класса и заполняет необходимые поля FAccessId и FSecretKey:

constructor TMegaplanRequest.Create(AccessID,SecretKey: string);
begin
  inherited Create;
  FAccessID:=AccessID;
  FSecretKey:=SecretKey;
  FData:=TStringStream.Create;
end;

GetData получает данные из потока FData:TStringStream и представляет данные в виде строки string:

function TMegaplanRequest.GetData: string;
begin
  Result:=FData.DataString
end;

SetData — обновляет данные в потоке FData, записывая в него строку:

procedure TMegaplanRequest.SetData(Str: string);
begin
  FData.Clear;
  FData.WriteString(Str);
end;

GetURI по заданному значению URL определяет URI — строку для формирования подписи:

function TMegaplanRequest.GetURI(const URL: string): string;
begin
  if pos('http://',URL)>0 then
    Result:=Copy(URL,8,length(URL)-7)
  else
    if pos('https://',URL)>0 then
      Result:=Copy(URL,9,length(URL)-8)
    else
      Result:=URL;
end;

CalcSignarure на основании данных, содержащихся в полях класса рассчитывает значение подписи:

function TMegaplanRequest.CalcSignarure(const Method, URL: string;
  Date: TDateTime): string;
var BaseString: TStringStream;
    HMACsig,RFCDate: String;
begin
BaseString:=TStringStream.Create;
try
  BaseString.WriteString(Method+LF);//метод
  if FData.Size=0 then
    BaseString.WriteString(LF)//ContentMD5 отсутствует
  else
    BaseString.WriteString(StrToHex(MD5(FData.DataString))+LF);
  if UpperCase(Method)='POST' then
    BaseString.WriteString('application/x-www-form-urlencoded'+LF)
  else
    BaseString.WriteString(LF);//Content-Type отсутствует
  RFCDate:=Rfc822DateTime(Date);//формируем дату в формате RFC-822
  BaseString.WriteString(RFCDate+LF);
  BaseString.WriteString(URL);//HOST+URI
  HMACsig:=HMAC_SHA1(BaseString.DataString,FSecretKey);//зашифровали по HMAC-SHA1
  Result:=EncodeBase64((StrToHex(HMACsig)));//перевели в HEX и шифроали по Base64
finally
  BaseString.Free;
end;
end;

Get — выполняет GET-запрос и возвращает ответ в виде строки string:

function TMegaplanRequest.Get(const URL: string): string;
var URI:string;
    Date: TDateTime;
    DataStream: TstringStream;
begin
  Date:=Now;
  DataStream:=TStringStream.Create;
try
  with THTTPSend.Create do
    begin
      Headers.Add('Date: '+Rfc822DateTime(Date));
      Headers.Add('X-Authorization: '+FAccessID+':'+CalcSignarure('GET',GetURI(URL),Date));
      Headers.Add('Accept: application/json');
      if HTTPMethod('GET',URL) then
        DataStream.LoadFromStream(Document)
      else
        Exception.Create(Format(cErrString,[ResultCode,ResultString]));
    end;
  Result:=DataStream.DataString;
finally
  DataStream.Free;
end;
end;

Post — отправляет на сервер POST-запрос и возвращает ответ в виде строки:

function TMegaplanRequest.Post(const URL: string): string;
var URI:string;
    Date: TDateTime;
    DataStream: TstringStream;
begin
  Date:=Now;
  DataStream:=TStringStream.Create;
try
  with THTTPSend.Create do
    begin
      Headers.Add('Date: '+Rfc822DateTime(Date));
      Headers.Add('X-Authorization: '+FAccessID+':'+CalcSignarure('POST',GetURI(URL),Date));
      Headers.Add('Accept: application/json');
      FData.Position:=0;
      Document.LoadFromStream(FData);
      if HTTPMethod('POST',URL) then
        DataStream.LoadFromStream(Document)
      else
        Exception.Create(Format(cErrString,[ResultCode,ResultString]));
    end;
  Result:=DataStream.DataString;
finally
  DataStream.Free;
end;
end;

Рассмотрим пример работы с классом TMegaplanRequest. В качестве примера повторим получение списка всех задач, которое мы рассматривали в предыдущем посте про Мегаплан:

var
 MegaAPI: TMegaplanRequest;
begin
  MegaAPI:=TMegaplanRequest.Create('AccessID','SecretKey');
  Memo1.Lines.Add(MegaAPI.Get('http://webdelphi.megaplan.ru/BumsTaskApiV01/Task/list.api'));
  ...
end;

Вот и весь пример. Всего две строки и список всех задач из вашего аккаунта в Мегаплане у Вас в руках, ну, а дальше берем библиотеку SuperObject или другую, предназначенную для работы с JSON и парсим строку на предмет необходимых данных.

Модуль с классом TMegaplanRequest можно скачать здесь:

Скачать исходник: Исходники —> API онлайн-сервисов —> Прочие API

Книжная полка

Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
6 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
trackback

[…] This post was mentioned on Twitter by Королевство Delphi, Vlad. Vlad said: Класс для отправки запросов к Мегаплан API. | Delphi в Internet http://bit.ly/fyGY14 […]

Алексей Сухачёв
Алексей Сухачёв
13/12/2010 19:20

Спасибо!

Олег К
Олег К
20/05/2013 15:29

Влад, здравствуйте.

Получилось победить POST?

Олег К
Олег К
20/05/2013 16:17
Ответить на  Vlad

При попытке отправить любой POST-запрос, получаю «401 Unauthorized».
Меняю метод «POST» на «GET» — все Ок.
Я подумал, что «не хотят отсылаться POST-запросы» — из той же оперы.

Можно, конечно, и задачи методом GET создавать, но как-то криво :(
Код с паролями могу в мыло кинуть.