Just Blog about nothing

14Июнь/11Off

Защищённый запрос к ВКонтакте API

ВКонтакте 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;
  }
}
Комментарии (0) Пинги (0)

Извините, комментировать здесь запрещено.

Trackbacks are disabled.

Social Widgets powered by AB-WebLog.com.