C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Работа с TRESTClient, TOAuth2, VK API  (Прочитано 7281 раз)
nek
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 16


Работа с TRESTClient, TOAuth2, VK API
« : 16 Март 2014, 01:29:52 »

Доброго времени суток. Понадобилось прикрутить к проге (пишу в RAD Studio XE5 на C++ т.е. пытаюсь ), возможность тырить информацию о видео ВКонтакте.
Начал разбираться с API. Пока делал всё вручную через обычный браузер.


Если коротко, то всё делается примерно так (Принцип вам знаком? Смело пропускайте все это, основной вопрос после блока Код):

Создаём Standalone приложение на сайте ВК в разделе "Разработчикам". В результате получаем 2 параметра: номер приложения и secret. Авторизация проводится по протоколу OAuth 2.0
Далее нужно отправить запрос на получение токена, который в свою очередь используется для всех остальных операций от имени пользователя.
Мой запрос будет выглядить так: **tps://oauth.vk.com/authorize?client_id=ид_приложения&scope=video,offline&redirect_uri=**tps://oauth.vk.com/blank.html&display=page&v=5.14&response_type=token
Теперь по порядку. Client_ID - это понятно; scope - для тестирования позволю себе бесконечный токен)) и мне нужен доступ к видео; redirect_uri - хорош, когда с API работает сайт, на этот адрес вышлют тот самый токен, но т.к. приложение standalone, то и отправлять ответ некуда (redirect_uri можно и не указывать, всё равно будет blank); display - тип окна авторизации (page, mobile,..); v - версия API; response_type - какой прислать ответ токен или code?

Что получится, если всё это дело выполнить в браузере? Появится окно авторизации ВК, если пользователь не вошел на свой акк, то ему предложат ввести пароль и логин, затем спросят давать ли привилегии приложению такому-то или нет? Те самые video и доступ к видеозаписям и offline - доступ в любое время, даже, если пользователь не в сети.
В строке браузера появится ссылка: **ps://oauth.vk.com/blank.html#access_token=Набор_Буков_и_Цифр&expires_in=0&user_id=ИД_Пользователя_ВК
А вместо страницы надпись: Пожалуйста, не копируйте данные из адресной строки для сторонних сайтов. Таким образом Вы можете потерять доступ к Вашему аккаунту.
Оно и понятно, токен то бесконечный. Зная его и ид можно начать гадить согласно запрошенным разрешениям от имени пользователя)
expires_in без offline будет содержать не нулевое значение. Например 86000 (сек)

Всё, теперь можно выполнять методы. Лезу смотреть документацию. Нужный мне метод video.get.
Запрос должен быть таким: **ps://api.vk.com/method/'''METHOD_NAME'''?'''PARAMETERS'''&access_token='''ACCESS_TOKEN'''
Ага,
**tps://api.vk.com/method/video.get?owner_id=-51189706&count=1&access_token=токен_полученный_при_авторизации&v=5.14&extended=1
owner_id - имя группы или пользователя (минус ставится, если группа). count - кол-во результатов в ответе API, extended - отобразить доп. параметры такие как приватность.

Результат:
Специально вставил пробелы для наглядности. Так всё будет подряд.
Код:
{"response":{
"count":1296,
"items":
[{
"id":168023859,
"owner_id":-51189706,
"title":"Пока никто не видит. Пёс и скрытая камера",
"duration":127,
"description":"\nЕще больше крутых видео: vk.com\/just_vid\nРекомендую!",
"date":1394873597,"views":36621,"comments":55,
"photo_130":"http:\/\/cs619719.vk.me\/u191269\/video\/s_cb41ed31.jpg",
"photo_320":"http:\/\/cs619719.vk.me\/u191269\/video\/l_465756dc.jpg",
"player":"http:\/\/www.youtube.com\/embed\/7D5bPLxU8U8",
"can_comment":1,"can_repost":1,"likes":{"user_likes":0,"count":7413},
"repeat":0}
]}}
---------------------------
Отсюда мне нужны: "player" - ссылка на видео и описание - "title". Пока всё, остально по мере надобности доделаю сам.
В результате ошибочного запроса ответ будет error и другие поля тоже будут error со всякими животрепещущими подробностями.
А можно и id. ...com/videos-owner_id присоединю id и получится намного аккуратнее.
Player содержит любую ссылку, которую поддерживает ВК.

