19 февраля 2014 в 17:27

Притворяемся официальным приложением ВКонтакте из песочницы

Началось всё с того, как мой друг попросил меня опубликовать на его странице от его имени пост с моего iPad'а. Дальше я… Не знаю, как это описать… А потом задумался о том, как же официальные приложения ВК для мобильных устройств и планшетов выполняют какие-либо действия.

Сначала подумал, что приложение отправляет через POST или GET во ВКонтактик какие-то данные. Потом понял, что, скорее всего, приложение авторизуется через API. Зашёл на страницу «Разработчикам» в ВК, выбрал «Standalone/Mobile-приложения», выбрал «OAuth-авторизация». Увидел, как приложение должно авторизовываться. Оно должно создавать окно с диалогом авторизации, с такой ссылкой:

oauth.vk.com/authorize?client_id=APP_ID&scope=PERMISSIONS&redirect_uri=REDIRECT_URI&display=DISPLAY&v=API_VERSION&response_type=token

Итак, сначала нужно узнать id официального приложения.

Я решил начать с приложения для iOS, а именно для iPad.

Запостил на своей стене запись с него, открыл на десктопе. Навёл мышку на значок Яблока, и увидел желаемое «vk.com/app3682744». С этим, самым простым, мы справились. Права я решил установить только доступ к стене (и, автоматически, к основной информации), если что-то надо будет ещё добавить, это можно будет сделать потом. И, конечно, нужно включить кроме «wall» ещё и «offline» — доступ к API в любое время со стороннего сервера. Иначе, делать что-либо сможет только сервер, куда приложение отсылает все действия, и через который всё делается (возможно этот сервер — сервер ВК, но я решил не выяснять, так как это мне не нужно. Сервер прописывается в настройках приложения).

Итак, сейчас наша ссылка выглядит как:

oauth.vk.com/authorize?client_id=3682744&scope=wall,offline&redirect_uri=REDIRECT_URI&display=DISPLAY&v=API_VERSION&response_type=token

С redirect_uri разберёмся потом, как с самым сложным. «display» — внешний окна авторизации, page, popup или mobile. Выберем page.
«v» выставим последнюю, 5.7. response_type изменять не нужно, нам получить токен и надо.

Теперь будем думать над «redirect_uri». Нам нужна страница, которая покажет токен. И тут я замечаю «Если Вы разрабатываете браузерное Javascript-приложение...». Понимаю, что именно это нам подходит, так как мы обращаемся со «стороннего сервера». Там написано, что в таком случае надо указать «oauth.vk.com/blank.html». Так и сделаем. Теперь наша ссылка выглядит так:

oauth.vk.com/authorize?client_id=3682744&v=5.7&scope=wall,offline&redirect_uri=http://oauth.vk.com/blank.html&display=page&response_type=token

Переходим по ссылке, и получаем то, что мы и хотели:

image

Нажимаем на «разрешить».

image

Получаем предупреждение, и ссылку в адресной строке в виде:

oauth.vk.com/blank.html#access_token=ТОКЕН&expires_in=0&user_id=IDПОЛЬЗОВАТЕЛЯ, ТОЕСТЬНАС

Ура! Мы получили, что хотели. А дальше можно экспериментировать с функциями. Попробуем использовать «wall.post», функцию для создания записи на стене. После маленького раздумья понимаем, что надо перейти по ссылке «api.vk.com/method/wall.post?owner_id=ТУТ_ID_ПОЛЬЗОВАТЕЛЯ&message=ТУТ_ТЕКСТ&v=5.0&access_token=ТОКЕН». Проверяем, убеждаемся, что работает. Радуемся.

После поиска среди записей, нахожу id приложения для WindowsPhone — 3502561. Ещё чуть-чуть радуюсь. Решаю для ещё какого-то количества лулзов создать приложения ВУтюг и ВОкно. Их id — 3998121 и 4147789. Ссылка везде точно такая же, только параметр «client_id» надо поменять на id приложения.

Для полной очистки совести решаю написать ещё и от имени Android и iPhone, нахожу их ID (28909846 и 3087106), и тут… Вместо страницы разрешения система выдаёт грозное "{«error»:«invalid_access»,«error_description»:«Security issue»}". Я начинаю думать, в чём дело. Через какое-то время вспоминаю, что приложения для Android и WindowsPhone авторизуются не через OAuth. Захожу в документацию. Вижу, что для того, чтобы использовать прямую авторизацию, нужен ключ приложения. Его у меня, понятное дело, нет. Решаюсь на отчаянный шаг — нахожу в интернете официальное приложение ВКонтакте для Android'а, и декомпилирую его. После примерно двухчасовых рысканий по исходникам понимаю, что найти ключ не реально. Начинаю придумывать другой способ. Наконец мне это надоедает, и я начинаю заниматься другими делами. И тут до меня доходит!.. Ведь в первых версиях API была только прямая авторизация, а это значит, что старые версии приложений работают через OAuth, а, так как ВКонтакте не могло оставить не работающими старые версии, должна быть какая-то лазейка. И тут у меня появляется гениальная идея (всё гениальное — просто): в ссылке для получения токена, например, в oauth.vk.com/authorize?client_id=3682744&v=5.7&scope=wall,offline&redirect_uri=http://oauth.vk.com/blank.html&display=page&response_type=token указывается версия API системы, например тут — последняя, 5.7. А если указать старую, например, 3.0? А если вообще не указывать версию? Проверяю на приложении для Android: перехожу по ссылке oauth.vk.com/authorize?client_id=2890984&scope=notify,friends,photos,audio,video,docs,notes,pages,status,offers,questions,wall,groups,messages,notifications,stats,ads,offline&redirect_uri=http://api.vk.com/blank.html&display=page&response_type=token (на всякий случай даю полные права) и… у меня получается! ВКонтакте спрашивает разрешение, я нажимаю на «разрешить» и оно мне выдаёт токен!

