Ещё когда только начинал изучать API Twitter’а хотел воспользоваться OAuth-авторизацией для работы. Но за неимением знаний о том, как построена в принципе эта система авторизации пользователей, всё как-то не пробовал даже поискать готовых решений. Вчера решил вернуться к решению этого вопроса по нескольким причинам:
- Для клиентов, работающих через OAuth лимит запросов к API увеличен
- Разработчики API уже давным давно обещались перевести работу с API только через OAuth (хотя Base-авторизацию оставит, но лимит на запросы будет в 2 раза ниже)
- При работе через OAuth ваше приложение получает одно небольшое, но вполне ощутимое преимущество — в каждоем сообщении, отправленном через Ваш клиент будет указываться название Вашего приложения со ссылкой на сайт. Выглядит это примерно так:
Ну, а ссылка на Ваш сайт в огромной куче сообщений (если приложение будет пользоваться успехом у пользователей) — это какой-никакой, а прирост трафика на сайт. Буквально вчера нашел класс Delphi для работы с API Twitter’а с использованием OAuth-авторизации.
Точнее даже сказать отдельную библиотеку, реализующую OAuth в Delphi и класс для Twitter API.
Рассматривать вопрос «Что такое OAuth?», думаю смысла нет, т.к. в Сети валом самой разнообразной информации на эту тему, а вот рассмотреть пример работы с классом TTwitter, думаю стоит. Итак, скачивайте немного доработанные модули:
[download id=»49″ format=»1″]Рассмотрим весь процесс работы по пунктам.
1. Регистрируем наше приложение. Для этого заходим на страницу, заполняем все необходимые поля и жмем Save. После чего нам выдадут два ключа для приложения: consumer key и consumer secret. Сохраните эти ключи — они нам пригодятся.
2. Создаем новый проект Delphi и подключаем в uses модули Twitter и OAuth. Теперь размещаем на главной форме следующие элементы: 2 TButton, 3 TEdit, 1 TMemo, 1 TidHTTP. Должно получиться примерно следующее:
3. Начинаем процесс авторизации. Создаем глобальную переменную TwitterObj: TTwitter; и в обработчике события onClick кнопки «Start Authorization» определяем необходимые переменные и создаем объекты:
procedure TForm9.Button1Click(Sender: TObject); var Callback_URL: string; Key, Secret: string; Response, URL: string; endpos: integer; begin TwitterObj:=TTwitter.Create; TwitterObj.Source:='LinkCompressor'; TwitterObj.Key:=Edit1.Text; //consumer key TwitterObj.Secret:=Edit2.Text; //consumer secret TwitterObj.Consumer := TOAuthConsumer.Create(TwitterObj.Key, TwitterObj.Secret); TwitterObj.HMAC := TOAuthSignatureMethod_HMAC_SHA1.Create; ...
Теперь начинаем по пунктам выполнять весь процесс авторизации. Вначале получаем Token:
URL := 'http://twitter.com/oauth/request_token'; TwitterObj.Request := TOAuthRequest.Create(URL); TwitterObj.Request := TwitterObj.Request.FromConsumerAndToken(TwitterObj.Consumer, nil, URL); TwitterObj.Request.Sign_Request(TwitterObj.HMAC, TwitterObj.Consumer, nil); URL := URL + '?' + TwitterObj.Request.GetString; Response := idHTTP1.Get(URL);
Сервер вернет нам два значения: oauth_token и oauth_token_secre. Получим эти значения из строки ответа:
endpos := AnsiPos('&oauth_token_secret=', Response); TwitterObj.OAuth_token := ''; TwitterObj.OAuth_token_secret := ''; TwitterObj.OAuth_token:=Copy(Response, 13, endpos-13); Response := Copy(Response, endpos, Length(Response)); TwitterObj.OAuth_token_secret := Copy(Response, 21, Length(Response)); TwitterObj.Token := TOAuthToken.Create(TwitterObj.OAuth_token, TwitterObj.OAuth_token_secret);
Следующий шаг — запрос авторизации пользователя. И здесь нам придётся воспользоваться WebBrowser’ом. Небходимо отправить пользователя на страницу Twitter’а где он введет логин и пароль и получит в ответ PIN-код:
URL := 'http://twitter.com/oauth/authorize'; Callback_URL := 'http://webdelphi.ru'; URL := URL + '?' + 'oauth_token=' + TwitterObj.OAuth_token + '&' + 'oauth_token_secret=' + TwitterObj.OAuth_token_secret + '&oauth_callback=' + TOAuthUtil.urlEncodeRFC3986(Callback_URL); WebBrowser1.Navigate(URL);
На этом моменте следует остановиться и подождать пока пользователь не введет в третий Edit значение PIN-кода. После того как PIN-код получен, можно заканчивать процесс авторизации и начать работать с API. Для примера, в обработчике onClick кнопки «Send PIN» я закончу процесс авторизации и отправлю в Twitter новое сообщение. Заканчиваем процесс авторизации пользователя:
URL := 'http://twitter.com/oauth/access_token'; TwitterObj.Consumer := nil; TwitterObj.Consumer := TOAuthConsumer.Create(TwitterObj.Key, TwitterObj.Secret, 'http://webdelphi.ru'); TwitterObj.Request.HTTPURL := URL; TwitterObj.Request := TwitterObj.Request.FromConsumerAndToken(TwitterObj.Consumer, TwitterObj.Token, URL); TwitterObj.Request.Sign_Request(TwitterObj.HMAC, TwitterObj.Consumer, TwitterObj.Token); URL := URL + '?' + TwitterObj.Request.GetString+'&oauth_verifier='+Edit3.Text; Memo1.Lines.Clear; Memo1.Lines.Add(URL); Response := idHTTP1.Get(URL); Memo1.Lines.Add(''); Memo1.Lines.Add(Response); endpos := AnsiPos('&oauth_token_secret=', Response); TwitterObj.OAuth_token := ''; TwitterObj.OAuth_token := Copy(Response, 13, endpos-13); Response := Copy(Response, endpos, Length(Response)); endpos := AnsiPos('&user', Response); TwitterObj.OAuth_token_secret := ''; TwitterObj.OAuth_token_secret := Copy(Response, 21, endpos-21); Memo1.Lines.Add(''); Memo1.Lines.Add(TwitterObj.OAuth_token_secret);
И отправляем сообщение в Twitter:
Memo1.Lines.Text:=TwitterObj.Update(('Hello Twitter!!!'),xml);
И вот, что мне не совсем понятно при работе с Twitter’ом с использованием этого метода авторизации. Согласно документации API символы в запросах должны кодироваться стандартными методами, т.е., например, строка вида:
Google+Модератор
Должна выглядеть в закодированном виде как:
Google %D0%9C%D0%BE%D0%B4%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80
С английским языком проблем нет — всё работает на ура. Проблема с русским — он в упор не хочет переводится из закодированного состояния в нормальный текст. Вроде бы нашел вариант решения проблемы — представлять русский текст в виде кодов в Unicode. Например так:
&_#1055;&_#1088;&_#1086;&_#1075;&_#1088;&_#1072;&_#1084;&_#1084;&_#1080;&_#1088;&_#1086;&_#1074;&_#1072;&_#1085;&_#1080;&_#1077;. Delphi, Lazarus, Free Pascal
Без символа «_». Что представляет собой строку:
Программирование. Delphi, Lazarus, Free Pascal
Но опять же трабл — пробелы между английскими словами отправляются нормально, а между русскими — не хотят. На любой такой запрос вылетает 401 ошибка, означающая, чо авторизация не прошла, а в описании ошибки «Incorrect Signature» хотя моя подпись ни при чём.
В общем пока застрял на работе с русским текстом — решаю проблему. Буду рад любой посильной помощи.
Кстати я неспроста решил вернуться к API Twitter. Дело в том, что в коллективном разуме лидирует предложение о создании органайзера с возможностью синхронизации контактов Twitter, FaceBook и т.д. Так что как доделаю API Контактов — попробую синхронизировать их с Twitter’ом…есть небольшая идея.
>> Проблема с русским – он в упор не хочет переводится из закодированного состояния в нормальный текст. Вроде бы нашел вариант решения проблемы – представлять русский текст в виде кодов в Unicode. Например так:
А если использовать :
function WideStr2UTF8URLEncode(const WStr:WideString):string;
var
UStr:UTF8String;
i:integer;
begin
UStr:=UTF8Encode(WStr);
result:=»;
if length(UStr)>0 then
for i:=1 to length(UStr) do
result:=result+’%’+IntToHex(ord(UStr[i]),2);
end;
У меня это работало, при Base-авторизации.
При base-авторизации у меня все работает на ура, если делать даже так (используя Synapse модуль synacode):
EncodeUrl(AnsiToUtf8(‘Бла-бла-бла — это русский текст’))
А при OAuth — ни в какую….Сейчас проверю Ваш вариант, спасибо за подсказку :)
UPDATE: опять не хочет — на отправке снова выкидывает 401 типо неавторизован :(((
У меня в Twitter-е все сработало, спасибо. А нет ли у Вас подобного решения по LinkedIn-у? Дело в том, что там POST-запросы, все вроде то же самое, только всегда нарываюсь на 401 при первом же запросе (ругается на signature, но она точно верна)… Возможно я упускаю какой-то незнакомый мне нюанс…
C LinkedIn я не работал, как-то не довелось. Но, могу сказать, что вы возможно упускаете тот факт, что подпись генерируется на момент отправки запроса. Если, например, запрос отправляется в 12 часов 12 минут 10 секунд, то это же самое время используется в алгоритме формирования подписи. Если есть расхождения по времени, то подпись может не пройти аутентификацию.
Очень жаль, что не работали. Да нет, я пользуюсь Вашим классом TTwitter. Просто там формирование строки, с помощью которой формируется signature, описано как то через пень колоду. Что ни пробую, все не так. Ну извините за беспокойство…
Я так понимаю, это кадый раз при запуске програмки надо проходить такую длинную авторизацию с вбиванием логина пароля на твитере, и вставки пина ?
не обязательно. Достаточно запомнить параметры авторизации. И проводить авторизацию по-новой только после того, как истек срок действия ключа.
После того как я залогинелся и дал доступ PIN код никто мне не вернул!!! сработал редирект на урл колбека и все!
В последний раз, когда использовал API Twitter, то работал этот код -> http://www.webdelphi.ru/2010/05/twitter-oauth-i-russkie-simvoly-resheno/ Если не работает сейчас — открываем документацию по API и читаем чего там изменили.
если в теле твита будет «=» ошибочка вылазит
сергей, есть такое дело. Надо спец.символы записать в массив исключений, тогда должно всё заработать без ошибок
ага понял, в статье «Twitter OAuth и русские символы. Решено.» описано, спасибо.
сергей, не за что.
З.Ы. Всё руки не доходят нормально серии постов перелинковать…надо будет заняться
[…] так давно я писал про единственную более менее готовую библиотеку OAuth […]
[…] одном из постов про OAuth и Twitter я говорил, что с имеющейся в наличии и единственной […]