Приложение в твоем смартфоне
Приложение в твоем смартфоне
Приложение в твоем смартфоне
Приложение в твоем смартфоне
28 июля 2011 в 21:00

Публикация на стене Вконтакте средствами php из песочницы

Получив задачу создать автоматическую публикацию материалов сайта на стене нашей страницы Вконтакте, я обнаружил, что рецептов по этой, казалось бы, актуальной теме относительно мало.

В действительности всё оказалось довольно просто, и чтение документации по API часто помогает сэкономить время.



Для того чтобы получить доступ к API контакта из php-скрипта, нужно начать с клика по кнопке “Подключить сайт” на странице для разработчиков.

На следующей форме надо выбрать опцию «Standalone-приложение» и ввести название, например, Auto app. После клика по кнопке «Подключить приложение» вам придется ввести код. Он в течение минуты придет в виде смски на мобильный, указанный в профиле пользователя, под которым вы залогинены. Отлично, теперь у вас есть standalone-приложение, информацию о котором в дальнейшем можно редактировать на страничке «Приложения», кликнув по ссылке «настройки».

На новой странице не забудьте ввести реальный адрес сайта, базовый домен и сохранить изменения; если оставить эти поля пустыми, контакт не будет публиковать ваши «автоматические» посты.


Теперь, после того, как приложение создано, мы можем получить 2 важных значения для конфигурации приложения — защищенный ключ и ID приложения, которые нам понадобятся для работы.

Создадим на своем проекте папку приложения, например, my_folder/.

Также для удобства создадим 3 файла, из которых и будет состоять наше standalone-приложение:

сonfig.php – подключаемый конфиг, в который мы положим защищенный ключ и ID приложения, а также ID пользователя, на стене которого мы будем публиковать наши посты.
connect.php — простая страничка для стандартной процедуры подключения приложения к странице пользователя.
export.php — скрипт, который непосредственно будет постить наши материалы.

Так будет выглядеть сложный код нашего конфигурационного файла:


<?php

     *  конфигурация standalone приложения Вконтакте
     *  ID приложения и ключ можно получить на странице редактирования приложения, или после добавления
     */
     
    $vkontakteApplicationId = '12345';
    $vkontakteKey ='сюда надо скопировать защищенный ключ вашего приложения';
    
    // ID юзера, к которому должно подключаться приложение
    $vkontakteUserId='12345';


Теперь нам надо подключить приложение к странице пользователя Вконтакте, используя механизм авторизации на базе протокола OAuth 2.0. Подключение происходит так:
  1. Создаем специальным образом ссылку (см. ниже) на странице connect.php нашего приложения.
  2. Открываем бразуер и логинимся Вконтакте под тем пользователем, на стене которого мы будем публиковать сообщения. Это вполне может быть тот же самый пользователь, под которым мы зарегистрировали приложение.
  3. Заходим на свою страничку connect.php и кликаем по ссылке, переходим на страницу Вконтакте.
  4. На странице Вконтакте авторизуем приложение (нажав кнопку «Разрешить»), после чего вконтакт редиректит браузер назад, на страницу connect.php, передав через url параметр code
  5. Используя параметр code, делаем запрос к контакту по протоколу https и получаем access_token – токен, который мы сохраним в текстовом файле (к примеру) и будем в дальнейшем использовать при публикации сообщений на стене. В процессе публикации для авторизации приложения при передаче данных, нам уже не понадобятся секретный ключ и id нашего приложения, и параметр code. Мы будем использовать только полученный токен.


Вот простой вариант страницы connect.php:

<?php

    require  'config.php';

    if (!empty($_GET['code'])){

        // вконтакт присылает нам код        
        $vkontakteCode=$_GET['code'];
        
        // получим токен 
        $sUrl = "https://api.vkontakte.ru/oauth/access_token?client_id=$vkontakteApplicationId&client_secret=$vkontakteKey&code=$vkontakteCode";

// создадим объект, содержащий ответ сервера Вконтакте, который приходит в формате JSON
        $oResponce = json_decode(file_get_contents($sUrl));
        
        $fp = fopen('token.txt', 'w');
        fputs($fp, $oResponce->access_token);
        fclose($fp);
        
}

?>
<a href="http://api.vkontakte.ru/oauth/authorize?client_id=<?=$vkontakteApplicationId?>&scope=offline,wall&redirect_uri=http://<?=$sYourDomain?>/my_folder/connect.php&response_type=code">Авторизация Вконтакте</a>