После этого, для теста, пишу в адресной строке api.vk.com/method/wall.post?owner_id=ТУТ_мой_ID&message=Ура! Я смог написать от имени Android!&v=5.0&access_token=тут_мой_токен. Запись на моей стене появляется.
После этого я решаю для своего удобства сделать нормальную прогу для работы с API ВКонтакте. Пишу я её на php:

<?
class Vk{

    const CALLBACK_BLANK = 'https://oauth.vk.com/blank.html';
    const AUTHORIZE_URL = 'https://oauth.vk.com/authorize?client_id={client_id}&scope={scope}&redirect_uri={redirect_uri}&display={display}&v=5.0&response_type={response_type}';
    const GET_TOKEN_URL = 'https://oauth.vk.com/access_token?client_id={client_id}&client_secret={client_secret}&code={code}&redirect_uri={redirect_uri}';
    const METHOD_URL = 'https://api.vk.com/method/';

    public $secret_key = null;
    public $scope = array();
    public $client_id = null;
    public $access_token = null;
    public $owner_id = 0;

    function __construct($options = array()){

        $this->scope[]='offline';

        if(count($options) > 0){
            foreach($options as $key => $value){
                if($key == 'scope' && is_string($value)){
                    $_scope = explode(',', $value);
                    $this->scope = array_merge($this->scope, $_scope);
                } else {
                    $this->$key = $value;
                }

            }
        }
    }

    /**
     * Выполнение вызова Api метода
     * @param string $method - метод, http://vk.com/dev/methods
     * @param array $vars - параметры метода
     * @return array - выводит массив данных или ошибку (но тоже в массиве)
     */
    function api($method = '', $vars = array()){

        $params = http_build_query($vars);

        $url = $this->http_build_query($method, $params);

        return (array)$this->call($url);
    }


    /**
     * Построение конечного URI для выхова
     * @param $method
     * @param string $params
     * @return string
     */
    private function http_build_query($method, $params = ''){
        return  self::METHOD_URL . $method . '?' . $params.'&access_token=' . $this->access_token;
    }

    /**
     * Получить ссылка на запрос прав доступа
     *
     * @param string $type тип ответа (code - одноразовый код авторизации , token - готовый access token)
     * @return mixed
     */
    public function get_code_token($type="code"){

        $url = self::AUTHORIZE_URL;

        $scope = implode(',', $this->scope);

        $url = str_replace('{client_id}', $this->client_id, $url);
        $url = str_replace('{scope}', $scope, $url);
        $url = str_replace('{redirect_uri}', self::CALLBACK_BLANK, $url);
        $url = str_replace('{display}', 'page', $url);
        $url = str_replace('{response_type}', $type, $url);

        return $url;

    }

    public function get_token($code){

        $url = self::GET_TOKEN_URL;
        $url = str_replace('{code}', $code, $url);
        $url = str_replace('{client_id}', $this->client_id, $url);
        $url = str_replace('{client_secret}', $this->secret_key, $url);
        $url = str_replace('{redirect_uri}', self::CALLBACK_BLANK, $url);

        return $this->call($url);
    }

    function call($url = ''){

        if(function_exists('curl_init')) $json = $this->curl_post($url); else $json = file_get_contents($url);

        $json = json_decode($json, true);

        if(isset($json['response'])) return $json['response'];

        return $json;
    }

