Многие знают о том, что у контакта есть API для различных действий. С помощью них можно и сообщение от имени пользователя послать, и его френдленту получить. Но проблема (по крайней мере для меня это проблема) в том, что не все методы API можно вызвать через сайт, для некоторых нужны desktop-решения. Вконтакте это описано так: внутри программы ставим компонент браузера, в который будет выводится форма с разрешением некоторых прав для программы и пользователь сам выбирает, что разрешить. Далее форма переходит на специальный адрес и из ссылки после # вытаскиваются необходимые параметры. Решил обойти это ограничение. Накатал небольшой класс PHP: <?php class vkapi { public $mid = ''; public $sid = ''; public $secret = ''; public $expire = ''; public $settings = ''; public $settings_hash = ''; public $user_first_name = ''; public $user_full_name = ''; public $user_thumb = ''; public $auth_hash = ''; public $sig = ''; private $api_id = ''; public $cookie = ''; // печеньки public $remixsid = ''; // главная печенька public $antigateHash = ''; public function __construct($api_id='') { $this->api_id = $api_id; } public function get($url, $follow=1) { $process = curl_init($url); curl_setopt($process, CURLOPT_HEADER, 1); curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; ru-ru) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7'); curl_setopt($process, CURLOPT_COOKIE,$this->cookie); curl_setopt($process, CURLOPT_TIMEOUT, 15); curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); curl_setopt($process, CURLOPT_FOLLOWLOCATION, $follow); $return = curl_exec($process); curl_close($process); return $return; } public function post($url, $data, $follow=1) { $process = curl_init($url); curl_setopt($process, CURLOPT_HEADER, 1); curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; ru-ru) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7'); curl_setopt($process, CURLOPT_COOKIE,$this->cookie); curl_setopt($process, CURLOPT_TIMEOUT, 15); curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); curl_setopt($process, CURLOPT_FOLLOWLOCATION, $follow); curl_setopt($process, CURLOPT_POST, 1); curl_setopt($process, CURLOPT_POSTFIELDS, $data); $return = curl_exec($process); curl_close($process); return $return; } public function doAppPermit() { /* Возвращается объект со следующими значениями: expire Время истечения сессии в формате UNIX mid ID пользователя в ВКонтакте secret Специально сгенерированный секрет сессии sid Идентификатор сессии */ $resp = $this->getBody($this->post('http://vkontakte.ru/login.php', 'act=a_auth&app='.$this->api_id.'&hash='.$this->auth_hash.'&permanent=1')); if ($obj = @json_decode($resp)) { $this->mid = $obj->mid; $this->sid = $obj->sid; $this->secret = $obj->secret; $this->expire = $obj->expire; } else return false; } public function doLogin($login, $pass) { // 1 шаг $resp = $this->post('http://vkontakte.ru/login.php?app='.$this->api_id.'&layout=popup&type=browser&settings=16383', '',1); $this->getCookie($resp); $match = array(); preg_match('#type=("|\')hidden("|\')\sname=("|\')app_hash("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match[]); preg_match('#type=("|\')hidden("|\')\sname=("|\')vk("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match[]); preg_match('#type=("|\')hidden("|\')\sname=("|\')permanent("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match[]); preg_match('#type=("|\')hidden("|\')\sname=("|\')al_test("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match[]); $postdata = "act=login&app={$this->api_id}&app_hash={$match[0][6]}&vk={$match[1][6]}&captcha_sid=&al_test={$match[3][6]}&captcha_key=&email={$login}&pass={$pass}&expire=&permanent={$match[2][6]}"; // 2 Шаг $resp = $this->post('http://login.vk.com/', $postdata, 0); $this->cookie = ''; $this->getCookie($resp); if (preg_match_all('#name=("|\')(.*)("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match)) { $postdata = ''; foreach ($match[2] as $k => $v) { $postdata .= $match[2][$k] . '=' . $match[5][$k] . '&'; } $postdata = substr($postdata, 0, -1); preg_match('#name=("|\')s("|\')\svalue=("|\')(.*)("|\')#Us', $resp, $match); $this->remixsid = $match[4]; // 3 Шаг $resp = $this->post('http://vkontakte.ru/login.php', $postdata, 0); if (preg_match('#<script type="text/javascript">parent.onDone\((.*)\)<\/script>#Us', $resp, $match)) { $obj = json_decode(iconv("WINDOWS-1251", "UTF-8", $match[1])); $this->mid = $obj->mid; $this->sid = $obj->sid; $this->secret = $obj->secret; $this->expire = $obj->expire; $this->settings = $obj->settings; $this->settings_hash = $obj->settings_hash; $this->user_first_name = $obj->user_first_name; $this->user_full_name = $obj->user_full_name; $this->user_thumb = $obj->user_thumb; $this->auth_hash = $obj->auth_hash; return true; } else return false; } else return false; } public function desktop_api($method, $data='') { $sig = ''; $postdata = array( 'api_id' => $this->api_id, 'v' => '3.0', 'format' => 'JSON', 'method' => $method ); if ($data) { foreach ($data as $k => $v) { $postdata[$k] = $v; } } ksort($postdata, SORT_STRING); foreach ($postdata as $k => $v) $sig .= $k . '=' . $v; $sig = md5($this->mid . $sig . $this->secret); $postdata['sig'] = $sig; $postdata['sid'] = $this->sid; $resp = $this->post('http://api.vkontakte.ru/api.php', $postdata); return $resp; } public function saveSettings() { $this->cookie = "remixchk=5; remixsid=".$this->remixsid; $postdata = array('addMember' => 1, 'id' => $this->api_id, 'hash' => $this->settings_hash, 'app_settings_8192' => 1, 'app_settings_4096' => 1,'app_settings_2048' => 1,'app_settings_1024' => 1,'app_settings_512' => 1,'app_settings_256' => 1,'app_settings_128' => 1,'app_settings_64' => 1,'app_settings_32' => 1,'app_settings_16' => 1,'app_settings_8' => 1); $resp = $this->post('http://vkontakte.ru/apps.php?act=a_save_settings', $postdata, 1); // Работаем с капчей if (preg_match('#"captcha_sid":"(.*)"#Us', $resp, $match)) { if ($this->antigateHash) { $temp = $this->getBody($this->get('http://m.vkontakte.ru/captcha?s=1&sid='.$match[1])); file_put_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'captcha'. DIRECTORY_SEPARATOR . $match[1].'.jpg',$temp); $temp = $this->captcha(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'captcha'. DIRECTORY_SEPARATOR . $match[1].'.jpg'); $postdata['captcha_sid'] = $match[1]; $postdata['captcha_key'] = $temp; $resp = $this->post('http://vkontakte.ru/apps.php?act=a_save_settings', $postdata, 1); } else { return false; } } else { return true; } } // Достаем из запроса кукисы private function getCookie($data) { if (preg_match_all('#Set-Cookie: (.*);#Us',$data,$match)) $this->cookie .= implode('; ',$match[1]); } // Возвращает текст ответа сервера без заголовка public function getBody($text) { return array_pop(explode(PHP_EOL.PHP_EOL,$text)); } public function captcha($captchaFile) { $rtimeout = 5; $mtimeout = 90; $postdata = array( 'method' => 'post', 'key' => $this->antigateHash, 'file' => '@'.$captchaFile, 'phrase' => 0, 'regsense' => 1, 'numeric' => 0, 'min_len' => 4, 'max_len' => 7 ); $result = $this->post('http://www.antigate.com/in.php', $postdata); if (strpos($result, "ERROR")!==false) { $this->captchaDebug = $this->getBody($result); return false; } else { $ex = explode("|", $result); $captcha_id = $ex[1]; $waittime = 0; sleep($rtimeout); $time1 = microtime(true); while(true) { $result = @file_get_contents('http://antigate.com/res.php?key='.$this->antigateHash.'&action=get&id='.$captcha_id); if (strpos($result, 'ERROR')!==false) { $this->captchaDebug = $result; return false; } if ($result=="CAPCHA_NOT_READY") { $waittime += $rtimeout; if ($waittime>$mtimeout) { $this->captchaDebug = 'Time expired'; break; } sleep($rtimeout); } else { $ex = explode('|', $result); if (trim($ex[0])=='OK') { $this->captchaTime = microtime(true) - $time1; return trim($ex[1]); } } } return false; } } } ?> Его применение: PHP: <?php $api_id = '456654'; $login = [email='asd@asd.ru]'asd@asd.ru[/email]'; $pass = 'qwe'; $vk = new vkapi($api_id); if ($vk->doLogin($login, $pass)) { $vk->saveSettings(); $vk->doAppPermit(); $text = $vk->getBody($vk->desktop_api('newsfeed.get', '')); echo $text; } ?> Фишка в том, что скрытно можно добавить пользователю любое приложение с полными правами. Пытался узнать в группе по API о том, не нарушаю ли я таким образом каких-либо прав - никто не ответил. Так что, если кому интересно, пользуйтесь. Также всегда интересны ремарки по коду!
А можно сделать так чтобы пользователь вводил свои пароль и логин на сайте контакта как при OPEN API авторизации, если есть такие наработки поделитесь. У меня начало кагбЭ есть т.е. открывается окошко в котором вводим пароль и логин, перебрасывает на страницу где http://vkontakte.ru/api/login_success.html#session={%22mid%22%3A3242346576%2C%22sid%22%3A%22d1b2942597672176bee39dcee1a5030fb4a2d5008d7fd2b903cdf7e6d415ae%22%2C%22secret%22%3A%22eefd544eb3%22%2C%22expire%22%3A0%2C%22sig%22%3A%22e2e931fg3rt545f6233e38bb3188f11e0%22} а вот данные сессии не знаю как вернуть обратно в php (по ходу надо javascript использовать, но я блин в нем не силен) подскажите как быть...