Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > VitaliyKrivtsov

Рейтинг: 3.67. Голосов: 3.

VkontakteAPI. Разбор полётов.

Запись от VitaliyKrivtsov размещена 18.05.2011 в 23:48
Обновил(-а) VitaliyKrivtsov 25.06.2011 в 22:27

Эта статья будет интересна тем, кому хотелось бы знать, как работать с ВконтактеAPI, так сказать, на "низком уровне", без посредника:
- APIConnection для взаимодействия с API без контейнера;
- Wrapper для взаимодействия с API с использованием контейнера;
Рассматривается отправка запроса для получения от Вконтакте данных, касающейся пользователя приложения.
Разобравшись с тем, как работать с ВконтактеAPI можно написать собственную библиотеку, так как APIConnection предоставляет из себя инструмент для отправки запросов и кое-какой обработки ответа, а этого мало. Для взаимодействия с JavaScript API без APIConnection и Wrapper не обойтись. По этому написать приложение не прибегая к использованию посредника, не получится, но нам и не нужно - главное понять, как осуществлять запросы к API.
Скорей всего, старожилам, которые грызут API Вконтакте уже не первый месяц, статья не понадобится, то бишь статься ориентирована на новичков.
В посте рассматривается взаимодействие по таким схемам:
- API2.0 (в данный момент не актуально, но знать особенности - полезно);
- API3.0;
- OAuth2.0(к сегодняшнему дню статус - beta, но тем не менее - работает отлично);

Начнем
Очень недавно Вконтакте (где-то полтора месяца назад) переделали раздел "Мои приложения", в частности и интерфейс админки приложения. Как оказалось - не без последствий для разработчиков. Убрали secret, который можно было применять для подписывания сигнатуры по старой схеме взаимодействия - API 2.0. Неприятное, то что убрать то убрали, но не написали в документации, что искать secret в настройках приложения не стоит, так как его там уже давно нет. И так, этот secret нужен был для подписи сигнатуры по API 2.0, но не для API 3.0. После небольших изменений в схеме взаимодействия API 2.0 - разработчики ВконтактеAPI решили обозвать его API 3.0.

Взаимодействие приложения с API по схеме API 3.0
Что нового появилось в API 3.0:
1. secret, который мы получаем flashVars использовать можно исключительно по схеме - API 3.0;
2. sid - идентификатор сессии. Получить можно только из flashVars. Передается посредством POST/GET запроса серверу как переменная с остальными параметрами конкретного метода API (если таковые есть);
3. v=3.0 - версия используемого API.