    // @deprecated
    private function curl_get($url)
    {
        if(!function_exists('curl_init')) return false;

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $tmp = curl_exec ($ch);
        curl_close ($ch);
        $tmp = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $tmp);
        return $tmp;
    }

    private function curl_post($url){

        if(!function_exists('curl_init')) return false;

        $param = parse_url($url);

        if( $curl = curl_init() ) {

            curl_setopt($curl, CURLOPT_URL, $param['scheme'].'://'.$param['host'].$param['path']);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $param['query']);
            $out = curl_exec($curl);

            curl_close($curl);

            return $out;
        }

        return false;
    }
    /**
     * @param array $options
     */
    public function set_options($options = array()){

        if(count($options) > 0){
            foreach($options as $key => $value){
                if($key == 'scope' && is_string($value)){
                    $_scope = explode(',', $value);
                    $this->scope = array_merge($this->scope, $_scope);
                } else {
                    $this->$key = $value;
                }

            }
        }

    }

    /**
     * @param bool $gid
     * @param array $files
     * @return array|bool
     */
    function upload_photo($gid = false, $files = array()){

        if(count($files) == 0) return false;
        if(!function_exists('curl_init')) return false;

        $data_json = $this->api('photos.getWallUploadServer', array('gid'=> intval($gid)));

        if(!isset($data_json['upload_url'])) return false;

        $temp = array_chunk($files, 4);

        $files = array();
        $attachments = array();

        foreach ($temp[0] as $key => $data) {
            $files['file' . ($key+1)] = '@' . $data;
        }

        $upload_url = $data_json['upload_url'];

        $ch = curl_init($upload_url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $files);

        $upload_data = json_decode(curl_exec($ch), true);

        $response = $this->api('photos.saveWallPhoto', $upload_data);

        if(count($response) > 0){

            foreach($response as $photo){

                $attachments[] = $photo['id'];
            }
        }

        return $attachments;

    }

    /**
     * Заливка документа (например GIF файл)
     *
     * @param bool $gid
     * @param $file
     * @return bool|string
     */
    function upload_doc($gid = false, $file){

        if(!is_string($file)) return false;
        if(!function_exists('curl_init')) return false;

        $data_json = $this->api('docs.getUploadServer', array('gid'=> intval($gid)));

        var_dump($data_json);

        if(!isset($data_json['upload_url'])) return false;

        $attachment = false;

        $files['file'] = '@' . $file;

        $upload_url = $data_json['upload_url'];

        $ch = curl_init($upload_url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $files);

        $upload_data = json_decode(curl_exec($ch), true);

        $response = $this->api('docs.save', $upload_data);

        if(count($response) > 0){

            foreach($response as $photo){

                $attachment = 'doc'.$photo['owner_id'].'_'.$photo['did'];
            }
        }

        return $attachment;

    }

    /**
     *
     * Заливка видео
     *
     * http://vk.com/dev/video.save
     *
     * @param array $options
     * @param bool $file
     * @return bool|string
     */
    function upload_video($options = array(), $file = false){

        if(!is_array($options)) return false;
        if(!function_exists('curl_init')) return false;

        $data_json = $this->api('video.save', $options);

        if(!isset($data_json['upload_url'])) return false;

        $attachment = 'video'.$data_json['owner_id'].'_'.$data_json['vid'];

        $upload_url = $data_json['upload_url'];
        $ch = curl_init($upload_url);

        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");

        // если указан файл то заливаем его отправкой POST переменной video_file
        if($file && file_exists($file)){

            $files['video_file'] = '@' . $file;
            curl_setopt($ch, CURLOPT_POSTFIELDS, $files);
            curl_exec($ch);

        // иначе просто обращаемся по адресу (ну надо так!)
        } else {

            curl_exec($ch);
        }

        return $attachment;

    }

}

// теперь - используем наш класс:
    $config['client_id'] = 2890984; //ID приложения, тут - Android 
    $config['user_id'] = 3087106; // id текущего пользователя (нужно не во всех случаях)
    $config['access_token'] = '778eee10654727ea96fec257f4fa4b39bd23b403649265d0fe7c37c9b01bf4c25fcb66de3738d670d5bc9'; //токен, тоже нужен не всегда
    //$config['scope'] = 'wall,photos,video'; // права доступа к методам (для генерации токена)

    $v = new Vk($config);

	$method = 'wall.postt'; ///название метода, который мы используем, в данном случае мы отпраляем запись на стену

	$params = array(); //в этом массиве - параметры, которые мы отправляем
	$params['message'] = 'I love Habrahabr!'; //в данном случае - только само сообщение
    $response = $v->api($method, $params); //выполняем
   print_r($response); //печатаем ответ, который приходит в формате JSON, но в виде массива
?>
Самин Михаил @mishasamin
карма
–11,0
рейтинг 0,0
Самое читаемое Разработка

