14Июнь/11Off
Защищённый запрос к ВКонтакте API
Класс из GMFramework, с помощью которого можно осуществлять запросы к ВКонтакте API.
Для обеспечения безопасности запроса используется защищенный ключ приложения. Подразумевается, что он сохранён в константе SECURE_CODE
.
Для выполнения запросов к скриптам ВКонтакте используется модуль PHP cURL, для обработки ответа JSON. От использования XML-формата я отказался, поэтому он больше не поддерживается.
/** * Защищённый запрос к api ВКонтакте * @package ru.vbinc.gm.framework.VKontakte * @author GreyMag * @copyright 2009 * @version 1.6 */ class SecureRequest { /** * Сообщение об ошибке */ public $error; /** * Номер ошибки */ public $errno; /** * Посланные поля */ public $requestFields; private $_secureCode; // защищенный ключ private $_apiId; // идентификатор приложения private $_method; // название метода API из общего списка функций private $_parameters = array(); // массив передаваемых параметров private $_v = '2.0'; // версия API - необязательный параметр private $_format; // формат возвращаемых данных – XML или JSON. По умолчанию JSON (на ВК по умолчанию XML) - необязательный параметр private $_requestUrl = 'http://api.vkontakte.ru/api.php'; // url для запроса private $_testMode = false; // тестовый режим // список защищёных методов /** * Метод отправляет уведомление пользователю */ const SEND_NOTIFICATION = 'secure.sendNotification'; /** * Метод сохраняет строку статуса приложения * для последующего вывода в общем списке приложений на странице пользоваетеля */ const SAVE_APP_STATUS = 'secure.saveAppStatus'; /** * Метод возвращает платежный баланс приложения */ const GET_APP_BALANCE = 'secure.getAppBalance'; /** * Метод возвращает баланс пользователя на счету приложения */ const GET_BALANCE = 'secure.getBalance'; /** * Метод списывает голоса со счета пользователя на счет приложения */ const WITHDRAW_VOTES = 'secure.withdrawVotes'; /** * Метод возвращает историю транзакций внутри приложения */ const GET_TRANSACTIONS_HISTORY = 'secure.getTransactionsHistory'; /** * Таймаут между запросами ( не больше трех в секунду ) */ const KONTAKT_REQUEST_DELAY = .3; /** * формат возвращаемых данных - xml * @var String */ const FORMAT_XML = 'XML'; /** * формат возвращаемых данных - json * @var String */ const FORMAT_JSON = 'JSON'; public function __construct( $apiId, $testMode = false ) { $this->_apiId = $apiId; if( defined( 'SECURE_CODE' ) ) $this->_secureCode = SECURE_CODE; $this->_format = self::FORMAT_JSON; $this->_parameters['api_id'] = $this->_apiId; $this->_parameters['v'] = $this->_v; $this->_parameters['format'] = $this->_format; if( $testMode ) { $this->_testMode = true; $this->_parameters['test_mode'] = '1'; } } /** * SecureRequest::request() * Отправка запроса на ВКонтакте * @param mixed $method Название метода * @param array $parameters Массив передаваемых параметров со значениями * @return Объект ответа с ВКонтакте */ public function request( $method, $parameters = array() ) { $this->_parameters['method'] = $method; if( is_array( $parameters ) ) $this->_parameters = array_merge( $this->_parameters, $parameters ); $this->_parameters['timestamp'] = $this->getTimestamp(); $this->_parameters['random'] = BaseString::randomStr(); $queryString = $this->createQueryString(); $curl = curl_init(); curl_setopt( $curl, CURLOPT_URL, $this->_requestUrl ); curl_setopt( $curl, CURLOPT_POST, 1 ); curl_setopt( $curl, CURLOPT_POSTFIELDS, $queryString ); curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec( $curl ); $error = curl_getinfo( $curl ); curl_close( $curl ); if ( $error['http_code'] != "200" ) { $this->errno = '0'; $this->error = 'Ошибка соединения'; return false; } else { $answer = json_decode( $result ); if( !isset( $answer->response ) ) { if( isset( $answer->error ) ) { $this->errno = $answer->error->error_code; $this->error = $answer->error->error_msg; $this->requestFields = $answer->error->request_params; } else $this->error = 'Неопознанная ошибка.'; return false; } else return $answer->response; } } /** * Формирует строку запроса */ private function createQueryString() { $string = ''; foreach( $this->_parameters as $name=>$value ) $string .= $name . '=' . urlencode( $value ) . '&'; $string .= 'sig=' . $this->createSIG(); return $string; } /** * Создаёт подпись запроса */ private function createSIG() { $string = ''; ksort( $this->_parameters, SORT_STRING ); foreach( $this->_parameters as $name=>$value ) $string .= $name . '=' . $value; $string .= $this->_secureCode; return md5( $string ); } /** * Возвращает случайную строку для обеспечения уникальности запроса */ private function getRandom() { return BaseString::randomStr(); } /** * Возвращает текущее значение unixtime на сервере */ private function getTimestamp() { return DateTimeUtils::date(); } }
Примечание. Класс использует утилиты из GMFramework. Но все такие использования заключены в отдельные методы с описанием, так что при желании можно просто переписать их, без использования GMFramework.
Использование, на примере совершения транзакции (снятие голосов со счёта пользователя на счёт приложения):
function transferVotes( $votes, $userId = 0 ) { $userId = (float)$userId; if( $votes < 0 || $userId <= 0 ) return false; if( $votes == 0 ) return true; $votes = (int)( $votes * 100 ); $invoker = new SecureRequest( API_ID ); // API_ID - константа, содержащая идентификатор приложения if( $result = $invoker->request( SecureRequest::WITHDRAW_VOTES, array( 'uid' => $userId, 'votes' => $votes ) ) ) { if( (int)$result == $votes ) return true; else { // ошибка перевода голосов return false; } } else { // здесь можно отдельно обраотать ошибки, // например ошибка $invoker->errno == 502 - у пользователя на счету нет голосов return false; } }