Не так давно я столкнулся с трудностью. У меня не получалось при запросе по API в OK.RU (одноклассники) создать правильную SIG (ошибка 104). Как оказалось, я не единственный такой был, предлагаемые в сети рецепты не очень работали (проверил многие методом тыка). На самом деле работали, просто я не понимал, как правильно построить нужный запрос, чтобы ещё и SIG был правильным.

Конкретно, этот пост посвящен именно 104 ошибке API OK.RU.

PARAM_SIGNATURE	104	Неверная подпись

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


	protected $params = array(
	'application_id' => '5*******6',
	'application_key' => 'C***********A',
	'session_secret_key' => '*************0'
	
	);
	
	protected $apiUrl = 'https://api.ok.ru/fb.do?';
	
	public function getalbums( Request $request ) {
		
		//access_token я записываю в БД и вытаскиваю его оттуда.
		$userok = Userok::where('useroks.user_id', '=', $request->user_id)->first();
		
		$paramsArray = array(
		'application_key' => $this->params['application_key'],
		'format' => 'json',
		'method' => 'photos.getAlbums',
		);
		ksort($paramsArray);
		
		foreach($paramsArray as $k=>$v) {
			$paramsStr .= $k . "=" . $v;
		}
		
		
		
		/*** Отредактировано уже в статье. Это кусок кода, как делать не надо (в первой редакции забыл закоментировать).
			
			$sig = strtolower(
			md5(
			$paramsStr)
			. md5(
			$userok->access_token
			.$this->params['session_secret_key']
			)
			);	
			
		**/
		
		
		$sectret_key = md5($userok->access_token.$this->params['session_secret_key']);
		$sig = md5($paramsStr.$sectret_key);
		
		
		$paramsArray['sig'] = $sig;
		$paramsArray['access_token'] = $userok->access_token;
		
		
		return $this->sendRequest(
		$this->apiUrl,
		$paramsArray,
		'POST'
		);
		
		
	}
	
	
	protected function sendRequest($url = '', $params = array(), $method = 'POST') {
		if(is_array($params)) {
			$params = http_build_query($params);
		}
		$ch = curl_init();
		if($method == 'GET') {
			$url .= $params;
			} else if($method == 'POST') {
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		}
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		$result = curl_exec($ch);
		curl_close($ch);
		return json_decode($result, true);
	}

Но чтобы это работало, нужен правильный $paramsArray, иначе Вы решите 104-ю ошибку, но получите другую. Многие начинающие программисты, наверняка, игнорируют старания OK.RU помочь разработчикам.

Итак, переходим по ссылке https://apiok.ru/dev/methods/.

Находим вот такую форму:



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

Надеюсь, статья была полезной.

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


  1. HunterNNm
    21.09.2019 15:49
    +1

    Замечание — код бы под PSR подогнать, да форматирование добавить — читается сложно.
    Вопрос — это laravel? Очень похоже. Если да — то почему curl, а не guzzle?


    1. maxsharun Автор
      21.09.2019 16:30

      Это Laravel. Я делаю заказ. Curl потому что он точно у меня установлен, я умею с ним работать и сдавать нужно вчера, поэтому даже в голову не пришло что-то другое взять. Честно, с Guzzle не работал. Но! Я делаю отдельный свой проект, изучу и, возможно, буду использовать.

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


      1. HunterNNm
        21.09.2019 19:16

        Пробегусь по всему коду.


        1. Полностью array() можно не писать, лучше []. Сути не меняет, но полную запись давно не видел(больше имхо)
        2. Нет валидации. Понимаю, что демка, но в демку лучше тоже добавлять
        3. 'useroks.user_id' — 'useroks' излишне. Да и название таблицы такое себе, если честно. Про переменные не по PSR я молчу — в комменте выше было. Ну и можно свести where('useroks.user_id', '=', $request->user_id) до whereUserId($request->user_id)
        4. ksort не нужен
        5. foreach выглядит странно
        6. sectret_key — ааааа именование :(
        7. В объявлениях методов (кроме getalbums) нету объявления типа аргумента. Не надо так… Да и проверки типа is_array уйдут


        1. maxsharun Автор
          21.09.2019 21:55

          Я поясню.
          1. Здесь полностью согласен
          2. Валидация здесь совсем не нужна (т.к. это черновик реального проекта, там это чуть иначе реализовано и форм для ввода нет).
          3. useroks — здесь хранятся acess_token пользователя. Есть и uservks. Таблицы я разделил. Можно и в одной, но не стал. Мало ли какие ещё настройки по API придется вписывать.
          4. ksort нужен. Это я параметры сейчас составил в алфавитном порядке. Но если их не отсортировать, то мы получим всё ту же ошибку 104.
          5. foreach в данном случае быстро и просто решает задачу — создать строку из параметров ключ=значение (см. документацию APIOK)
          6. sekret_key. Это наименование из мануала в ВК. Здесь для наглядности. Вообще я за очень короткий код и минимум переменных. Но на этапе поиска решения иной раз приходится идти на жертвы.
          7. Я аргументы убрал почти со всех функций. У меня много асинхронных запросов на api маршруты. И для проекта есть своя система управления правами. Короче в моем случае все аргументы передаются через $request, а middlewear определяет принадлежность токена пользователю, какие права у группы пользователя на конкретный маршрут (1 разрешено всё, 2 операции только со своей информацией, 3 запрещено, опять же если в БД как-то заявлены права на маршрут, но для конкретной группы пользователей ничего не написано, то автоматом права 3 — запрещено). В моем случае — это одно из решений. Бюджет заказа не скажу, что большой, поэтому делаю то, что быстро, что работает, попутно оставляю комментарии.

          Но Вы дали мне вполне ценную информацию и замечания. И я несомненно учусть, в т.ч. благодаря Вам.


  1. Vjaka
    23.09.2019 13:24

    Насколько я знаю, при вызове методов API ок с помощью https подпись больше не требуется (но валидируется, если передана). Узнаю детали, почему информация об этом опубликована только для bot api методов


    1. maxsharun Автор
      23.09.2019 13:24

      Возможно и так, но в в моих запросах ОК требовал подпись


      1. Vjaka
        23.09.2019 13:42

        Уточнил. Подпись требуется при использовании OAUTH сессии. Если приложение/игра работает внутри портала ОК, то должно работать и без подписи