Комментарии (92)

  • +2
    Дико извиняюсь… А зачем?
    • +3
      Что зачем?
      • +2
        Как я понял всё равно требуется авторизация того пользователя, от чьего лица будет произведено действие.
        Тогда зачем все эти шаманства? Ради значка яблока?
        • +1
          Во-первых, да, а во-вторых, можно, например, получать через api-функции ВКонтакте video.get и audio.get ссылки на скачивание музыки и видео, это даётся только официальным приложениям
          • 0
            А как тогда работаю обычные ВК Плееры под iOS? Они же не из воздуха берут музыку, а по ссылка из audio.get.
            • +1
              думаю, таким же способом, что описан в статье.
              Про audio не знаю, а ссылки на видео можно получить только с помощью client_id официальных клиентов.
              • 0
                Да, причём это делается таким же способом, как я написал в статье. Код точно такой же, только $method=audio.get или video.get и соответственно берутся нужные параметры
              • 0
                я занимался реализацией такого функционала и получал ссылки на треки под своим client_id
                • 0
                  речь о прямых ссылках? на что?
                  • 0
                    >> получал ссылки на треки
                    • 0
                      ключевое слово «прямые»
                      • 0
                        Да, ссылки на треки *.mp3. Кстати, хоть и это, скорее всего, фича для «продвинутых пользователей» ( :) ), ссылка на трек даётся в HTML. Сложность с прямыми ссылками только на видео, они даются только официальным приложениям
                      • 0
                        А на треки могут быть не прямые ссылки? Ссылка на плеер, который проигрывает этот трек? Конечно речь о прямых ссылках на *.mp3 файлы.
                        • 0
                          Нет)
                          Проблема тут только с видео.
                          Кстати, PHP класс, который я тут выложил, значительно упрощает работу с API ВКонтакте. И написать, имея такой класс, тысяча первый VK Downloader — это одна строчка.
                • 0
                  Ссылки на видео (не на плеер, а на само видео, *.mp4) вы точно не получите через своё приложение
              • 0
                И, кстати, даже если закроют возможность авторизации так, как написано в статье, а оставят для официальных приложений только OAuth, то можно сделать скачивалку через страницу документации, там даётся протестировать функции API, и можно, в том числе, получать ссылку, подставляя запрос. На PHP, например, можно написать так, чтобы поля заполняла программа, и вырезала из ответа ссылку.
                ЗЫ: страница документации — vk.com/dev/video.get
          • 0
            ой да я для своего плагина чтоб на ps3 музыку отсылать спокойно получаю offline токен и качаю музыку. Одна оговорка, ссылка действует ограниченное время.
            • 0
              как выше сказали, так прокатит только с аудио.
              • 0
                а в чем профит прямой ссылки на видео? вот просто там есть ютубчик, коуб, рутьюб. И что все дают прямые ссылки на видео?
                • 0
                  в чем профит прямой ссылки на аудио?
                  нет, прямая ссылка только с vk.com
                  • 0
                    например в том что аудио храниться на сервере вк? и я могу получить список своей музыки и музыки друзей. А вот в видео очень сомнительная необходимость. Верите или нет но видео у меня на компе только в фильмах. Все остальное я смотрю через ютуб. Собственно и музыка у меня тоже только в вк. Мне так удобнее, я могу слушать свою музыку с любого устройства в доме. Даже не заходя в ВК. Вот в этому профит прямой ссылки на аудио. А вот смотреть везде видео… Согласитесь сомнительная операция, в том плане что везде есть приложение ютуба.
                    • 0
                      итого вы обладатель выборки из одного пользователя на основе его кейса использования видео. Продолжать?
                      • 0
                        Продолжите пожалуйста.
                        • 0
                          другим людям может быть иметь видео на компьютере, иметь возможность пакетно скачать все видео из группы или определенного пользователя итд.
                    • 0
                      Но некоторые видео могут удалятся — как с ютуба, так и из ВК. И иногда понятно, что их скоро удалят. Для этого и скачивают
                  • 0
                    И еще один вопрос, вам не кажется что все что проситься в интернеты, можно проснифать? следовательно раскусить алгоритм получения прямой ссылки… Ну не знаю, смешно просто?
                    • 0
                      не очень понятна ваша мысль.
                      • 0
                        Я говорю, что сопоставив параметры которые мы передаем видео плееру и реальный запрос на видео (например я посмотрел в wireshark и у меня плеер ломанулся на s.youtube.com/stream_204?..another_parametrs...) Мы можем зная только параметры запроса видео(да хоть парся html вставку видео). Транслировать это в запрос к видео. Но все это бессмысленно. Есть у меня один Асоциальный товарищ, он с вами солидарен в вопросе хранения видео на ПК. Единственное применение я вижу только в том, что бы тащить видео туда где отсутствует интернет, но для этого я уже предпочитаю трекер.
                        • 0
                          Я говорю, что сопоставив параметры которые мы передаем видео плееру и реальный запрос на видео (например я посмотрел в wireshark и у меня плеер ломанулся на s.youtube.com/stream_204?..another_parametrs...)
                          не имеет отношения к делу. Вам гвоорят про автоматизированное получение ссылок, вы говорите, что да, дескать, так можно, но поснифать нужно, да еще регулрочками html распарсить…

                          Есть у меня один Асоциальный товарищ, он с вами солидарен в вопросе хранения видео на ПК.
                          ну-ка, ну-ка, где я высказывался по этому вопросу?

                          но для этого я уже предпочитаю трекер
                          любой более менее подкованный человек предпочтет трекер.
                          • 0
                            ну-ка, ну-ка, где я высказывался по этому вопросу?

                            вот здесь:
                            другим людям может быть иметь видео на компьютере, иметь возможность пакетно скачать все видео из группы или определенного пользователя итд.

                            Теперь дальше.
                            не имеет отношения к делу. Вам гвоорят про автоматизированное получение ссылок, вы говорите, что да, дескать, так можно, но поснифать нужно, да еще регулрочками html распарсить…

                            Отчасти да, но от части и нет. Регулярки в топку во первых, для этого гораздо удобнее использовать Dom Reader. Потом, снифать надо один раз когда разбираешься. А потом уже дело техники понять от каких входных параметров зависит выходная ссылка на прямой поток. Или вы думаете там магия происходит внутри плеера? Я вам привел пример, что правильно сформировав эту ссылку и заголовки HTTP мы получаем прямой поток с ютуба.
                            P.S. Как можно слить все видео с вк группы если половина там лежит на ютубе и прямых ссылок нет?
                            • 0
                              вот здесь:
                              я лишь высказался, что фича скачивания видео может быть полезна, иначе не было бы столько примочек к браузерам и сторонних программ, дающих прямую ссылку на видеофайлы.

                              А потом уже дело техники понять от каких входных параметров зависит выходная ссылка на прямой поток.
                              тогда вам на форумы разработчиков расширений для браузеров для скачки с ютуба. Там вас быстро осадят.

                              Как можно слить все видео с вк группы если половина там лежит на ютубе и прямых ссылок нет?
                              ответ логичен: никак.
                              • 0
                                что сводит пользу на половину в «никак».

                                Не надо решать куда мне идти, а куда нет. Но мне кажется, не «осадят»(перекрестилсо). Хотя бы по той причине, что половина этих странных программ работает по принципу который я Вам пытаюсь объяснить. Да вы сами прекрасно говорили, что нет API для получения прямой ссылки. А со мной спорите.

                                Хорошо, давайте проведем эксперемент! :) Перейдите по ссылке пожалуйста:
                                Доступ приложения в ВК

                                скопируйте url параметр access_token. и перейдите по ссылке

                                api.vk.com/method/video.get?uid=66748&access_token=_СЮДА_ВАШ_ACCESS_TOKEN_
                                Мы видим json. отлично.

                                Json Ответик
                                {«response»:[12,{«vid»:167235694,«owner_id»:66748,«title»:«New Year 2014»,«description»:"",«duration»:132,«link»:«video66748_167235694»,«image»:«http:\/\/cs534202.vk.me\/u66748\/video\/m_a65e6db4.jpg»,«image_medium»:«http:\/\/cs534202.vk.me\/u66748\/video\/l_a43809c0.jpg»,«date»:1388520121,«views»:319,«comments»:3,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=167235694&hash=d32b1a275f425628»},{«vid»:166583881,«owner_id»:66748,«title»:«New York»,«description»:"",«duration»:155,«link»:«video66748_166583881»,«image»:«http:\/\/cs505314.vk.me\/u66748\/video\/m_98ec7e45.jpg»,«image_medium»:«http:\/\/cs505314.vk.me\/u66748\/video\/l_4d005dad.jpg»,«date»:1382596566,«views»:287,«comments»:3,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=166583881&hash=b366ec402bb0d119»},{«vid»:166168343,«owner_id»:66748,«title»:«Year 2013»,«description»:"",«duration»:284,«link»:«video66748_166168343»,«image»:«http:\/\/cs505102.vk.me\/u66748\/video\/m_24f9f20e.jpg»,«image_medium»:«http:\/\/cs505102.vk.me\/u66748\/video\/l_7022d128.jpg»,«date»:1377976180,«views»:447,«comments»:0,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=166168343&hash=19ae7747722bcdc8»},{«vid»:162488090,«owner_id»:66748,«title»:«NY Alina»,«description»:"",«duration»:31,«link»:«video66748_162488090»,«image»:«http:\/\/cs505311.vk.me\/u66748\/video\/m_7f46f4b0.jpg»,«image_medium»:«http:\/\/cs505311.vk.me\/u66748\/video\/l_6193e11c.jpg»,«date»:1332748858,«views»:587,«comments»:0,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=162488090&hash=654f224360dd1767»},{«vid»:164385929,«owner_id»:66748,«title»:«in 60 seconds»,«description»:"",«duration»:60,«link»:«video66748_164385929»,«image»:«http:\/\/cs6061.vk.me\/u66748\/video\/m_ce7d46ef.jpg»,«image_medium»:«http:\/\/cs6061.vk.me\/u66748\/video\/l_33d02060.jpg»,«date»:1357995796,«views»:2224,«comments»:3,«player»:«http:\/\/player.vimeo.com\/video\/57246985»},{«vid»:164351227,«owner_id»:66748,«title»:«Dubai Fountains»,«description»:"",«duration»:100,«link»:«video66748_164351227»,«image»:«http:\/\/cs6061.vk.me\/u66748\/video\/m_515346c4.jpg»,«image_medium»:«http:\/\/cs6061.vk.me\/u66748\/video\/l_d0ffe9a1.jpg»,«date»:1357627040,«views»:487,«album»:37166103,«comments»:0,«player»:«http:\/\/player.vimeo.com\/video\/56948103»},{«vid»:164320862,«owner_id»:66748,«title»:«Крокодил»,«description»:"",«duration»:21,«link»:«video66748_164320862»,«image»:«http:\/\/cs523110.vk.me\/u66748\/video\/m_33b38e9f.jpg»,«image_medium»:«http:\/\/cs523110.vk.me\/u66748\/video\/l_6b430594.jpg»,«date»:1357242999,«views»:329,«album»:37166103,«comments»:0,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=164320862&hash=84010730da187a06»},{«vid»:163477624,«owner_id»:66748,«title»:«Year 2012»,«description»:«Сегодня мой день рождения. Год назад я проснулся на другом конце мира, сейчас засыпаю дома, это был не лёгкий период, и многое изменилось за это время. Пытаясь отложить сон я обрёл несколько свободных часов и решил сделать одну мелочь. Я склеил разные видео, снятые за этот год, в коротенький клип. Только то, что снял за этот год. Не много, но на пару минут хватило. Думаю идея хорошая и это должно стать традицией.»,«duration»:148,«link»:«video66748_163477624»,«image»:«http:\/\/cs507412.vk.me\/u66748\/video\/m_8fe5f910.jpg»,«image_medium»:«http:\/\/cs507412.vk.me\/u66748\/video\/l_056089b2.jpg»,«date»:1346450624,«views»:395,«comments»:2,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=163477624&hash=5e526ac5c13353c2»},{«vid»:163196601,«owner_id»:66748,«title»:«VK CUP»,«description»:"",«duration»:3,«link»:«video66748_163196601»,«image»:«http:\/\/cs526400.vk.me\/u66748\/video\/m_2d9ce4ec.jpg»,«image_medium»:«http:\/\/cs526400.vk.me\/u66748\/video\/l_736a664d.jpg»,«date»:1342289809,«views»:870,«album»:37166103,«comments»:2,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=163196601&hash=052746db77ed409e»},{«vid»:162537461,«owner_id»:66748,«title»:«Flakes»,«description»:«No microwave, they are cold. No soda and other reagents, only milk and flakes.»,«duration»:18,«link»:«video66748_162537461»,«image»:«http:\/\/cs510111.vk.me\/u66748\/video\/m_1138e37a.jpg»,«image_medium»:«http:\/\/cs510111.vk.me\/u66748\/video\/l_040050b7.jpg»,«date»:1333268191,«views»:1855,«comments»:18,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=162537461&hash=882f0157f6ef688d»},{«vid»:161487590,«owner_id»:66748,«title»:«test»,«description»:«sdfasfg»,«duration»:5,«link»:«video66748_161487590»,«image»:«http:\/\/cs507411.vk.me\/u66748\/video\/m_df39f59d.jpg»,«image_medium»:«http:\/\/cs507411.vk.me\/u66748\/video\/l_4e8de9aa.jpg»,«date»:1320591379,«views»:1095,«comments»:1,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=161487590&hash=aac1b7e121858b8a»},{«vid»:163884836,«owner_id»:66748,«title»:«Vld_hppy_bzd.vonny»,«description»:"",«duration»:171,«link»:«video66748_163884836»,«image»:«http:\/\/cs527320.vk.me\/u66748\/video\/m_a4024281.jpg»,«image_medium»:«http:\/\/cs527320.vk.me\/u66748\/video\/l_ab8a89aa.jpg»,«date»:1351877397,«views»:912,«album»:37166103,«comments»:4,«player»:«http:\/\/vk.com\/video_ext.php?oid=66748&id=163884836&hash=0fcdd3e1eb0378a1»}]}


                                Возьмем самое первое видео не ведомого мне юзера, и перейдем по адресу, vk.com/video66748_167235694, сделаем поиск по исходному коду на тему url720, и там ВНЕЗАПНО видим ссылку \«url720\»:\«http:\\\/\\\/cs534202v4.vk.me\\\/u66748\\\/videos\\\/3c03a57fda.720.mp4\», что можно отбросив экранирующие символы прочитать как cs534202v4.vk.me/u66748/videos/3c03a57fda.720.mp4, Давайте теперь вместе перейдем по этой прямой ссылкой на видео. Это наипростейший пример с ВК, с youtube сложнее. Но возможно. Имеет смысл дальше продолжать наш спор или Вы признаете поражение? Вот честно, не заставляйте меня разжёвывать ютуб.
                                • 0
                                  я с вами спорю? я вам говорю, что с помощью апи можно получить прямую ссылку на видео. Без лишних телодвижений.
                                  Делаю один запрос, получаю 100 прямых ссылок (ну или сколько там можно за раз? непринципиально). А вы получаете 100 ссылок на страницы с видео, которые еще нужно http-запросом скачать (вы же понимаете, что 100 запросов займут > 90% времени работы скрипта?), а потом xpath'ом, регуляркой, «вашим любимым инструментом для парсинга dom» извлечь прямую ссылку.
                                  Речь не о том, что можно добыть ссылку — это не обсуждается. Речь о том, что ее можно быстро и «официально» добыть (кавычки не объясняю, понятно).
                                  То, что вы предлагаете, это очевидно и не обсуждается. Но по сравнению с темой топика — это вылавливание видео в папке с кэшем. Помните такую забаву n-летней давности?
                                  И, боже упаси, я с вами не спорю — все, что есть в инете, теоретически будет на наших компах.
                                  И куда идти вам тоже не указывал. Но будь вы в теме, знали бы, что алгоритмы скачивания видео на ютубе меняются несколько раз в год. Надо ли говорить сколько раз менялся метод video.get за последние несколько лет?
                                  • 0
                                    Тема топика прикинуться чужим приложением. Для не совсем объективных целей. Если алгоритм меняется это станет известно, и раскусить его дело 15 минут. Опять таки, вы не получите 100 ссылок на видео если они не хранятся в вк. И даже если так, то, поймите меня правильно, когда вы качаете видео по 100-200мб, подождать когда скачается 2кб страница и распарсится чтоб выдернуть json, не должно доставлять неудобств. Просто к чему это я. Есть у меня сейчас один проект, который по сути региональный сайт клон московского гиганта. Причем почти все страницы у меня прозрачно проксированы на сайт оригинал, где я на ходу меняю шапку и футер. Ну и что бы все совсем весело, скрипты и картинки тоже проксируются. Правильно играя кэшем, это не вызывает проблем. Поэтому я не вижу проблемы вполне официально получить прямую ссылку из исходников если не хочется показывать видео, а хочется именно его скачать. Разница наших подходов, что я предпочту пользоваться апи которому 100 лет в обед и оно не поменяется(да не важно сколько video.get раз менялось, оно возвращает ссылки на видео — факт. ), а уж плеер мне кажется уже большое наследие тащит, достаточно глянуть какие параметры передаются во flashvars. и я сомневаюсь что этим кто то будет серьёзно заниматься и это кому то надо. и вы не поверите, я тоже спокойно скачаю 200 видео за раз. Только я буду спокоен что мое приложение говорит что оно мое приложение.
                                    • 0
                                      объективные, необъективные цели — это все вкусовщина, как и «я буду спокоен что мое приложение говорит что оно мое приложение».

                                      И даже если так, то, поймите меня правильно, когда вы качаете видео по 100-200мб, подождать когда скачается 2кб страница и распарсится чтоб выдернуть json, не должно доставлять неудобств.
                                      об одном-двух видео говорить глупо. Для этого есть более быстрые (one-click) пути скачать видео.
                                      Если речь идет о сотне видео, то скрипт будет отрабатывать около минуты вместо пары секунд.
                                      И речь, конечно, идет только о скриптах «для себя», никаких сайтов и сервисов.

                                      • 0
                                        уфф… в архитектуре дело. Вот если делать скрипт который будет вываливать список видео, то я уж извольте не буду выдирать сразу прямые ссылки, что будет блин так же быстро как и у вас. а потом за one-click другим скриптом парсить нужную мне страницу и вырезать видео файл и просто выдавать его пользователю на скачивание. Как вам такой поворот? Ах и да, в моем подходе есть +, что можно просто скормить адрес видео который уже открыт в браузере. Так что не надо мне тут прикидываться чужим приложением что бы якобы качать видео у юзеров кейсом. Я 10000000 раз подумаю когда у меня какое то приложение для вк iPad запросит доступ на хер его знает сколько разрешений. Или вы предлагаете всем offline токен свой раздавать? Нет абсолютно никакого смысла ради прямых ссылок прикидываться другим приложением. И что делать если его удалят? А что делать если для новых приложений выключать старую авторизацию? Миллион а что если, против одного — поменяли выдачу. И кстати когда я говорил, я подразумевал максимальное число выдачи video.get, а не 1-2 видео.
                                        • 0
                                          вас понял, но диалог идет в стиле о Фоме и Ереме. Вы пишите 2кб страница, я пишу, что профит от 100 ссылок, вы отвечаете, что не 2кб имели в виду а 2*100, я говорю тогда в вашем подходе профита нет, вы отвечаете про токены и безопасность. Через 5 сообщений цикл закончился, начали заново обсуждать каждый свое.
                                          Предлагаю свернутся и идти на отдых. )
                                          • 0
                                            согласен, а то разговор ведем с двух разных башен
                                • 0
                                  Если делать так, то вообще надо не через исходный код, а через страницу с тестированием функции video.get делать. Но это… Неспортивно как-то…
                                  • 0
                                    я думаю вы про мой метод. страница с исходным кодом чисто для ручного теста. Естественно браузер тоже жует то что мы будем жевать. То есть голый html в котором задаются параметры видеоплеера.
                • 0
                  В том, что видео можно скачать, до того, как его, например, удалят. С YouTube'а, RuTube'а и так далее можно скачивать, получая прямую ссылку, намного проще, так как там в API это делается намного проще
                  • 0
                    апи ютуба не позволяет скачивать ролик. думаю, рутуба тоже
                    • 0
                      Позволяет. Этим пользуется, например, SaveFrom
                      • 0
                        нет, все инструменты для скачки с ютуба идут обходными путями.
                        • 0
                          Нет. Ссылка на скачивание с YouTube'а у SaveFrom'а ведёт на сервера YouTube'а. В этом я уверен.
                          • 0
                            ссылка с сервера на ютуб != скачивание через апи.
  • +1
    Этот же пост был тут дней 10 назад? На данный момент он в черновиках.

    з.ы. а… походу это ваш же аккаунт.
    • –1
      Да, аккаунт заблокировали, так как я не знал тогда правил Хабра, и выпрашивал карму. Эта статья, кстати, значительно дополнена.
  • 0
    Мне кажется теперь закроют поддержку старых версий API, так как вы обнародовали способ прямой авторизации в ВК.
    • 0
      а в новых версиях другой способ авторизации?
      • 0
        Ну да, через ихнюю веб форму
        • 0
          какую веб-форму? в документации описано 4 способа oauth-авторизации, и они все являются рабочими в последней версии api.
          Что-то путаете или я вас неправильно понял.
          • 0
            OAuth — это один из способов авторизации. А не в принципе авторизация
            • 0
              и не спорю. Только проблемы не вижу в «способе прямой авторизации»
              • 0
                Повторюсь, я перепутал прямую авторизацию и OAuth
      • 0
        В новых версиях — через OAuth. Почитайте документацию API ВКонтакте. Для работы через OAuth нужен ключ приложения.
        • 0
          и что? что поменялось то? был oauth, остался oauth, в чем проблема?
          • 0
            Был — не OAuth. Была только прямая авторизация. Так нужен будет ключ приложения. Секретный ключ приложения, а не токен
          • 0
            Извиняюсь, я перепутал везде OAuth и прямую авторизацию
    • –1
      Нет, не закроют, так как иначе перестанут работать старые версии приложений
      • 0
        Вы правы, не закроют. Просто начнут вешать капчу на каждый чих + саспендить «за подозрительную активность», как это было во время борьбы с VKBot.

        Все это уже было. Ваш «срыв покровов» опоздал года на два, да и пользоваться им в текущей реализации реально опасно, поскольку отправляемые запросы очень отличаются от того, что отправляется даже из старых клиентов, а блокировка может быть установлена на срок до трёх суток (мне не кто-то рассказывал, я сам на подобную нарывался). Причем им наплевать — спамите вы или просто ищете музыку.
        • 0
          Отправляемые запросы — такие же. Да и все многочисленные VK Downloader'ы сделаны именно так. Кстати, скачивать музыку можно и не от имени официальных приложений. Только от имени официальных приложений можно получать ссылки на скачивание видео.
          • 0
            скачивание вообще происходит без участия приложения.
          • 0
            Не такие. Например, юзерагент у мобильного приложения далеко на Mozilla. Да и запросы оно формирует несколько иначе, чем описано в официальной документации. И это только то, что я вынес бегло просмотрев вашу портянку.

            Про музыку и видео я в курсе. Я для примера упомянул именно музыку.
    • 0
      и, кстати, о прямой авторизации написано в документации, о client_id оф. приложений известно в интернете, и даже на хабре об этом писали уже. Мир не перевернулся.
      • 0
        Да, кстати, id приложения можно узнать, наведя на его значок (например, на яблоко). Там высвечивается ссылка «vk.com/app<ID приложения>. Но ведёт эта ссылка на группу приложения. На Хабре об этом, вроде, ещё не писали. Но самое главное в этом посте — достаточно удобный PHP класс для работы с API ВКонтакте. Можно, например, сделать скачивалку видео из ВКонтакте, прямая ссылка на видео, а не на плеер даётся только официальным приложениям
        • 0
          у меня такой класс уже полгода лежит на гитхабе в том числе с поддержкой прямой авторизации.
          • 0
            Скинь ссылку на свой класс, пожалуйста
            • 0
              • 0
                Спасибо. А мой класс для работы с API ВКонтакте нормальный?
                • 0
                  класс как класс. на гитхабе есть еще несколько аналогов — они все похожи.
      • 0
        Прямая авторизация — для доверенных приложений
        • 0
          Нет. Прямая авторизация — для Stadelone/Mobile приложений.
          Или нет? Блин. Забыл уже(
          • 0
            Доступ к этому типу авторизации может быть получен только после предварительного согласования с администрацией ВКонтакте.

            vk.com/dev/auth_direct
            • 0
              конечно. И что? все реквизиты оф. приложений известны. Не тайна за семью печатями.
              • 0
                Вот именно
              • 0
                Вам не кажется, что не совсем правильно использовать реквизиты другого приложения? Мне прийдется каждый раз перезаливать приложение в стор, когда они будут меня реквизиты.
                • 0
                  не совсем правильно, но для своих нужд вполне пойдет, не для паблика.
                  Вам зачем придется перезаливать что-то?
            • 0
              Значит, я в статье везде OAuth и прямую авторизацию перепутал(
  • 0
    В статье поменял местами OAuth и прямую авторизацию, перепутал их. Спасибо пользователям zelenin и usgleb за разъяснение!
  • 0
    На 4pda можно скачать пересобранную версию приложения под андроид с id от других платформ ( 4pda.ru/forum/index.php?showtopic=246233&st=2560#entry23727782)
    • 0
      хм, интересно)
    • 0
      Как-то там сложно пошли, для подмены всего-то надо токен по ссылке
      https://oauth.vk.com/token?grant_type=password&client_id=3140623&client_secret=VeWdmVclDCtn6ihuP1nt&username=user@domain.ru&password=mypassword
      выдернуть и положить в файле /data/data/com.vkontakte.android/shared_prefs/null.xml в поле sid
      • 0
        Дело в том, что токен приложения найти достаточно сложно
        • 0
          Ну как сказать, если его специально разработчик не прячет — то regexp-ом во всем файлам вполне найти можно.
          • 0
            Я не нашёл)
            Да и разработчик, думаю, прячет его
            • 0
              Вы ссылку выше открывали со своими данными? Я не понимаю, зачем на 4пда в инструкции идет перепаковка и какие-то лишние манипуляции. Достаточно наличия root-explorer'а и браузера в самом смартфоне, чтобы прилепить несчастное яблоко к своим постам.
              • 0
                С 4pda поставил приложение — и сразу всё есть, никаких лишних ковыряний, справится почти любой.
  • 0
    После примерно двухчасовых рысканий по исходникам понимаю, что найти ключ не реально.

    Я бегло глянул и, насколько я увидел, секретный ключ для SHA-1 подписи — это сигнатура APK которую приложение добывает в Runtime через developer.android.com/reference/android/content/pm/PackageInfo.html --> developer.android.com/reference/android/content/pm/Signature.html
    • 0
      Дело в том, что я почти не знаю Java, и по исходникам пробежался бегло, в надежде, что ключ находится где-то на поверхности
  • 0
    Ссылка авторизаци, выдрал из декомпила адроид приложения ВК
    api.vk.com/oauth/token?grant_type=password&scope=nohttps&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username=%1$s&password=%2$s
  • 0
    в первых версиях API была только прямая авторизация, а это значит, что старые версии приложений работают через OAuth

    Логично, что ж…

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