vkontakte_api - ruby-адаптер для ВКонтакте API. Он позволяет вызывать методы API, загружать файлы на сервера ВКонтакте, а также поддерживает все 3 доступных способа авторизации (при этом позволяя использовать стороннее решение).
# Gemfile
gem 'vkontakte_api', '~> 1.0'или просто
$ gem install vkontakte_api# создаем клиент
@vk = VkontakteApi::Client.new
# и вызываем методы API
@vk.users.get(uid: 1)
# в ruby принято использовать snake_case в названиях методов,
# поэтому likes.getList становится likes.get_list
@vk.likes.get_list
# также названия методов, которые возвращают '1' или '0',
# заканчиваются на '?', а возвращаемые значения приводятся
# к true или false
@vk.is_app_user? # => false
# если ВКонтакте ожидает получить параметр в виде списка,
# разделенного запятыми, то его можно передать массивом
users = @vk.users.get(uids: [1, 2, 3])
# большинство методов возвращает структуры Hashie::Mash
# и массивы из них
users.first.uid # => 1
users.first.first_name # => "Павел"
users.first.last_name # => "Дуров"
# если метод, возвращающий массив, вызывается с блоком,
# то блок будет выполнен для каждого элемента,
# и метод вернет обработанный массив
fields = [:first_name, :last_name, :screen_name]
@vk.friends.get(fields: fields) do |friend|
"#{friend.first_name} '#{friend.screen_name}' #{friend.last_name}"
end
# => ["Павел 'durov' Дуров"]Загрузка файлов на сервера ВКонтакте осуществляется в несколько этапов: сначала вызывается метод API, возвращающий URL для загрузки, затем происходит сама загрузка файлов, и после этого в некоторых случаях нужно вызвать другой метод API, передав в параметрах данные, возвращенные сервером после предыдущего запроса. Вызываемые методы API зависят от типа загружаемых файлов и описаны в соответствующем разделе документации.
Файлы передаются в формате хэша, где ключом является название параметра в запросе (указано в документации, например для загрузки фото на стену это будет photo), а значением - массив из 2 строк: полный путь к файлу и его MIME-тип:
url = 'http://cs303110.vkontakte.ru/upload.php?act=do_add'
VkontakteApi.upload(url: url, photo: ['/path/to/file.jpg', 'image/jpeg'])Метод вернет ответ сервера ВКонтакте, преобразованный в Hashie::Mash; его можно использовать при вызове метода API на последнем этапе процесса загрузки.
Для вызова большинства методов требуется токен доступа (access token). Чтобы получить его, можно использовать авторизацию, встроенную в vkontakte_api, либо положиться на какой-то другой механизм (например, OmniAuth). В последнем случае в результате авторизации будет получен токен, который нужно будет передать в VkontakteApi::Client.new.
Для работы с ВКонтакте API предусмотрено 3 типа авторизации: для сайтов, для клиентских приложений (мобильных либо десктопных, имеющих доступ к управлению браузером) и специальный тип авторизации серверов приложений для вызова административных методов без авторизации самого пользователя. Более подробно они описаны тут; рассмотрим, как работать с ними средствами vkontakte_api.
Для авторизации необходимо задать параметры app_id (ID приложения), app_secret (защищенный ключ) и redirect_uri (адрес, куда пользователь будет направлен после предоставления прав приложению) в настройках VkontakteApi.configure. Более подробно о конфигурировании vkontakte_api см. далее в соответствующем разделе.
Авторизация сайтов проходит в 2 шага. Сначала пользователь перенаправляется на страницу ВКонтакте для подтверждения запрошенных у него прав сайта на доступ к его данным. Со списком возможных прав можно ознакомиться здесь. Допустим, нужно получить доступ к друзьям (friends) и фотографиям (photos) пользователя.
В соответствии с рекомендациями в протоколе OAuth2 для защиты от CSRF, нужно передать параметр state, содержащий случайное значение. На данный момент по непонятным причинам ВКонтакте игнорирует этот параметр, если в scope не указан notify.
session[:state] = Digest::MD5.hexdigest(rand.to_s)
redirect_to VkontakteApi.authorization_url(scope: [:notify, :friends, :photos], state: session[:state])После подтверждения пользователь перенаправляется на указанный в настройках redirect_uri, причем в параметрах будет передан код, по которому можно получить токен доступа, а также переданный ранее state. Если state не совпадает с тем, который был использован при отправлении пользователя на ВКонтакте, то скорее всего это попытка CSRF-атаки - стоит отправить пользователя на повторную авторизацию.
redirect_to login_url, alert: 'Ошибка авторизации' if params[:state] != session[:state]vkontakte_api предоставляет метод VkontakteApi.authorize, который делает запрос к ВКонтакте, получает токен и создает клиент; нужно лишь передать ему код:
@vk = VkontakteApi.authorize(code: params[:code])
# и теперь можно вызывать методы API на объекте @vk
@vk.is_app_user?Клиент будет содержать id пользователя, авторизовавшего приложение; его можно получить с помощью метода VkontakteApi::Client#user_id:
@vk.user_id # => 123456Также в этот момент полезно сохранить полученный токен (и, при необходимости, id пользователя) в БД либо в сессии, чтобы использовать их повторно:
current_user.token = @vk.token
current_user.vk_id = @vk.user_id
current_user.save
# позже
@vk = VkontakteApi::Client.new(current_user.token)Авторизация клиентского приложения несколько проще - не нужно получать токен отдельным запросом, он выдается сразу после редиректа пользователя.
# пользователь направляется на следующий урл
VkontakteApi.authorization_url(type: :client, scope: [:friends, :photos])Необходимо принимать во внимание, что redirect_uri нужно выставлять на http://api.vkontakte.ru/blank.html, иначе не получится вызывать методы, доступные клиентским приложениям.
Когда пользователь подтвердит права приложения, он будет перенаправлен на redirect_uri, при этом в параметре access_token будет токен, который нужно передать в VkontakteApi::Client.new.
Последний тип авторизации - самый простой, т.к. не предполагает участия пользователя.
@vk = VkontakteApi.authorize(type: :app_server)Если ВКонтакте API возвращает ошибку, выбрасывается исключение класса VkontakteApi::Error.
vk = VK::Client.new
vk.friends.get(uid: 1, fields: [:first_name, :last_name, :photo])
# VkontakteApi::Error: VKontakte returned an error 7: 'Permission to perform this action is denied' after calling method 'friends.get' with parameters {"uid"=>"1", "fields"=>"first_name,last_name,photo"}.vkontakte_api логгирует служебную информацию о запросах при вызове методов. По умолчанию все пишется в STDOUT, но в настройке можно указать любой другой совместимый логгер, например Rails.logger.
Есть возможность логгирования 3 типов информации, каждому соответствует ключ в глобальных настройках.
| ключ настройки | по умолчанию | уровень логгирования | |
|---|---|---|---|
| URL запроса | log_requests |
true |
debug |
| JSON ответа при ошибке | log_errors |
true |
warn |
| JSON удачного ответа | log_responses |
false |
debug |
Таким образом, в rails-приложении с настройками по умолчанию в production записываются только ответы сервера при ошибках; в development также логгируются URL-ы запросов.
Здесь можно посмотреть пример использования vkontakte_api в rails-приложении (используются только читающие методы *.get - приложение ничего не пишет на ВКонтакте, только читает). Исходный код можно посмотреть тут.
Глобальные параметры vkontakte_api задаются в блоке VkontakteApi.configure следующим образом:
VkontakteApi.configure do |config|
# параметры, необходимые для авторизации средствами vkontakte_api
# (не нужны при использовании сторонней авторизации)
config.app_id = '123'
config.app_secret = 'AbCdE654'
config.redirect_uri = 'http://example.com/oauth/callback'
# faraday-адаптер для сетевых запросов
config.adapter = :net_http
# HTTP-метод для вызова методов API (:get или :post)
config.http_verb = :get
# параметры для faraday-соединения
config.faraday_options = {
ssl: {
ca_path: '/usr/lib/ssl/certs'
},
proxy: {
uri: 'http://proxy.example.com',
user: 'foo',
password: 'bar'
}
}
# логгер
config.logger = Rails.logger
config.log_requests = true # URL-ы запросов
config.log_errors = true # ошибки
config.log_responses = false # удачные ответы
end
# создание короткого алиаса VK для модуля VkontakteApi
VkontakteApi.register_aliasПо умолчанию для HTTP-запросов используется Net::HTTP; можно выбрать любой другой адаптер, поддерживаемый faraday.
ВКонтакте позволяет использовать как GET-, так и POST-запросы при вызове методов API. По умолчанию vkontakte_api использует GET, но в настройке http_verb можно указать :post, чтобы совершать POST-запросы.
При необходимости можно указать параметры для faraday-соединения - например, параметры прокси-сервера или путь к SSL-сертификатам.
Чтобы сгенерировать файл с настройками по умолчанию в rails-приложении, можно воспользоваться генератором vkontakte_api:install:
$ cd /path/to/app
$ rails generate vkontakte_api:installvkontakte_api использует парсер Oj - это единственный парсер, который не показал ошибок при парсинге JSON, генерируемого ВКонтакте.
Также в библиотеке multi_json (обертка для различных JSON-парсеров, которая выбирает самый быстрый из установленных в системе и парсит им) Oj поддерживается и имеет наивысший приоритет; поэтому если он установлен в системе, multi_json будет использовать именно его.
- метод, возвращающий права текущего токена в читабельной форме (используя
getUserSettingsи кэшируя результат) - сохранение параметра
expires_inтокена в объектеVkontakteApi::Clientпосле авторизации черезVkontakteApi.authorize POST-запросы по умолчанию- логгирование тела
POST-запроса
Если вы хотите поучаствовать в разработке проекта, форкните репозиторий, положите свои изменения в отдельную ветку, покройте их спеками и отправьте мне pull request.
vkontakte_api тестируется под MRI 1.8.7, 1.9.2 и 1.9.3. Если в одной из этих сред что-то работает неправильно, либо вообще не работает, то это следует считать багом, и написать об этом в issues на Github.


