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

У каждого из нас есть свой план. Кто-то хочет стать космонавтом, кто-то банкиром, а третий уже начальник какой-нибудь компании и у него есть МЕГАплан – стать лидером на рынке чего-либо. И чтобы достичь поставленной цели необходимо чёткое планирование деятельности, постановка и контроль выполнения задач, постоянный мониторинг деятельности подчиненных и т.д. На крайний случай, необходимо всегда иметь под рукой элементарный список задач, чтобы наглядно видеть свою работу и работу других. Именно для таких целей и предназначен замечательный, на мой взгляд, он-лайн сервис “Мегаплан”. И, что замечательно, у Мегаплана появился недавно свой API, а это значит – есть, что использовать в Delphi. Но, вначале, пара слов о самом сервисе, чтобы было представление о том, с чем мы будем иметь дело.

Введение

Мегаплан предоставляет своим пользователям сразу несколько продуктов, каждый из которых рассчитан на свой круг деятельности. К примеру, продукт Таск-менеджер – это простенький сервис для ведения списка повседневных задач, Проджект-менеджер — это система управления проектами и взаимоотношениями с клиентами и т.д.

При регистрации нового аккаунта Вам дается 30-ти дневный бесплатный период использования без каких-либо ограничений, после чего Вы либо отказываетесь от дальнейшего использования продукта, либо переходите на платное обслуживание. Надо сразу сказать, что стоимость не такая уж и высокая. Например, Таск-менеджер обходится всего в 90 рублей в месяц. Почему бы не заплатить, если им удобно пользоваться? В принципе, я уже пообщался по телефону с тех.поддержкой Мегаплана и могу сказать, что беседой остался в целом доволен, равно, как и их дальнейшими планами на развитие (создание приложений под iPhod, iPhone, дальнейшее развитие API и т.д.) и, думаю, что можно будет прикупить Таск-менеджера для себя и своих нынешних коллег по работе.

При регистрации в Мегаплане Вам выдается свой URL для доступа к продукту. Например, мой тестовый аккаунт находится по адресу:

http://webdelphi.megaplan.ru

Здесь же (в своем аккаунте) я могу добавлять/удалять новых сотрудников, не заставляя их регистрировать собственные аккаунты в Мегаплане, а равно как и платить за использование продукта – все достаточно прозрачно и удобно.

Теперь, что касается API. На данный момент API Мегаплана ещё достаточно мал и по способу доступа к данным очень напоминает REST-интерфейс Amazon.com. Напоминает, НО не 1 в 1. Есть некоторые различия о которых мы сегодня и поговорим.

Итак, сегодняшний день посвятим двум задачам:

  1. Авторизуемся в Мегаплане по средствам API
  2. Научимся формировать правильные подписи запросов для получения данных, т.е. на сегодня ограничимся только GET-запросами.

Для работы будем использовать Delphi + Synapse. Из Synapse нам понадобятся следующие модули:

  1. httpsend.pas – для отправки запросов
  2. synacode.pas – для шифрования данных
  3. synautil.pas – для дополнительных преобразований данных, например для перевода строк в HEX-форму, формирования дат запросов и т.д.

Авторизация в Мегаплане

Для авторизации в сервисе нам необходимо отправить GET или POST на адрес:

адрес_аккаунта/BumsCommonApiV01/User/authorize.api

с двумя параметрами:

Login – Ваш логин доступа к аккаунту

Password – MD5 пароля в HEX-форме.

В ответ сервер отдаст нам JSON-массив с двумя ключами:

AccessID – открытый ключ доступа к аккаунту

SecretKey – секретный ключ, который мы будем использовать для формирования подписей.

JSON мы разбирать сегодня не будем, а процедура авторизации может выглядеть следующим образом (для моего тестового аккаунта):

var Post: TStringStream;
    Pass: string;
begin
  with THTTPSend.Create do
    begin
      Pass:=StrToHex(MD5('password'));
      POST:=TStringStream.Create('Login=MyLogin&Password='+Pass);
      Document.LoadFromStream(POST);
      MimeType:='application/x-www-form-urlencoded';
      HTTPMethod('POST','https://webdelphi.megaplan.ru/BumsCommonApiV01/User/authorize.api');
      Memo1.Lines.LoadFromStream(Document);
    end;
