Нещодавно розробники соціальної мережі ВКонтакте повідомити про запуск можливості використання VK API для standalone-додатків. Я ж вирішив експериментально перевірити цю нову можливість у зв'язці з мовою Ruby.
Використані джерела:
Авторизація Desktop-додатків
Desktop-додатки на відміну від звичайних програм ВКонтакте запускаються у вигляді звичайних програм на пристрої користувача, яким може бути комп'ютер, комунікатор або смартфон. Наприклад, це може бути додаток на платформі Adobe AIR або додаток для iPhone, написане на Objective-C.
Почав писати обгортку до цього на Ruby. І відразу ж засмутився - авторизація на даний момент через одне місце. Потрібен компонент браузера з підтримкою JavaScript. Насправді я уявлення не маю як таке реалізувати на Ruby. Доведеться вручну вивчати що і куди посилати. Але чому б не зробити метод у який висилається логін-пароль? І просто отримувати ID сесії.
Маємо те, що маємо. Обійдемося поки цим. А в майбутньому, надіюся виправлять.
Для початку необхідно створити новий або взяти вже існуючий додаток.
Нам знадобиться ID додатку.
Вхід і отримання сесії
Для отримання сесії необхідно усередині додатку створити елемент управління, який буде містити усередині себе браузер(наприклад UIWebView при створенні iPhone додатки). Після цього для входу необхідно буде направити браузер в створеному елементі керування на наступний URL
http://vkontakte.ru/login.php
і передати описані нижче параметри в POST або GET запиті:
Назва параметру | Обов'язковий | Опис |
---|---|---|
app | ✔ | ID додатку |
layout | ✔ | Вказує тип дизайну сторінки авторизації. На даний момент підтримуються наступні типи:
|
type | ✔ | Вказує яким чином передається значення сесії. На даний момент підтримуються наступні типи:
|
success_url | Сторінка, на яку буде перенаправлено браузер в разі успішної авторизації. У рядку запиту даної сторінки буде передано інформацію про сесію. Коли цей параметр не заданий, то за замовчуванням перенаправлення відбувається на сторінку http://vkontakte.ru/api/login_success.html | |
fail_url | Сторінка, на яку буде перенаправлено браузер в разі скасування авторизації користувачем. Коли цей параметр не заданий, то за замовчуванням перенаправлення відбувається на сторінку http://vkontakte.ru/api/login_failure.html | |
settings | Бітова маска настройок доступу програми, які необхідно перевірити при авторизації користувача і запитати, у разі відсутності необхідних. |
Наш додаток ми будемо писати на чистому Ruby. А в якості броузера у нас буде бібліотека Mechanize, у якій відсутня підтримка JavaScript. Забігаючи на перед скажу, що це викликає деякі незручності.
require 'mechanize'
API_ID = '1861808'
agent = Mechanize.new{|a|
a.user_agent_alias = 'Linux Konqueror'
}
login_url = "http://vk.com/login.php?app=#{API_ID}&layout=popup&type=browser&settings=130"
login_page = agent.get(login_url)
Далі по сценарію ми повинні потрапити на сторінку авторизації користувача, де потрібно ввести логін і пароль.Виконаємо цю пересічну дію силами Mechanize.
email = 'user@example.com'
pass = 'xxx'
login_form = login_page.form_with(:name => 'real_login')
login_form.email = email
login_form.pass = pass
verify_page = login_form.submit
Тут починається найцікавіше. У разі успішної авторизації користувач опиниться на сторінці http://login.vk.com.<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=windows-1251' />
</head>
<body onload="document.getElementById('l').submit();">
<form id='l' method='post' action='http://vk.com/login.php'>
<input type='hidden' name='s' id='s' value='5656ecbc545b7fcb9fcce1bfde0ad20d368dda058a5908925141c94d' />
<input type="hidden" name="act" id="act" value="auth_result" />
<input type="hidden" name="m" id="m" value="4" />
<input type="hidden" name="permanent" id="permanent" value="1" />
<input type="hidden" name="app" id="app" value="1861808" />
<input type="hidden" name="app_hash" id="app_hash" value="2f90dbb41067e7b22d" />
</form>
</body>
</html>
Якби це був броузер з підтримкою JavaScript, то при успішнії авторизації вбудований в додатку браузер буде перенаправлено на наступну URL-адресу:
http://vkontakte.ru/login_success.html#session=(...)
де в session записані параметри сесії в форматі JSON.В нашому випадку, доведеться виконувати ці дії власноруч.
params_page = verify_page.forms.first.submit
Опиняємося на сторінці http://vk.com/login.php, у джерелі якої містяться необхідні параметри сесії в форматі JSON:
<script type="text/javascript">parent.onDone({"mid":12227146,"sid":"09f3c88847be319f9e5a44710d1549c166f3848e557f1780623bc222","secret":"893daf7ef4","expire":0})</script>
Нижче описано значення кожного з параметрів сесії:
Параметр | Значення |
---|---|
expire | час закінчення сесії у форматі UNIX |
mid | ID користувача ВКонтакте |
secret | спеціально згенерований секрет сесії |
sid | ідентифікатор сесії |
Ми успішно авторизувалися і отримати сесію. Зберігаємо її параметри для подальшого використання.
require 'json'
@session_params = JSON::parse(/\((.*)\)/.match(params_page.body)[1])
Взаємодія з API
Після отримання сесії взаємодія з ВКонтакте API проводиться шляхом створення HTTP-запиту (POST або GET) до адреси API-сервісу http://api.vkontakte.ru/api.php.
Які параметри необхідно передавати при запиті?
Назва параметру | Обов'язковий параметр | Опис |
---|---|---|
api_id | ✔ | ідентифікатор програми, присвоюється при створенні. |
method | ✔ | назва методу API із загального списку функцій. |
sig | ✔ | підпис, який створюється з метою безпеки. Порядок створення підпису описаний нижче. |
v | ✔ | версія API, в даному випадку необхідно використовувати 3.0. |
format | формат відповіді - XML або JSON. За замовчуванням XML. | |
sid | ✔ | дентифікатор сесії, отриманий раніше при авторизації |
Як створювати підпис запиту?
Параметр sig дорівнює md5 від конкатенації наступних рядків:
- mid - id поточного користувача, отриманий раніше при авторизації
- пар "parameter_name = parameter_value", розташованих у порядку зростання імені параметра (за алфавітом) за винятком параметра sid
- секрету сесії secret, який був отриманий раніше при авторизації
Напишемо функцію, яка на вході буде приймати назва методу API із загального списку функцій та його параметри як об’єкт Hash.
require 'digest/md5'
def make_sig(method_name, method_params)
sig = @session_params['mid'].to_s
params = {'api_id' => API_ID, 'format' => 'JSON', 'v' => '3.0', 'method' => method_name}
params.merge!(method_params)
sig = params.sort.inject(sig) {|s, e| s += "#{e[0]}=#{e[1]}"}
sig = sig + @session_params['secret']
sig = Digest::MD5.hexdigest(sig)
return sig
end
Приклад запиту:
method_name = 'getProfiles'
method_params = {'uids' => '15297587', 'fields' => 'photo,sex'}
sig = make_sig(method_name, method_params)
method_params_to_url = method_params.inject(""){|s, e| s += "&#{e[0]}=#{e[1]}"}
res_url = "http://api.vk.com/api.php?api_id=#{API_ID}&method=#{method_name}#{method_params_to_url}&sig=#{sig}&v=3.0&format=JSON&sid=#{@session_params['sid']}"
res_page = agent.get(res_url)
puts JSON::parse(res_page.body)
У даному випадку API отримує запит getProfiles з параметрами:
- uids=15297587
- fields=photo,sex
5 коментарів:
Хороша стаття!
Буде вільний час - обов'язково попробую.
І коли вже Mechanize буде підтримувати JavaScript...?
мабуть ніколи :(
Кому до снаги писати самотужки процесор JavaScript?
http://watir.com/
После прочтения твоего поста, решаил тоже поразбираться с апями контакта и вариант запросов немного другой, не обязательно вызывать рендеринг обычной страницы через нокогири, можно все сделать json запросом.
2 Волошин Руслан
зараз так і роблю.
Авторизація з використанням Mechanize, а взаємодія з API через httparty.
http://github.com/mamantoha/vkontakte/blob/master/lib/vkontakte.rb
Дописати коментар