Для того чтобы работала конструкция json_decode(file_get_contents('https://...')), на сервере должна быть установлена версия php 5.x c поддержкой openssl.

Строка запроса ссылки «авторизация Вконтакте» собирается из следующих параметров:
client_id – ID нашего приложения Вконтакте, которое мы уже прописали в конфигурационном файле;
scope — запрашиваемые права доступа приложения, которые можно перечислять через запятую. В данном случае приложение запрашивает доступ к API со стороннего сервера в любое время (offline) и wall – доступ к методам работы со стеной;
redirect_uri – абсолютная ссылка на страницу подключения connect.php, на которую будет передан параметр code;
responce_type – code.

Теперь, после того, как access_token получен, мы можем приступить к публикации материалов на стене.


<?php

require 'config.php';
$vkontakteAccessToken = file_get_contents('token.txt');

/**
…......
ваш код, где вы получаете текст, ссылку поста или другие значения
*/

// строка запроса к серверу Вконтакте
$sRequest = "https://api.vkontakte.ru/method/wall.post?owner_id=$vkontakteUserId=&access_token=$vkontakteAccessToken&message=$text&attachment=$link";

// ответ от Вконтакте
$oResponce = json_decode(file_get_contents($sRequest));



Запускаем скрипт, и если мы нигде не ошиблись, получаем такой результат:


Подобным образом можно формировать запросы и для использования других методов API. Строка запроса собирается так:
api.vkontakte.ru/method/ + название метода + ID пользователя в контакте + полученный ранее токен + перечень параметров соответствующего метода API.

В приведенном примере обязательным параметром является message – это собственно текст, публикуемый на стене Вконтакте. Текст должен быть в кодировке UTF-8, если вы по-прежнему работаете с windows-1251, используйте такое преобразование:


$text = urlencode(iconv( 'windows-1251', 'utf-8' , $text));


Так как наш текст и ссылка являются частью строки запроса url, не забываем использовать кодирование urlencode.

Если мы хотим запостить только текст, без ссылки, то, в случае успеха сервер пришлет ответ такого вида
{«response»:{«post_id»:1}}

Для того чтобы рядом с сообщением на стене была опубликована ссылка, к строке запроса необходимо добавить attachment=$link, где $link — это абсолютная ссылка на существующую страницу вашего сайта. В таком случае запись публикуется отложено (за несколько секунд ли меньше секунды), а с сервера приходит ответ вида
{«response»:{«processing»:1}}

Подробнее о методе wall.post можно почитать на странице документации.

Не отправляйте запросы на сервер слишком часто. В большинстве случаев лимита в один запрос в минуту вполне достаточно, иначе сервер вернет вам ошибку «Captcha is needed» и публикация будет временно приостановлена.

Результат работы standalone-приложения выглядит так

Вот, все оказалось достаточно просто, ставим скрипт экспорта на крон, и контент-менеджеру не придется публиковать записи вручную!
+36
34174
317
alexj 9,5

комментарии (59)

0
Richard_Ferlow, #
Интересная информация. Скажите, а в группе можно таким образом размещать информацию на стене?
+4
ezj, #
Можно, перед ID группы подставьте "-", т.е. owner_id=-group_id
Но API вконтакта на столько убог что от имени группы опубликовать пост не удастся
+1
myagi, #
Странно, что также на стену группы нельзя опубликовать ссылку. $link просто игнорируется…
0
leshaogonkov, #
А с публичными страницами этот фокус не пройдет?
0
ezj, #
Ну а в чем разница между публичными и закрытыми страницами? Я думаю разница лишь в приватности
0
leshaogonkov, #
без понятия, если честно)
0
Methos, #
А как узнать id группы? Или нужно писать именно название?

У меня выдаёт вот такое:

[error_code] => 7
[error_msg] => Permission to perform this action is denied