end;

После чего, в Memo1 выведется JSON-объект содержащий необходимые нам ключи AccessId и SecretKey, которые мы должны будем каким-либо образом сохранить. Здесь мы использовали для формирования строки пароля две функции:

MD5() – сформировала нам MD5 пароля (строки “password”)

StrToHex() из модуля synautil.pas перевела MD5 в HEX-форму.

Ну а дальше элементарная отправка POST и вывод ответа в Memo.

Формирование подписи и отправка GET-запросов

Как видите, авторизация – дело пары минут. С формированием подписи все несколько сложнее. Для доступа к какой-либо информации аккаунта посредствам API нам необходимо включать в заголовки запрос три заголовка:

  1. “Date:” – дата запроса
  2. “Accept: application/json”
  3. “X-Authorization: AccessID:Signature” – заголовок аутентификации

Если отправляется POST, то дополнительно в заголовки включается заголовок “Content-MD5”. И здесь, основная сложность состоит в том, чтобы правильно сформировать строку Signature. Это строка формируется на основании некой BaseString – строки содержащий сведения о запросе. Схема составления BaseString следующая:

BaseString = HTTP-Verb+LF+ContentMD5+LF+Content-Type+LF+Date+LF+HOST+URI

Здесь HTTP-Verb – тип запроса. Может принимать значения GET, POST, PUT, DELETE

LF – символ перевода строки ($0A)

ContentMD5 – MD5 тела запроса

Content-Type – тип данных, например, для POST это будет строка “application/x-www-form-urlencoded

Date – дата запроса в формате RFC-822, например, Fri, 15 Oct 1999 21:14:56 +0200

HOST – хост вашего аккаунта, например webdelphi.megaplan.ru

URI – адрес куда отправляется запрос, например, для получения списка задач это /BumsTaskApiV01/Task/list.api

Следует обратить особое внимание на следующий момент: даже, если в запросе отсутствует какой либо элемент для формирования BaseString, например тип контента или MD5 тела документа, то символ перевода строки все равно должен присутствовать в строке.

Например, я хочу отправить GET-запрос на получение списка задач в своем аккаунте. В этом случае BaseString будет выглядеть следующим образом:

BaseString = GET$0A$0A$0AWed, 24 Nov 2010 13:42:39 +0600$0Awebdelphi.megaplan.ru/BumsTaskApiV01/Task/list.api

Теперь о том как формируется подпись на основании BaseString. Алгоритм достаточно прост:

  1. Шифруем BaseString, используя алгоритм HMAC-SHA1 (с ключом SecretKey)
  2. Полученное значение переводим в HEX-форму
  3. Полученное значение шифруем, используя Base64.

Функция для формирования подписи для GET-запроса может выглядеть следующим образом:

const
    LF = #$0a;
var BaseString: TStringStream;
    HMACsig,RFCDate: String;
begin
  BaseString:=TStringStream.Create;
  BaseString.WriteString(Method+LF);//метод (передается в параметрах)
  BaseString.WriteString(LF);//ContentMD5 отсутствует
  BaseString.WriteString(LF);//Content-Type отсутствует
  RFCDate:=Rfc822DateTime(Date);//формируем дату в формате RFC-822 (Date:TDateTime - передается в параметрах)
  BaseString.WriteString(RFCDate+LF);
  BaseString.WriteString(URI);//HOST+URI (передается в параметрах)
  HMACsig:=HMAC_SHA1(BaseString.DataString,SecretKey);//зашифровали по HMAC-SHA1
  Result:=EncodeBase64((StrToHex(HMACsig)));//перевели в HEX и шифроали по Base64
  BaseString.Free; 
end;

И теперь остается только отправить наш первый GET и получить данные. Сделать это можно таким образом:

var AccessID, SecretKey,URL: UTF8string;
    HTTP: THTTPSend;
    Date:TDateTime;
    ContentMD5,RFCDate:string;