Что бы осуществить запрос по схеме API 3.0 нужно обязательно передавать sid. В формировании сигнатуры - sid не нужно использовать. Рассмотрим формирование запроса и в частности сигнатуры на примере метода getProfiles. Укажем параметры, которые нас интересуют - nickname, sex, bdate. В результате успешного запроса, сервер возвращает uid, first_name, last_name - всегда, даже если не указали явно и nickname, sex, bdate при условии, что эти поля у пользователя заполнены.
Обязательными параметрами запроса есть id приложения, method, sid согласно документации. Но здесь упущен один важный параметр. Согласно доков параметр v не есть обязательным и по умолчанию равен 3.0. Если упустить этот параметр - получаем в ответ ошибку:
Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<error>Incorrect signature: server authorization</error>
Для формирования сигнатуры нужно все параметры расставить по алфавиту, по этому все параметры добавляем в массив и методом Array#sort сортируем содержимое массива. По умолчанию, метод сортирует элементы в восходящем порядке (a предшествует b). То, что нам нужно.
Код AS3:
var arr:Array = [];
arr.push( "api_id="+api_id );
arr.push( "format=XML" );
arr.push( "v=3.0" );
arr.push( "method=getProfiles" );
arr.push( "uids="+viewer_id );
arr.push( "fields=nickname,bdate,sex" );
arr.sort( );
sid не участвует в формировании сигнатуры, по этому добавим его в после sig.
Параметр sig равен md5 от контактенации:
- viewer_id;
- параметры запроса;
- secret;
То есть:
Код AS3:
var sig:String = MD5.hash( viewer_id + arr.join("") + secret );
Добавляем sig и sid в параметры запроса:
Код AS3:
var arr:Array = [];
arr.push( "api_id="+api_id );
arr.push( "format=XML" );
arr.push( "v=3.0" );
arr.push( "method=getProfiles" );
arr.push( "uids="+viewer_id );
arr.push( "fields=nickname,bdate,sex" );
// -- //			
arr.sort( );			
// -- //
var sig:String = MD5.hash( viewer_id + arr.join("") + secret );			
arr.push( "sig=" + sig );
arr.push( "sid=" + sid );
И завершающий этап - создаем экземпляры классов: URLLoader, URLRequest, URLVariables и отправляем запрос серверу:
Код AS3:
var req:String = arr.join( "&" );			
// -- //
var urlLoader:URLLoader = new URLLoader( );					
var urlRequest:URLRequest = new URLRequest( );
urlRequest.url = "http://api.vkontakte.ru/api.php";
var urlVariables:URLVariables = new URLVariables( req );
urlRequest.method = "POST";
urlRequest.data = urlVariables;
urlLoader.load( urlRequest );
urlLoader.addEventListener( Event.COMPLETE, completeHandler );
Полная картина происходящего:
Код AS3:
package example 
{
	import by.blooddy.crypto.MD5;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
 
	/**
	 * ...
	 * @author Vitalik Krivtsov aka Nickel
	 */
	public class Example extends Sprite 
	{
		/**
		 * @private
		 * id приложения.
		 */
		private var api_id:String = "2192563";
 
		/**
		 * @private
		 * id пользователя.
		 */
		private var viewer_id:String = "41138144";
 
		/**
		 * @private
		 * идентификатор сессии.
		 */
		private var sid:String = "0eb7159b2e2273f75df88caa440eda4cfc9b1cafa39aa27c4dc83173eb889d";
 
		/**
		 * @private
		 * секрет приложения. 
		 */
		private var secret:String = "0a8d203358";
 
		public function Example() 
		{
			var arr:Array = [];
			arr.push( "api_id="+api_id );
			arr.push( "format=XML" );
			arr.push( "v=3.0" );
			arr.push( "method=getProfiles" );
			arr.push( "uids="+viewer_id );
			arr.push( "fields=nickname,bdate,sex" );
			// -- //			
			arr.sort( );
		        // -- //
			var sig:String = MD5.hash( viewer_id + arr.join("") + secret );			
			arr.push( "sig=" + sig );
			arr.push( "sid=" + sid );			
			var req:String = arr.join( "&" );			
			// -- //
			var urlLoader:URLLoader = new URLLoader( );					
			var urlRequest:URLRequest = new URLRequest( "http://api.vkontakte.ru/api.php" );
			var urlVariables:URLVariables = new URLVariables( req );
			urlRequest.method = "POST";
			urlRequest.data = urlVariables;
			urlLoader.load( urlRequest );
			urlLoader.addEventListener( Event.COMPLETE, completeHandler );			
		}
 
		private function completeHandler( event:Event ):void 
		{
			trace( event.target.data );
		}		
	}
}
Получаем строку в формате XML. Я явно указал в каком формате сервер должен прислать мне ответ, но можно и не указывать - XML установлено по умолчанию. Сюрпризов, как в случаи с параметром v, не будет.
Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<response list="true">
 <user>
  <uid>41138144</uid>
  <first_name>Виталий</first_name>
  <last_name>Кривцов</last_name>
  <nickname>Nickel</nickname>
  <bdate>21.5.1992</bdate>
  <sex>2</sex>
 </user>
</response>
При использовании API 3.0 возможно тестировать приложение локально без постоянного выдергивания secret'a и sid из страницы приложения после каждого выхода из Вконтакте. Для этого нужно передать параметр test_mode равный 1.
Все пройдет успешно. Если не задать параметр или передать test_mode равным 0, то получим следующую ошибку:
Код AS3:
 
<?xml version="1.0" encoding="utf-8"?>
<error>
 <error_code>2</error_code>
 <error_msg>Application is disabled. Enable your application or use test mode</error_msg>
 <request_params list="true">
  <param>
   <key>sid</key>
   <value>ecf4bb724f628819831bfb14f7fc7cd790e1218dd5212f4fb6c59a4aa3f815</value>
  </param>
  <param>
   <key>format</key>
   <value>XML</value>
  </param>
  <param>
   <key>sig</key>
   <value>ffc077d5ae4336618a07424b162cb2c7</value>
  </param>
  <param>
   <key>uids</key>
   <value>41138144</value>
  </param>
  <param>
   <key>method</key>
   <value>getProfiles</value>
  </param>
  <param>
   <key>fields</key>
   <value>nickname,bdate,sex</value>
  </param>
  <param>
   <key>api_id</key>
   <value>2192563</value>
  </param>
  <param>
   <key>v</key>
   <value>3.0</value>
  </param>
 </request_params>