Хотя при подключении указывал scope=wall
0
ezj, #
Может Firebug поможет узнать ID (ну или аналогичный инструмент)
0
deniamnet, #
Спасибо, интересно. Интересует также, можно ли размещать что-то кроме текста (изображения, например)?
+1
alexj, #
Можно. Необходимо добавить медиа-приложение в параметре attachment (см. доку по wall.post), а для этого нужно предварительно загрузить его на сервер в контакте.
+8
ezj, #
Ничего необычайного, все это написано в документации…
+1
alexj, #
Да, необычного ничего нет, но пост может быть полезен, как простой рецепт работы с api standalone приложения контакта на конкретном примере. На хабре есть и более оригинальный подход.
0
veveve, #
Поправьте меня, если ошибаюсь, но по запросу можно подключить RSS. Вконтакте сам будет публиковать записи из ленты.
0
alexj, #
На данный момент подключение RSS предоставляется не всем пользователям. Запрос необходимо отправлять на почту, если у Вас есть официальная страница.
0
veveve, #
Вообще, если по-хорошему, это правильно. К сожалению, описанный вами скрипт будет использоваться в первую очередь для спама.
0
alexj, #
Приложение не может постить записи на стену, пока это не разрешено самим пользователем.
+2
VolCh, #
Написал бы кто пост, как создавать IFrame приложения. Это ж надо додуматься — сначала создай приложение, а потом мы включим тебя в группу для разработчиков…
0
SovGVD, #
зачем писать об этом пост, если есть официальная документация в которой от и до всё расписано, iframe приложение это просто обычный сайт, которому GET запросом отправляются данные (я им не доверяю и для одного из приложений сделал авторизацию через вконтакт)
+1
VolCh, #
Интересуют не технические нюансы, а административные. Например создал я приложение — по моему мнению и по моим тестам оно должно работать, но не попробуешь — не узнаешь — может при попытке предъявить его на модерацию они устроят 100500 коннектов в секунду и отклонят за то, что выдаёт ошибку. А может я лоханусь и где-то опечатку сделаю. Не к столу могу вспомнить ВебМани — у них есть тестовый режим — ни о чём подобном от контакта не слышал и страшно подавать им приложение на модерацию потму как если вдруг не пройдёт, то второй попытки (даже другого приложения) не будет. А может будет. Вероятно эти вопросы обсуждаются в группе для разработчиков, но по-моему, пока не разработаешь приложение, которое их устроит — не узнаешь. Уж лучше бы штуку-другую баксов за участие в группе брали, чтоб узнать о нюансах до подачи заявки.
+1
SovGVD, #
может правила поменялись, но несколько месяцев назад: создал приложение, сам его потестил, отправил на модерацию, через пару дней одобрили, другое не одобрили и сказали что исправить, исправил и тоже одобрили
+ есть тестовый режим, в get запрос надо пихнуть test_mode=1 кажется
+8
seriyPS, #
Я когда с вконтактовским API работал написал консоль для работы с методами API.



Точнее изначально написал питонью библиотеку — обертку для API и уже после к ней консоль добавил для облегчения отладки. Если кому надо — смотрите на GitHub github.com/seriyps/vkontakte_api_wrapper
0
egorinsk, #
vkontakte.ru/apptest для этого же не катит?
0
seriyPS, #
о… Фиг его знает. Я раньше его не видел.
Ну и оно методы для десктоп-приложений не умеет использовать…
+3
SLY_G, #
«и чтение документации по API часто помогает сэкономить время.»
Позабавило. То есть, настоящие программисты доки по api не читают сначала, так же как настоящие хозяйственные пацаны не читают инструкции к бытовой технике.
И только когда что-то сломалось… ;)
0
Aidos, #
Альтернативный велосипед — подключить к странице твиттер аккаунт который связан с rss
0
Dexif, #
Тут есть один недостаток… ограничение по длине :) хотя первое время именно так и делал :)
0
ponomar, #
Так ведь там возможен только экспорт, а в статье рассматривается именно импорт.
0
Aidos, #
Сейчас уже работает в обе стороны, а не так как раньше
0
ponomar, #
А где настраивается?

0
taliban, #
Piccy.info - Free Image Hosting
Там и настраивается, но для начала надо подключить аккаунт твиттера.
0
ponomar, #
Вы, видимо, показываете мне окно настроек пользователя, а я о странице говорю. Для страниц эта возможность все же недоступна:

0
taliban, #
Да, я прозевал =)
0
svarda, #
Сегодня заметил новую «фишку»:

Теперь переписка может происходить как на Facebook.com:

PS. Вынес бы это в песочницу, но не позволяют завести топик.
0
VolCh, #
Хоть бы написали как. Не все на фэйсбуке переписываются…
0
svarda, #
В заголовке страницы появился индикатор количества друзей online.