Всё это прекрасно и замечательно, НО как всегда страдает реализация. Погуглив нашел Indy компонент TRESTClient (response и т.д.). Он поддерживает OAuth 2.0 и обладает собственным веб интерфейсом авторизации. Добился я от него лишь code, видимо без secret_key не обойтись, однако где-то в документации вычитал, что его не рекомендуется вставлять в код программы из-за угрозы безопасности, всего 2 запроса, авторизация и видео, секрет нафиг не нужен.
С английским туго, много инфы про делфи и другие соц. сети). Как же мне организовать именно так как требует ВК?

Вторая проблема - дальнейшее выполнение методов с помощью этих самых компонентов. В результате мне бы просто иметь переменные выдернутые из ответа JSON. Опять же подойдут ли компоненты TRest* ?
Вопрос в том связываться ли вообще с Indy или легче использовать другие способы/библиотеки (с примерами желательно)
Мои запрсы API в тексте выше

P.S.: Собственно почему я такими мелочами озаботился? Да потому, что мало работал вообще с HTTP и с JSON в частности. Одним словом нуб)
« Последнее редактирование: 06 Июнь 2014, 22:15:28 от nek » Записан
S0mbre
Глобальный модератор


Сказали спасибо: +1113/-22
Offline

Сообщений: 2132

S0mbre


Re: TRESTClient + VK API?
« Ответ #1 : 16 Март 2014, 09:12:14 »

Привет. Самое первое решение, которое приходит в голову, - использовать Indy для запросов / ответов, получать ответ (тот JSON код, который ты привел) в виде ответа от сервера (простая строка), а затем "скармливать" эту строку парсеру JSON. Благо для этого есть классы TJSON... - TJSONValue и его производные классы. Почитай справку и примеры тут. По Indy на форуме и в инете много примеров (например тут). Также в дистрибутиве Indy есть готовые примеры - их можно скачать тут.
Записан
nek
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 16


Re: TRESTClient + VK API?
« Ответ #2 : 18 Март 2014, 20:26:43 »

Спасибо, там кстати можно в XML получить ответ, но это уже другая история, сейчас я смотрю на IdHTTP. Для работы с SSL нужен IdSSLIOHandlerSocketOpenSSL.
Ставлю эти 2 компонента на форму, HandleRedirects у IdHTTP - true, далее выполняю IdHTTP1->Get("https://oauth.....") и по идее в OnRedirect можно отловить адрес, по которому совершен переход (а это и есть токен, user_id и время жизни токена): IdHTTP1->Response->Location;
С HTTP всё ок, а вот с HTTPS пустая строка. IOHandler тоже имеет свои опции...будем поискать.

upd.: все параметры поумолчанию, но даже с портом 443 в IOHandler - хост localhost и др. значения, destanation: oauth.vk.com пока пусто. С фаерволлом всё ок.
uupd: Как только выполняю к примеру IdSSLIOHandlerSocketOpenSSL1->Open(), сразу ругается на отсутствие dll'шек (я так понимаю ssleay32.dll и libeay32.dll)
« Последнее редактирование: 19 Март 2014, 07:48:03 от nek » Записан
S0mbre
Глобальный модератор


Сказали спасибо: +1113/-22
Offline

Сообщений: 2132

S0mbre


Re: TRESTClient + VK API?
« Ответ #3 : 19 Март 2014, 08:08:00 »

Цитата: nek от 18 Март 2014, 20:26:43
uupd: Как только выполняю к примеру IdSSLIOHandlerSocketOpenSSL1->Open(), сразу ругается на отсутствие dll'шек (я так понимаю ssleay32.dll и libeay32.dll)

Эти библиотеки должны быть доступны для приложения, использующего Indy. Лучше распространять вместе с ними. Можно взять из \bin\subversion\
Записан
nek
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 16


Re: TRESTClient + VK API?
« Ответ #4 : 19 Март 2014, 23:02:14 »

До распространения мне ещё как до луны)  Точно! Сначала приходит страница авторизации)

Нашел VCL компонент, но он для Delphi
C TRESTOAuth вроде бы разобрался, по крайней мере вручную массив items я получил, теперь остался парсинг. Есть стандартные классы TJSONObject, Pair, Array и т.д.
Кто поможет с примером? Как и говорил ранее мне нужно всего id, owner_id, title.
« Последнее редактирование: 29 Март 2014, 14:31:31 от nek » Записан
S0mbre
Глобальный модератор


Сказали спасибо: +1113/-22
Offline

Сообщений: 2132

S0mbre


Re: TRESTClient + VK API?
« Ответ #5 : 31 Март 2014, 08:13:09 »

nek, я же давал ссылку на примеры по JSON. В XE5 это все уже есть, не надо никаких дополнительных компонентов.

Например, есть у тебя строка
Код
String sTxt = 
"{\"obj\": {\"items\": [10, 20, 30, 40], \"subobject\": {\"id\": \"sub_id\", \"number\": 0} } }";
 