</error>
Перед тестированием приложения локально нужно в настройках приложение поставить в режим "Приложение отключено." Если этого не сделать, получаем:
Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<error>
 <error_code>11</error_code>
 <error_msg>In test mode application should be disabled or user should be authorized</error_msg>
 <request_params list="true">
  <param>
   <key>sid</key>
   <value>ecf4bb724f628819831bfb14f7fc7cd790e1218dd5212f4fb6c59a4aa3f815</value>
  </param>
  <param>
   <key>test_mode</key>
   <value>1</value>
  </param>
  <param>
   <key>uids</key>
   <value>41138144</value>
  </param>
  <param>
   <key>format</key>
   <value>XML</value>
  </param>
  <param>
   <key>sig</key>
   <value>883d675957759cc2cd42b7d814bd3ef7</value>
  </param>
  <param>
   <key>method</key>
   <value>getProfiles</value>
  </param>
  <param>
   <key>fields</key>
   <value>nickname,bdate,sex</value>
  </param>
  <param>
   <key>api_id</key>
   <value>2192563</value>
  </param>
  <param>
   <key>v</key>
   <value>3.0</value>
  </param>
 </request_params>
</error>
В документации по API 3.0 про этот параметр ничего не написали (есть в документации по API 2.0), но он есть и такая схема работает. Да и про то, что приложение нужно отключать тоже ни кто не писал.
Добавлять в массив с параметрами нужно до сортировки элементов, то есть этот параметр участвует в формировании сигнатуры. И так, мы очень подробно разобрали формирование запроса по схеме API 3.0.
Теперь можно приступить к API 2.0.

Взаимодействие приложения с API по схеме API 2.0
Собственно разжёвывать тут ничего не нужно, все происходит точно так же как и в API 3.0. Но все же сделаю акцент на следующих моментах. Для формирования сигнатуры нужен ключ со страницы редактирования приложения - но его убрали по этому воспользоватся этой схемой не получится и не стоит читать документацию по API 2.0, лучше взяться за API 3.0. Приведу код, да бы пролить свет на их различия, а их немного:
Код AS3:
package example 
{
	import by.blooddy.crypto.MD5;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
 
	/**
	 * ...
	 * @author Vitalik Krivtsov aka Nickel
	 */
	public class Example extends Sprite 
	{
		/**
		 * @private
		 * id приложения.
		 */		
		private var api_id:String = "2192563";
 
		/**
		 * @private
		 * id пользователя.
		 */
		private var viewer_id:String = "41138144";		
 
		/**
		 * @private
		 * секрет приложения. 
		 */
		private var secret:String = "e5c2568b77";	
 
		public function Example() 
		{
			var arr:Array = [];
			arr.push( "api_id="+api_id );
			arr.push( "format=XML" );			
			arr.push( "v=2.0" );
			arr.push( "method=getProfiles" );
			arr.push( "uids="+viewer_id );
			arr.push( "fields=nickname,bdate,sex" );			
			// -- //			
			arr.sort( );			
		        // -- //
			var sig:String = MD5.hash( viewer_id + arr.join("") + secret );			
			arr.push( "sig=" + sig );			
 
			var req:String = arr.join( "&" );	
			var urlVariables:URLVariables = new URLVariables( req );
			// -- //							
			var urlRequest:URLRequest = new URLRequest( );
			urlRequest.url = "http://api.vkontakte.ru/api.php";			
			urlRequest.method = "POST";
			urlRequest.data = urlVariables;
 
			var urlLoader:URLLoader = new URLLoader( );	
			urlLoader.load( urlRequest );
			urlLoader.addEventListener( Event.COMPLETE, completeHandler );			
		}
 
		private function completeHandler( event:Event ):void 
		{
			trace( event.target.data );
		}		
	}
}
Здесь видим, что sid не передается серверу и версия API равна 2.0 и кидать в параметры не стоит. Параметр test_mode работает, как и в API 3.0. После рассмотрения API 2.0 и API 3.0 можно приступить к OAuth 2.0.

Взаимодействие приложения с API по схеме OAuth 2.0
При использовании этой схеме геморроя гораздо меньше, а значит сделать ошибку в запросе становится в разы тяжелее.
Согласно документации наш запрос представляет из себя следующее:
Код AS3:
var urL:String = "https://api.vkontakte.ru/method/getProfiles?uids=41138144&fields=nickname,bdate,sex&access_token=1bdf17ea54578cce19f114e1b1198dd4b9e19ad19ac8ef5898c0bc2f31db472";
В запрос передаем параметры метода и token. Параметр token получаем из flashVars. Все это отправляется по адресу - https://api.vkontakte.ru/method/getProfiles. Адрес содержит имя используемого метода API. В ответ получим строку в формате JSON:
Код AS3:
{"response":[
                {"uid":41138144,
                 "first_name":"Виталий",
                 "last_name":"Кривцов",
                 "nickname":"Nickel",
                 "bdate":"21.5.1992",
                 "sex":"2"}
                 ]}