begin
  AccessID:='1234567890';
  SecretKey:='asdasdasdasdasd';
  HTTP:=THTTPSend.Create;
  URL:='webdelphi.megaplan.ru/BumsTaskApiV01/Task/list.api';
  Date:=Now;//запомнили дату
  ContentMD5:='';
  RFCDate:=Rfc822DateTime(Date);
  {формируем заголовки}
  HTTP.Headers.Add('Date: '+RFCDate);
  HTTP.Headers.Add('X-Authorization: '+AccessID+':'+CalcSigature('GET',SecretKey,URL,ContentMD5,Params,Date));
  HTTP.Headers.Add('Accept: application/json');
  {отправили запрос}
  HTTP.HTTPMethod('GET','http://'+URL);
  {вывели ответ}
  Memo2.Lines.LoadFromStream(HTTP.Document);
  HTTP.Free;
end;

Ответ на этот запрос у меня получился следующий:

megaplan1

Далее остается использовать любую библиотеку для работы с JSON в Delphi, например, SuperObject и парсить ответ сервера. Обратите особое внимание на работу с датой – дата в заголовке запроса обязательно должна совпадать вплоть до секунды с той датой, которая использовалась при формировании подписи.

На сегодня все. Можете регистрироваться в Мегаплане и тестить его API :)

Скачать исходник: Исходники —> 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 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Алексей Сухачёв
Алексей Сухачёв
24/11/2010 16:50

Супер!!! Спасибо!

ad
ad
27/11/2010 12:20

Добый день. Прошу помощи. Пожалуйста  отпишитесь! Делаю всё как описанно в статье http://chuckbeasley.wordpress.com/2009/04/29/using-oauth-for-delphi/ , пытаюсь достучаться до API Твиттера, но всё время идёт ошибка 401. Код в котором идёт ошибка. Остальное(Авторизация) проходит без проблем.   function TMainForm.GETCommand(URL: string): string; var pos: integer; begin try Consumer := nil; Consumer := TOAuthConsumer.Create(Key, Secret, MY_Url); ARequest := TOAuthRequest.Create(URL); ARequest := ARequest.FromConsumerAndToken(Consumer, nil, URL); ARequest.HTTPURL := URL; Token := TOAuthToken.Create(OAuth_token, OAuth_token_secret); ARequest := ARequest.FromConsumerAndToken(Consumer, Token, URL); ARequest.Sign_Request(HMAC, Consumer, Token); pos := AnsiPos(‘?’, URL); if pos = 0 then URL := URL + ‘?’ + ARequest.GetString else URL := URL + ‘&’ + ARequest.GetString; Memo1.Text := MainIdHTTP.Get(Url); finally… Подробнее »

ad
ad
27/11/2010 12:21

Прошу прощения…
[code]
function TMainForm.GETCommand(URL: string): string;
var pos: integer; begin try Consumer := nil; Consumer := TOAuthConsumer.Create(Key, Secret, MY_Url); ARequest := TOAuthRequest.Create(URL); ARequest := ARequest.FromConsumerAndToken(Consumer, nil, URL); ARequest.HTTPURL := URL; Token := TOAuthToken.Create(OAuth_token, OAuth_token_secret); ARequest := ARequest.FromConsumerAndToken(Consumer, Token, URL); ARequest.Sign_Request(HMAC, Consumer, Token); pos := AnsiPos('?', URL); if pos = 0 then URL := URL + '?' + ARequest.GetString else URL := URL + '&' + ARequest.GetString; Memo1.Text := MainIdHTTP.Get(Url); finally end; end;[/code]

ad
ad
27/11/2010 20:21

Да. Я уже думал об этом, но не уверен точно. Ведь когда я через браузер иду по мною образованному запросу получаю ошибку 401, а когда на другой получаю, что такого nonce нету… ну как-то так.
Уверен, что я пишу неверную signature, может где-о ошибка :(

Dmitriy Sinyavskiy
19/09/2012 11:23

Отлично. Сам пользуюсь Мегапланом.
Раньше можно было получить в бесплатное пользование Free версию навсегда, чем я и пользуюсь до сих пор.