Кстати, он постоянно отслеживает обновление их количества (на самой странице тоже есть такой индикатор, но он обновляется лишь при перезагрузке страницы). Нажав на него, появляется всплавающее окошечко со списком доступных друзей. Для начала переписки, достаточно два раза кликнуть по нужному контакту и переписка будет оформоена в виде обычного чата в таком же всплывающем окошечке.

На мой взгляд, очень удобно.
0
fls_welvet, #
Ещё бы добавить возможность выборки по спискам друзей, а не показывать всех скопом.
0
VolCh, #
Блин, увидел, попробовал, понравилось, но закрыл окошки тепеь не могу найти как заново эту фичу включить…
0
svarda, #
Извините, не отобразились картинки, хотя загружал через habrastorage.org/
0
Nixx, #
В результате выполнения данного запроса Ваш сервер получит вновь созданный access_token. Вместе с access_token серверу возвращается время жизни ключа expires_in в секундах. Процедуру авторизации приложения необходимо повторять в случае истечения срока действия access_token, смены пользователем своего логина или пароля или удалением приложения из настроек.

Как вы с этим боролись или же токен хранится бесконечно, как в твитере?
+1
LanG, #
scope=offline, делает бесконечным жизнь токена, до тех пор пока его заново не получат
+1
seriyPS, #
Кстати, еще буквально месяц назад scope=offline работало по другому — сбрасывало токен при любой смене IP адреса.
0
vixh, #
А в чем разница между Standalone-приложение и Веб-сайт?
+1
lelik17, #
А никак не сделать так, чтобы при публикации на стене в группе сообщение выводилось от имени группы? И ещё. Опять же при публикации в группу у меня не получилось загрузить картинку. Это лечится или такая же фигня как при попытке опубликовать ссылку?
0
netp, #
поддерживаю вопрос
0
myagi, #
задавал этот вопрос уже выше. ответа пока нет. говорят, что ссылку можно передавать не через аттачмент, а прямо в тексте.
0
serzik, #
from_group=1
0
myagi, #
Да, теперь-то уже ввели :)
0
webwin, #
уже отключили для сайтов

Permission to perform this action is denied for non-standalone applications
0
Newbilius, #
C последнего времени всё немного изменилось: теперь в connect.php для StandAlone приложений —
redirect_uri=http://api.vkontakte.ru/blank.html 
— обязательно.

После редиректа на этой странице будет написан код, который можно подставить в функцию и получить вожделенный токен.
0
freem4n, #
сдается мне, Вы не догоняете смысла

redirect_uri=http://<?=$sYourDomain?>/my_folder/connect.php&response_type=code

таким макаром connect.php получает токен.

Вы говорите про ручной способ.
0
Krokodile, #
В том то и дело, что теперь для стендэлонов — теперь обязательный редирект на бланк
0
Empirik, #
Сделал вроде все как написано. Сформировал ссылку по типу http:// api.vkontakte.ru/oauth/authorize?client_id=123456&scope=wall%2Coffline&redirect_uri=http:// api.vk.com/blank.html&response_type=code

перешел по ней и получил код.

При помощи него сформировал запрос и curl-ом пытаюсь получить ответ на него https:// api.vkontakte.ru/oauth/access_token?client_id=123456&client_secret=blablabla&code=123456

Вконтакте мне выдает ответ типа Code is invalid or expired. Так вот вот вопрос, обязательно ли, что бы запрос на получения токена был с того-же ip, что и запрос на получения кода?
0
Empirik, #
Проверил, действительно ip должны совпадать. Теперь вопрос с хабражителям, есть у кого-то полнофукциональный прокси сервер написанный на php?
0
seriyPS, #
Http proxy на php-cgi???????

Или в виде демона?
Почему прям на PHP то?
0
Empirik, #
На хостинге которым я пользуюсь нет модуля mod_proxy для Apache. Так, что хотелось бы найти php прокси сервер, который можно было бы поднять демоном.
0
seriyPS, #
чтобы не было необходимости в совпадении IP убедитесь что ваше приложение не Deaktop приложение и, кажется, scope=offline тоже на это влияет
0
Empirik, #
Это да, но вот либо я не понял, либо метод wall.post доступен только дескстоп приложениям, и кроме того мне нужна возможность публиковать что-то на стену не в зависимости от того, залогонен пользователь в контакте или нет.
0
Newbilius, #
Так же дополнительная проблема: теперь ввод капчи требуется при каждом посте на страницу. Обидно, но факт.
0
Newbilius, #
Поправка. Оказывается, при _почти_ каждом. Ну ладно, не так страшно…

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