С использованием OAuth трудностей не должно возникнуть - все слишком просто. Приведу работающий код, да бы посмотреть на простоту и в тот же момент красоту взаимодействия:
Код AS3:
package example 
{
	import by.blooddy.crypto.MD5;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
 
	/**
	 * ...
	 * @author Vitalik Krivtsov aka Nickel
	 */
	public class Example extends Sprite
	{	
 
		public function Example() 
		{
                        if (stage) 
                             init();
			else
                             addEventListener( Event.ADDED_TO_STAGE, init );			
		}
 
                private function init( event:Event = null ):void 
                {
                        var flashVars:Object  = stage.loaderInfo.parameters as Object;
 
			var urlVariables:URLVariables = new URLVariables();
			urlVariables.access_token = flashVars.access_token;
			urlVariables.fields = "nickname, bdate, sex";
			urlVariables.uids = flashVars.viewer_id;
 
			var urlRequest:URLRequest = new URLRequest( );
			urlRequest.url = "https://api.vkontakte.ru/method/getProfiles";				
			urlRequest.method = "POST";
			urlRequest.data = urlVariables;
 
			var urlLoader:URLLoader = new URLLoader( );	
			urlLoader.load( urlRequest );
			urlLoader.addEventListener( Event.COMPLETE, completeHandler );		
 
                }
 
		private function completeHandler( event:Event ):void 
		{
			trace( event.target.data );
		}		
	}
}
"Магия" с test_mode не работает. По этому для локального тестирования удобнее пользоваться API 3.0, но выбор всегда за Вами.

Собственно, рассмотрены всевозможные варианты взаимодействия с сервером ВКонтакте. Теперь на пути к написанию приложения одним вопросом стало меньше.
Всего комментариев 5

Комментарии

Старый 26.05.2011 21:43 GBee вне форума
GBee
 
Аватар для GBee
Ой как в тему. Спасибо.
Старый 26.05.2011 22:24 GBee вне форума
GBee
 
Аватар для GBee
Если приложение отключено, то test_mode необходим в 3 версии
Старый 26.05.2011 23:12 VitaliyKrivtsov вне форума
VitaliyKrivtsov
 
Аватар для VitaliyKrivtsov
Цитата:
Если приложение отключено, то test_mode необходим в 3 версии
Если это вопрос, то ответ - да.
Если приложение выключено и передан параметр test_mode со значением 1 - сервер вернет ошибку:
Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<error>
 <error_code>2</error_code>
 <error_msg>Application is disabled. Enable your application or use test mode</error_msg>
 <request_params list="true">
  <param>
   <key>api_id</key>
   <value>2192563</value>
  </param>
  <param>
   <key>fields</key>
   <value>nickname,bdate,sex</value>
  </param>
  <param>
   <key>format</key>
   <value>XML</value>
  </param>
  <param>
   <key>method</key>
   <value>getProfiles</value>
  </param>
  <param>
   <key>sid</key>
   <value>b8c259a95b4a34fcdd04e2a9880d2a7fd56dc819b49f8f779c5471b0d8547d</value>
  </param>
  <param>
   <key>sig</key>
   <value>9f7584c1f6d442e911738d85fcbf459f</value>
  </param>
  <param>
   <key>uids</key>
   <value>41138144</value>
  </param>
  <param>
   <key>v</key>
   <value>3.0</value>
  </param>
 </request_params>
</error>
В том случае, когда были использованы sid и secret прошлой сессии.
Если приложение включено, secret и sid свежие и при этом передали в переменных запроса test_mode - параметр проигнорируется.
Обновил(-а) VitaliyKrivtsov 26.05.2011 в 23:22
Старый 27.05.2011 08:41 GBee вне форума
GBee
 
Аватар для GBee
Цитата:
Цитата:
Если приложение отключено, то test_mode необходим в 3 версии
Если это вопрос, то ответ - да.
Если приложение выключено и передан параметр test_mode со значением 1 - сервер вернет ошибку

Еще больше запутали :о)
У меня sid и secret скопированы и кода страницы, приложение отключено, без тестмоде=1 не работает.
Старый 27.05.2011 15:53 VitaliyKrivtsov вне форума
VitaliyKrivtsov
 
Аватар для VitaliyKrivtsov
Цитата:
У меня sid и secret скопированы и кода страницы, приложение отключено, без тестмоде=1 не работает.
Все верно.
Передавайте test_mode=1, когда приложение отключено.

В предыдущем посту опечатался, правильно было бы так:
--Если приложение выключено и передан параметр test_mode со значением 0 - сервер вернет ошибку.
Хотя если test_mode=0, то это тоже самое, что совсем этот параметр не передавать.
 

 


Часовой пояс GMT +4, время: 16:21.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.