Тебе надо ее перевести в объект JSON. Как показано в примере, это можно сделать методом ParseJSONValue или Parse:
Код
TJSONObject* jObj = new TJSONObject();
jObj->ParseJSONValue(sTxt);
 

Теперь объект jObj содержит данные в JSON формате:
Цитировать
obj:
   items: [10, 20, 30, 40]
   subobject:
      id: "sub_id"
      number: 0

Получить доступ к единственной JSON-паре (с ключом "obj") можно так:
Код
TJSONPair* jPair = jObj->Get(0); // 1-ая пара в объекте
 
// или так:
 
TJSONPair* jPair = jObj->Get("obj"); // доступ по ключу
 

Аналогично для вложенных данных. Например, значение obj > subobject > number (0) получаем так:
Код
int number = dynamic_castTJSONNumber*>(jPair->Value->Get("subobject")->Value->Get("number")->Value)->AsInt;
 

Любой объект JSON (образованный от TJSONValue) можно представить как строку методом ToString().
Записан
nek
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 16


Re: TRESTClient + VK API?
« Ответ #6 : 31 Май 2014, 14:49:15 »

Цитировать
int number = dynamic_cast(jPair->Value->Get("subobject")->Value->Get("number")->Value)->AsInt;
Не катит
Да и вообще какие-то мои попытки оказываются бесполезными) Ошибка обращения к памяти (Наверное потому, что результат {})
Ещё раз, мну нужны title, id, owner_id, player
Код:
{"response":{"count":1630,"items":[{"id":1678778,"owner_id":-500006,"title":"Jenga Cat","duration":83,"description":"Еще больше крутых видео","date":1401295310,"views":454,"comments":5,"photo_130":"http:\/\/cs541206.vk.me\/u2949887\/video\/s_af146ce5.jpg","photo_320":"http:\/\/cs541206.vk.me\/u2949887\/video\/l_1b666cdd.jpg","player":"http:\/\/vk.com\/video_ext.php?oid=-50006&id=1678778&hash=a89ac9f2208445bf","can_comment":1,"can_repost":1,"likes":{"user_likes":0,"count":35},"repeat":0}]}}

С самими запросами через REST вроде всё понятно кроме формы (Tfrm_OAuthWebForm)

Не говорю, что это правильный пример, даже Free запихнул, однако именно в FJSONObject->Get(i)... будет ошибка rtl200, rtl120 (я так понимаю утечка памяти или 0 значения какие-то) в зависимости от операторов. Может я не так загружаю (а пробовал и Edit, Memo, строки и т.д.).
Надо с простыми JSON'ами попробовать.

Код:
if(OpenDialog1->Execute())
{
TJSONObject* FJSONObject = new TJSONObject;
TStringList* sList = new TStringList;

sList->LoadFromFile(OpenDialog1->FileName);
(TJSONObject*)FJSONObject->ParseJSONValue(sList->Text); //Без разницы есть (TJSONObject) или нет

String s = FJSONObject->ToString();
ShowMessage(s);//Ответ {}

ListBox1->Clear();

int i;
for( i = 0;FJSONObject->Size()-1;i++)
{
ListBox1->Items->Add(FJSONObject->Get(i)->JsonString->Value()); //Ошибка
}
//И с этим игрался
FJSONObject->Free();
delete FJSONObject;
delete sList;
}
« Последнее редактирование: 03 Июнь 2014, 08:33:23 от nek » Записан
nek
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 16


« Ответ #7 : 06 Июнь 2014, 21:41:00 »

Вроде пашет!
Код:
#include
#include
...
std::auto_ptr object(static_cast(TJSONObject::ParseJSONValue(Memo1->Lines->Text)));
TJSONObject* response = static_cast(object->Get("response")->JsonValue);
TJSONArray* items = static_cast(response->Get("items")->JsonValue);
TJSONObject* id = static_cast(items->Get(0));
ShowMessage(id->GetValue("id")->ToString());
Осталась форма OAuth

UPD: например её можно создать вот так:
Код:
#include
...
new Tfrm_OAuthWebForm(Form1->Owner);
Даже ->ShowModal(), но это  ведь неправильно

Ыть
Код:
Tfrm_OAuthWebForm* TOauthForm = new Tfrm_OAuthWebForm(this);
TOauthForm->ShowModal();
« Последнее редактирование: 07 Июнь 2014, 08:32:30 от nek » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  




....

Powered by SMF 1.1.21 | SMF © 2025, Simple Machines
Страница сгенерирована за 0.069 секунд. Запросов: 21.