Страницы

Поиск по вопросам

Показаны сообщения с ярлыком vkontakte-api. Показать все сообщения
Показаны сообщения с ярлыком vkontakte-api. Показать все сообщения

суббота, 11 апреля 2020 г.

Как получить имя и фамилию пользователя VK без дополнительного запроса?

#вконтакте #vkontakte_api #oauth

                    
Возник такой вопрос: сделать так, чтобы vk при авторизации через oauth 2, помимо
id, сразу возвращал имя и фамилию пользователя?
Попробовал в настройках указать первый запрос к api:
users.get?user_id={viewer_id}&v=5.25
Но, похоже, с oauth это не работает. Есть другие варианты, не делая дополнительный
запрос к api со стороны сервера, заставить vk возвращать вместе с id имя и фамилию?    


Ответы

Ответ 1



Я так понимаю, что приемлемо сделать правильный первый запрос к API, раз есть id пользователя: $.ajax({ url: "https://api.vk.com/method/users.get", data: { user_ids: '1', v: "5.26" }, dataType: "jsonp", success: function (e) {alert(e.response[0].first_name + ' ' + e.response[0].last_name);} });

четверг, 9 апреля 2020 г.

Хранение авторизации Vkontakte в android приложении

#android #android_sdk #vkontakte_api #вконтакте

                    
Необходима авторизация через Вконтакте в приложении. Как лучше всего хранить полученный
токен авторизации в приложении и как подставлять его автоматически если он еще не устарел?
SharedPreference и SQLite небезопасны. Есть возможность хранить во внешней MySQL базе.
    


Ответы

Ответ 1



SharedPreference с MODE_PRIVATE http://developer.android.com/reference/android/content/Context.html#MODE_PRIVATE будет доступно только для текущего приложения Если это кажется недостаточно безопасным можно использовать реализацию с шифрованием https://github.com/scottyab/secure-preferences

Json Serialization, как правильно достать данные из гетерогенного массива?

#c_sharp #json #vkontakte_api

                    
Хочу вытянуть ID групп ВК, у которых в названии есть буква "а".
Отправляю запрос и получаю ответ:

{  
    "response":[  
        747369,
        {  
            "gid":60386075,
            "name":"Мың бір оқиға [K-POP]",
            "screen_name":"kazanonim",
            "is_closed":0,
            "type":"page",
            "is_admin":0,
            "is_member":0,
            "photo":"http:\/\/cs631116.vk.me\/v631116892\/bfa5\/mv5UyEdPfz8.jpg",
            "photo_medium":"http:\/\/cs631116.vk.me\/v631116892\/bfa4\/EEzzOElvS78.jpg",
            "photo_big":"http:\/\/cs631116.vk.me\/v631116892\/bfa2\/ktxcZIgNLVU.jpg"
        },
        ....
    ]
}


Но дальше у меня проблема, не могу достать правильно данные, если я делаю как в коде
ниже, то мне мешает : 747369 - количество групп у которых есть буква "а" в названии.
Я не знаю как обработать его, в результате получаю ошибку 


  newtonsoft.json.jsonserializationexception error converting value 747369 ...


public void Reader2(string r)
{
     Json2.RootObject groups = JsonConvert.DeserializeObject(r);
     foreach (var c in groups.items)
        {
          textBox1.Text += c.screen_name  + Environment.NewLine;
        }
}


public class Json2
{
    public class Item
    {
        public int id { get; set; }
        public string name { get; set; }
        public string screen_name { get; set; }
        public int is_closed { get; set; }
        public string type { get; set; }
        public int is_admin { get; set; }
        public int is_member { get; set; }
        public string photo_50 { get; set; }
        public string photo_100 { get; set; }
        public string photo_200 { get; set; }
    }
     public class RootObject
    {
        public List items { get; set; }
    }
}


Попробовал через http://json2csharp.com/ создать класс:

public class RootObject
{
    public List response { get; set; }
}

Json2.RootObject groups = JsonConvert.DeserializeObject(r);
foreach (var c in groups.response)
{
    textBox1.Text += c + Environment.NewLine;
}


И вот результат:

{
  "gid": 60386075,
  "name": "Мың бір оқиға [K-POP]",
  "screen_name": "kazanonim",
  "is_closed": 0,
  "type": "page",
  "is_admin": 0,
  "is_member": 0,
  "photo": "http://cs631116.vk.me/v631116892/bfa5/mv5UyEdPfz8.jpg",
  "photo_medium": "http://cs631116.vk.me/v631116892/bfa4/EEzzOElvS78.jpg",
  "photo_big": "http://cs631116.vk.me/v631116892/bfa2/ktxcZIgNLVU.jpg"
}


Как достать теперь из него данные?
Или если возможно, то как можно избежать ошибку в первом случае?
    


Ответы

Ответ 1



Необходимые свойства можно найти с помощью JSONPath // #r "\Newtonsoft.Json\6.0.3\lib\net45\Newtonsoft.Json.dll" using Newtonsoft.Json; using Newtonsoft.Json.Linq; var json = System.IO.File.ReadAllText(@"C:\Temp\json.txt"); var jo = JObject.Parse(json); foreach (var o in jo.SelectTokens("..screen_name")) // JSONPath if (o.ToString().Contains("a")) Console.WriteLine(o.Parent.Parent["gid"] + " " + o); Результат 60386075 kazanonim Для следующего json в файле C:\Temp\json.txt { "response":[ 747369, { "gid":60386075, "name":"Мың бір оқиға [K-POP]", "screen_name":"kazanonim", "is_closed":0, "type":"page", "is_admin":0, "is_member":0, "photo":"http:\/\/cs631116.vk.me\/v631116892\/bfa5\/mv5UyEdPfz8.jpg", "photo_medium":"http:\/\/cs631116.vk.me\/v631116892\/bfa4\/EEzzOElvS78.jpg", "photo_big":"http:\/\/cs631116.vk.me\/v631116892\/bfa2\/ktxcZIgNLVU.jpg" } ] }

Ответ 2



Перед десериализацией можно получить ответ сервера в виде дерева и отредактировать. Примерно так: var jroot = JObject.Parse(r); var jresponse = (JArray)jroot["response"]; jresponce.RemoveAt(0); var root = jroot.ToObject(); Если же это число также нужно, то можно поступить так: public class RootObject { public List response { get; set; } } // ... Json2.RootObject groups = JsonConvert.DeserializeObject(r); foreach (var c in groups.response) { if (c is JObject) { var item = c.ToObject(); // ... } if (c is JValue) { var count = (int)c; // ... } }

вторник, 31 марта 2020 г.

Как получить количество записей пользователя группы с помощью VK API

#php #vkontakte_api


Есть группа в контакте, в ней около 20К записей. Нужно получить общее количество
записей от одного пользователя с помощью API. Из документации я понял что такого метода
нет, но можно сделать таким образом: при добавлении новой записи на стену группы, просто
записывать данные автора и кол-во его записей в базу, а в последующем просто увеличивать
счетчик. Но это не совсем оптимальный способ. Возможно есть более простые решения,
подскажите!?
    


Ответы

Ответ 1



Если под "записями" подразумеваются посты (не комментарии!) то с помощью метода wall.get можно брать по 100 постов со стены, а если использовать execute то в одном запросе можно забирать 25*100=2500 постов, соответственно 20К постов в группе это меньше 10 запросов. Алгоритм возможен следующий - первый раз снимаем все посты и записываем в БД пары пост/автор и потом с некой периодичностью снимаем 2500 последний постов. Ну и далее простейший подсчет постов автора в БД.

воскресенье, 8 марта 2020 г.

Как получить больше 1000 людей, лайкнувших пост, через VK API?

#php #vkontakte_api #like


Пытаюсь получить всех пользователей, кто поставил лайк под записью, через likes.getList.
Но есть ограничение: получить разом можно только 1000 человек. А как получить всех
пользователей, если таковых является, например, 3500?

Вот так я получаю список первой 1000 лайкнувших:

$res = file_get_contents('https://api.vk.com/method/likes.getList?t‌​ype=post&owner_id=-1‌​111&item_id=111&exte‌​nded=1&count=1000&of‌​fset=0'); 
$resp = json_decode($res, true); 
foreach($resp['response']['items'] as $val) { 
    echo $val['first_name'] . "
\n"; }


Ответы

Ответ 1



Небольшая функция, которая работает рекурсивно, каждый раз смещая параметр offset на нужную величину (на offset в запросе + количество уже выбранных юзеров count) пока не придет пустой ответ. Это значит, что пора обрывать рекурсию. Однако может еще прийти ответ error вместо response. Но эта обработка на вашей совести)) Еще также указывайте версию API, а то может вернуть не те данные, которые ожидаете или вообще ошибку вернуть. $count = 1000; $offset = 0; $apiVersion = 5.60; $result = []; getLikesData($result, $count, $offset, $apiVersion); function getLikesData(&$output, $count, $offset, $apiVersion) { $query = 'https://api.vk.com/method/likes.getList?type=post&owner_id=-1‌​111&item_id=111&extended=1&friends_only=0&v='.$apiVersion.'&count='.$count.'&offset='.$offset; $resp = json_decode(file_get_contents($query), true); if (!$resp['response']) return; $items = $resp['response']['items']; if (empty($items)) return; foreach ($items as $item) { $output[] = $item; } getLikesData($output, $count, $offset + $count, $apiVersion); } echo '
';
print_r($result);
echo '
'; В функции находится цикл для заполнения результирующего массива по порядку. Если вместо этого воспользоваться array_push, то будет отрабатывать быстрее. Однако в результирующем наборе будет массив массивов. Это я к чему... Выбирайте что нужно: меньшая скорость, но по порядку или большая скорость, но потом при выводе придется организовывать двойной цикл.

Ответ 2



Схематично (параметр offset описан в документации): offset = 0; while( likes.getList(type, owner_id, item_id, count, offset) != ERROR ) { users = [сколько_юзеров_получили]; if( users == 0 ) { /* всё, больше юзеров нет */ break; } offset += users; }

суббота, 7 марта 2020 г.

Не могу получить популярные аудиозаписи VK

#android #vkontakte_api #аудио


получаю токен юзера и сразу пытаюсь получить 

VKRequest audios = VKApi.audio().getPopular();


И получаю error 15 :( Читал, что сторонние разработчики не могут работать с аудио
но как же тогда работает это  

Что я не так делаю? И вообще почему для получения популярных аудиозаписей нужен токен?
Мне их надо получать даже если пользователь не залогинился.
    


Ответы

Ответ 1



PROFIT! Я это сделал! Декомпилировал одно приложение и узнал какой сейчас используется хак. main.xml MainActivity.java public class MainActivity extends Activity { public class VkontakteWebViewClient extends WebViewClient { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); MainActivity.this.parseUrl(url); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); WebView kateWV = (WebView)findViewById(R.id.kateWebView); kateWV.getSettings().setJavaScriptEnabled(true); kateWV.clearCache(true); kateWV.setWebViewClient(new VkontakteWebViewClient()); CookieSyncManager.createInstance(this); CookieManager.getInstance().removeAllCookie(); kateWV.loadUrl(Auth.getUrl("2685278", Auth.getSettings())); } public void parseUrl(String url){ if (url != null) { try { if (url.startsWith(Auth.redirect_url)) { if (!url.contains("error=")) { String[] auth = Auth.parseRedirectUrl(url); saveTokenToSharedPreferences(getApplicationContext(), Auth.VK_SDK_ACCESS, "scope=groups,audio,offline&https_required=1&expires_in=0&access_token=" + auth[0] + "&user_id=" + Long.parseLong(auth[1])); } startActivity(new Intent(MainActivity.this, AudioActivity.class)); finish(); } } catch (Exception e) { e.printStackTrace(); } } } public void saveTokenToSharedPreferences(Context ctx, String tokenKey, String code) { SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); edit.putString(tokenKey, code); edit.apply(); } } Auth.java public class Auth { public static final String VK_SDK_ACCESS = "VK_SDK_ACCESS_TOKEN_PLEASE_DONT_TOUCH"; public static String redirect_url; static { redirect_url = "https://oauth.vk.com/blank.html"; } public static String getUrl(String api_id, String settings) { return "https://oauth.vk.com/authorize?client_id=" + api_id + "&display=mobile&scope=" + settings + "&redirect_uri=" + URLEncoder.encode(redirect_url) + "&response_type=token" + "&v=" + "5.53"; } public static String getSettings() { return "notify,friends,photos,audio,video,docs,status,notes,pages,wall,groups,messages,offline,notifications"; } public static String[] parseRedirectUrl(String url) throws Exception { String access_token = Utils.extractPattern(url, "access_token=(.*?)&"); String user_id = Utils.extractPattern(url, "user_id=(\\d*)"); if (user_id == null || user_id.length() == 0 || access_token == null || access_token.length() == 0) { throw new Exception("Failed to parse redirect url " + url); } return new String[]{access_token, user_id}; } } В итоге после авторизации через WebView в preferences будет сохранен токен scope=groups,audio,offline&https_required=1&expires_in=0&access_token=тут_токен_юзера&user_id=тут_id_юзера Далее можно работать с API VK. Лично у меня происходит переход в AudioActivity. Примерный код VKRequest request = VkApi.audio().getPopular(); request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { //выводим json с музыкой в логи Log.d("vkmusic", response.responseString); } @Override public void onError(VKError error){ Log.d("err", error.toString()); } }); request.start(); Ну и все, можно юзать. Результат

Ответ 2



И вот еще класс Utils class Utils { public static String extractPattern(String string, String pattern) { Pattern searchPattern = Pattern.compile(pattern); Matcher matcher = searchPattern.matcher(string); Log.d("pattern found - ", matcher.find() ? ("yes" + matcher.group(1)) : "no"); return matcher.group(1); } }

пятница, 6 марта 2020 г.

Где можно найти документацию по VK Streaming API?

#vkontakte_api #вконтакте


С лета этого года ВКонтакте ужесточает лимиты на вызов методов newsfeed.search, wall.search
и wall.get и предлагает использовать их новый Streaming API для интерактивного получения
данных по этим методам, но нигде нет информации по использованию этого API. Кто знает
где можно почитать документацию по Streaming API (в разделе для разработчиков у них
пока ничего нет)?

Также интересуют данные по новым лимитам. Пока есть информация по количественному
ограничению вызова метода newsfeed.search (до 100.000 запросов в сутки) с 07.06.2017.
Кто-нибудь знает про другие ограничения?

Судя по новостям, разработчики VK планируют выпустить несколько версий Streaming
API (основную и "расширенную"). Кто знает чем они будут отличаться (сейчас есть только
информация, что "расширенная" версия будет выдавать "100% данных")?

Сама новость в Roadmap:
https://vk.com/dev/data_limits
    


Ответы

Ответ 1



Появилась документация по Streaming API: https://vk.com/dev/streaming_api_docs Но там реально жесть, в базовой версии максимальное количество запросов (правил), по которым поступают данные = 10 штук, в ответе выдается 1% от всей доступной информации (говоря русским языком не выдается практически ничего)). Также сервер должен держать постоянное соединение через WebSockets, которое сервер может произвольно разорвать по прошествии определенного времени (в общем, это весьма неудобно). Из текущего, с 21.06.2017 начинают действовать следующие ограничения по методам newsfeed.search, wall.search и wall.get: метод newsfeed.search можно вызывать не более 25000 раз в сутки; метод wall.search можно вызывать не более 2500 раз в сутки; метод wall.get можно вызывать не более 500000 раз в сутки. Из личной переписки с разработчиками стало ясно, что в итоге сильно урежут суточное количество запросов, будет гораздо ниже вышеуказанных. Пока не ясно, будут ли вводить review (ручную модерацию) приложений по типу instagram, но в свете "борьбы со злоупотреблениями обхода ограничений" мне это видится единственным реальным шагом со стороны разработчиков VK, чтобы эти "злоупотребления" прекратить.

вторник, 25 февраля 2020 г.

Алгоритм регистрации и авторизации через социальные сети

#oauth #php #vkontakte_api #авторизация #регистрация


Добрый вечер.
Расскажите, пожалуйста, как организовать сабж. Что хранить в базе, что держать в
куках и как организовать авторизацию. Можно без кода - на словах. На всякий случай
- пишу на PHP.
Заранее спасибо.    


Ответы

Ответ 1



Пришёл новый чел, авторизуете его через ВК (см. Виджет Авторизации), получая от ВК напрямую в ваш сервер подтверждение, что этот клиент действительно Вася с ID 12345. Генерите для Васи запись у себя в БД, в том числе некий уникальный ключ, а ему ставите куки с этим ключем. В следующий раз придёт - если есть куки, соотв. записи в вашей БД - это видимо, Вася.

Ответ 2



Воспользуйтесь уже готовыми решениями, например http://ulogin.ru/constructor.php На странице справки, в разделе "Настройки виджета" -> "Информация о пользователе" найдете все данные, которые можно выудить из соц сети про данного пользователя, от имени, почты, до пола и возраста (если конечно есть такие). Дальше - как при обычной авторизации через логин форму - ставите куку после авторизации, и понеслась. Или делаете что-то типа авторегистрации (минимально необходимые данные уже ведь есть) и если чего-то нехватает, можете перебрасывать пользователя на профиль и пусть дозаполняет то, что осталось в неведении. При этом, раз пользователь фактически не вводит пароль, то можно ему сгенерить какой-нибудь достаточно стойкий из вида "!k2j$4#(Dk)543\bls"

понедельник, 24 февраля 2020 г.

что VkNet - VkApi - проблема с заливанием картинки для MarketAlbum

#c_sharp #vkontakte_api #вконтакте


Есть простенький метод для заливания картинки под альбом Маркета в ВК:

private VkNet.Model.Attachments.Photo AttachPicToAlbum(string path)
{
    var uploadServer = VkApi.Photo.GetMarketAlbumUploadServer(_group.Id);

    var wc = new WebClient();
    var responseFile = Encoding.ASCII.GetString(wc.UploadFile(uploadServer.UploadUrl,
path));

    var response = VkApi.Photo.SaveMarketAlbumPhoto(_group.Id, responseFile);
    return response[0];
}


По факту response приходит пустым. 0 обьектов внути.

Url = "https://api.vk.com/method/photos.saveMarketAlbumPhoto?group_id=129372114&photo=eyJwaG90byI6IjEiLCJid2FjdCI6Im1hcmtldF9hbGJ1bSIsInNlcnZlciI6NjM3NzE5LCJtaWQiOjE5NDk4NDA2LCJfc2lnIjoiYzI4MmNmNzdkN2E2MDJjOTYzZTE5NjdlMzQ3MzlkODgifQ&server=999&hash=a7d3c00bf6f76b058f917dde50f26f77&v=5.53&access_token=472a2bc9170f98b701fb019a6c3e971ef3a72c79a1c045743b4e4776b391cf105b6269a65fe5d8d4b13cf";
            const string json =
                @"{
                    'response': []
                  }";


Точно такой же код у меня есть для атача картинок в сообщения. Там все работает.
А тут -- не пойму почему нет. =(
На всякий случай код атачча картинок

    private VkNet.Model.Attachments.Document AttachPicToMessage(string path)
    {
        var uploadServer = VkApi.Docs.GetUploadServer();

        var wc = new WebClient();
        var responseFile = Encoding.ASCII.GetString(wc.UploadFile(uploadServer.UploadUrl,
path));

        return VkApi.Docs.Save(responseFile, "png")[0];
    }


Ошибок никаких не выдает.

Есть ли у кого идеи?



Как подсказал RoboNoob есть бага:
https://vk.com/bugs?act=show&id=4717174_65
Но если бы это было через нее, то фикс был бы следующим: (редактирование кода самой
библиотеки):

    [ApiVersion("5.44")]
    public UploadServerInfo GetMarketAlbumUploadServer(long groupId)
    {
        var parameters = new VkParameters {
            { "group_id", groupId },
            { "https", 1 }// ДОБАВЛЕНА ДАННАЯ СТРОКА
        };

        return _vk.Call("photos.getMarketAlbumUploadServer", parameters);
    }


По факту фикс не сработал, проблема осталась как есть. Значит, делаю вывод что проблема
в другом.

Так же автор бага[и багфикса описаного] подтвердил что даная бага здесь не при чем.
    


Ответы

Ответ 1



В баг-трекере ВК есть информация о баге самого ВК по поводу заливания фоток на сервер по API https://vk.com/bugs?act=show&id=4717174_65

пятница, 21 февраля 2020 г.

Javascript: как удалять результат выполнения функции при следующем вызове

#javascript #vkontakte_api #адаптивность


Прикрутил на сайте виджет ВК "Сообщества". Стояла задача сделать его адаптивным,
при этом ширина должна не просто подстраиваться под родительский блок при перезагрузке
страницы, а именно тянуться при изменении размера экрана.

Решил использовать window.onresize:





Задача с адаптивностью решена, но появилась проблема: при каждом изменении размера экрана функция VK.Widgets.Group вызывается с новой шириной, при этом прежний блок с виджетом (со старыми размерами) остаётся на странице. И так их число растёт... Как сделать, чтобы при изменении размера экрана результаты предыдущего вызова VK.Widgets.Group удалялись?


Ответы

Ответ 1



Вроде работает. Попробуй так. JS Bin


воскресенье, 16 февраля 2020 г.

Javascript: как удалять результат выполнения функции при следующем вызове

#javascript #vkontakte_api #адаптивность


Прикрутил на сайте виджет ВК "Сообщества". Стояла задача сделать его адаптивным,
при этом ширина должна не просто подстраиваться под родительский блок при перезагрузке
страницы, а именно тянуться при изменении размера экрана.

Решил использовать window.onresize:





Задача с адаптивностью решена, но появилась проблема: при каждом изменении размера экрана функция VK.Widgets.Group вызывается с новой шириной, при этом прежний блок с виджетом (со старыми размерами) остаётся на странице. И так их число растёт... Как сделать, чтобы при изменении размера экрана результаты предыдущего вызова VK.Widgets.Group удалялись?


Ответы

Ответ 1



Вроде работает. Попробуй так. JS Bin


понедельник, 10 февраля 2020 г.

Ошибка Json при обращении к vk: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

#python #json #vkontakte_api


Код:

import requests
result = requests.get('https://vk.com/dev/users.get',params={'user_ids':1})
print(result.json())


Вывод:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)


В чем проблема?
    


Ответы

Ответ 1



Вы выполняете запрос не в API, а на страницу документации. Запрос в API выглядит примерно так: https://api.vk.com/method/users.get?user_id=210700286&v=5.52 Ответ: { "response": [ { "id": 210700286, "first_name": "Lindsey", "last_name": "Stirling" } ] }

суббота, 8 февраля 2020 г.

Цикл внутри try…catch, как написать красивый код?

#c_sharp #исключения #vkontakte_api #captcha


Код примерно следующий:

    public void AntigateAuthorize(int appId, string email, string password, Settings
settings, string antigateKey)
    {
        var authorizationCompleted = false;

        try
        {
            Authorize(appId, email, password, settings);
            authorizationCompleted = true;
        }
        catch (CaptchaNeededException exception)
        {
            var captchaSid = exception.Sid;
            var image = GetImageFromUrl(exception.Img.AbsoluteUri);

            try
            {
                const int numberOfAuthorizationRetries = 5;
                var retryAuthorizationsCount = numberOfAuthorizationRetries;
                do
                {
                    var anticaptcha = new AntiCaptcha(antigateKey);
                    try
                    {
                        var captchaKey = anticaptcha?.GetAnswer(image);

                        if (captchaKey != null)
                        {
                            Authorize(appId, email, password, settings, captchaSid,
captchaKey);
                            authorizationCompleted = true;
                        }
                        else
                        {
                            Logger.Error("Ответ от сервера Antigate не получен.");
                        }
                    }
                    catch (CaptchaNeededException)
                    {
                        Logger.Trace("Капча распознана неверно.");
                        anticaptcha.FalseCaptcha();
                        retryAuthorizationsCount--;
                        if (retryAuthorizationsCount == 0)
                        {
                            Logger.Trace("Заданное количество попыток авторизации
исчерпано.");
                            throw;
                        }
                    }
                } while (!authorizationCompleted && retryAuthorizationsCount > 0);
            }
            catch (AntigateErrorException aee)
            {
                Logger.Error("Ошибка Antigate: {0}", aee.Message);
            }
        }
        catch (VkApiAuthorizationException)
        {
            Logger.Error("Не удалось авторизовать приложение. Неправильный логин
или пароль.");
        }
        catch (VkApiException)
        {
            Logger.Error("В процессе попытки авторизации произошла неизвестная ошибка.");
        }
    }

    public static Image GetImageFromUrl(string url)
    {
        using (var stream = ((HttpWebResponse)((HttpWebRequest)WebRequest.Create(url)).GetResponse()).GetResponseStream())
            return stream == null ? null : Image.FromStream(stream);
    }


Проблема в том, если обрабатывать ошибку CaptchaNeededException однократно, то всё
получается, а если в цикле - получается плохо и некрасиво.
    


Ответы

Ответ 1



Можно попробовать разбить на мелкие функции. Например, так: public void AntigateAuthorize( int appId, string email, string password, Settings settings, string antigateKey) { try { try { Authorize(appId, email, password, settings); } catch (CaptchaNeededException exception) { AuthorizeWithCaptcha(appId, email, password, settings, exception); } } catch (AntigateErrorException) { // ? } catch (VkApiAuthorizationException) { Logger.Error( "Не удалось авторизовать приложение. Неправильный логин или пароль."); } catch (VkApiException) { Logger.Error( "В процессе попытки авторизации произошла неизвестная ошибка."); } } Вспомогательные функции: private void AuthorizeWithCaptchaOnceImpl( int appId, string email, string password, Settings settings, CaptchaNeededException reason, AntiCaptcha anticaptcha) { var captchaSid = reason.Sid; var image = GetImageFromUrl(reason.Img.AbsoluteUri); try { var captchaKey = anticaptcha.GetAnswer(image); if (captchaKey == null) { Logger.Error("Ответ от сервера Antigate не получен."); throw new NoAntigateResponceException(); } Authorize(appId, email, password, settings, captchaSid, captchaKey); } catch (CaptchaNeededException) { Logger.Trace("Капча распознана неверно."); anticaptcha.FalseCaptcha(); throw; } } void AuthorizeWithCaptcha( int appId, string email, string password, Settings settings, CaptchaNeededException exception) { try { var anticaptcha = new AntiCaptcha(antigateKey); const int numberOfAuthorizationRetries = 5; CaptchaNeededException currentException = exception; for (int retry = 0; retry < numberOfAuthorizationRetries; retry++) { try { AuthorizeWithCaptchaOnceImpl( appId, email, password, settings, currentException, anticaptcha); return; } catch (CaptchaNeededException ex) { currentException = ex; } catch (NoAntigateResponceException ex) { // nothing to do, just retry } } throw new RetryNumberExceededException(); } catch (AntigateErrorException aee) { Logger.Error("Ошибка Antigate: {0}", aee.Message); throw; } } Заметьте, что я немного поменял логику. Например, после неудачного распознавания капчи теперь картинка меняется. Также, в результате превышения разрешённого количества попыток распознавания выбрасывается исключение (хотя, возможно, вы захотите вернуть bool из функции).

Ответ 2



Есть такая рекомендация: для упрощения читаемости кода блоки if/try/catch/finally/for/foreach/while должны содержать как можно меньше кода, в идеале -- вызов одного метода. Еще одна рекомендация: соблюдать минимальную вложенность кода. Например, у вас есть код: public void Foo() { try { FooInternal(); } catch (Exception1) { ... } catch (Exception2) { ... } } Цель этого метода: вызов некоторого кода и обработка ошибок. При этом метод не перегружен подробностями о том, какой код вызывается. В свою очередь метод FooInternal не будет перегружен информацией о возможных ошибках и их обработке. К вашему коду. Для внешнего блока try эти рекомендации у вас соблюдены: try { Authorize(appId, email, password, settings); authorizationCompleted = true; } Теперь осталось вынести содержимое catch (CaptchaNeededException exception) в отдельный метод. В нем -- в свою очередь вынести содержимое блоков try/catch в отдельные методы. От развесистой структуры блоков try/catch, к сожалению, совсем избавиться не удастся -- такова логика.

Ответ 3



Я бы вынес логику отдельно, т.к. в коде присутствуют другие методы не отвечающие за авторизацию, нет следования принципу SRP и не будет reuse. К примеру класс class Antigate Service, метод TryAuthenticate который будет возвращать bool и out AuthenticationResult. По крайней мере мне так видится, избавление в будущем от дублирования И вообще следует избегать ветвления кода(даже если это try/catch)

Ответ 4



Переделал сейчас примерно следующим образом (убрал для примера лишние catch): public void AuthorizeEx( int appId, string email, string password, Settings settings, int captchaRecognitionCount = MaxCaptchaRecognitionCount, AntiCaptcha antiCaptcha = null, CaptchaNeededException previousException = null) { if (captchaRecognitionCount < 0) return; var captchaSid = previousException?.Sid; var captchaKey = previousException == null ? null : antiCaptcha?.GetAnswer(GetImageFromUrl(previousException?.Img?.AbsoluteUri)); try { Authorize(appId, email, password, settings, captchaSid, captchaKey); } catch (CaptchaNeededException currentException) { AuthorizeEx(appId, email, password, settings, captchaRecognitionCount - 1, antiCaptcha, currentException); } } private static Image GetImageFromUrl([CanBeNull] string url) { if (url == null) return null; using (var stream = ((WebRequest.Create(url))?.GetResponse())?.GetResponseStream()) { return stream == null ? null : Image.FromStream(stream); } } Итог: код обработки капчи идёт отдельно, красиво. Из минусов - использование рекурсии, но так ли это страшно, если я ограничиваю её уровень? Если нехорошо, то как развернуть?

пятница, 7 февраля 2020 г.

Отправить сообщение пользователю через VK API из приложения с типом “Веб-сайт”

#vkontakte_api


Есть сайт с уже работающей авторизацией.
Для сайта в VK создали приложение с типом веб-сайт.
Есть необходимость добавить возможность сайту от имени приложения отправлять сообщение
пользователям через VK API.
Возможно ли подобное? Насколько я понял, для приложений типа "сайт" доступны не все
методы.
Если возможно, то какой метод будет правильнее использовать?
    


Ответы

Ответ 1



На сегодня есть следующие варианты отправки сообщения пользователю ВК: от другого пользователя ВК messages.send(); от сообщества в ответ на запрос пользователя – Сообщения для бизнеса; уведомления от приложения secure.sendNotification(); платная отправка SMS secure.sendSMSNotification(). Варианты 1–3 не доступны приложению типа «Сайт». Но можно поступить так: Заведите аккаунт пользователя ВКонтакте, представляющий ваш сайт – вымышленный персонаж, директор, «лицо» сайта. Создайте приложение типа Standalone, и получите для него бессрочный токен с правами messages. Тут придётся всего один раз выполнить процедуру с копированием токена из адресной строки браузера. Зато теперь у вас есть токен, с которым вы сможете из скриптов сайта писать личные сообщения пользователям. Приходить они будут от имени того аккаунта. Скорее всего, пользователи будут что-то писать в ответ – обрабатывайте их ответы. Наладьте какой-то механизм на случай если токен вдруг перестанет работать – чтобы вы тут же узнали и выпустили новый.

Ответ 2



Вам нужно для такого получить access_token вручную, иначе не будет у него нужных прав. Для этого перейти по ссылке: http://oauth.vk.com/oauth/authorize?redirect_uri=http://oauth.vk.com/blank.html&response_type=token&client_id={app_id}&scope=friends,messages,offline В строке адреса скопировать access_token и использовать его для отправки сообщений: https://api.vkontakte.ru/method/messages.send?user_id={receiver_vk_id}&message={vk_msg}&title={vk_msg_title}&access_token={received_access_token} P.S. Параметр offline дает токену неограниченное время существования.

понедельник, 3 февраля 2020 г.

Получить видео VKontakte Api

#вконтакте #ios #vkontakte_api #видео


Привет всем) такая проблемка - не могу получить ссылку на видео.  Есть access_key,
vid, owner_id. Все это я получаю из newsfeed. Причем, на странице документации ВК,
если в поле для проверки запроса вписать просто owner_id, то без проблем выдает весь
список видеозаписей данного пользователя/группы, но если установить videos, то приходит
ответ типа

response: {
count: 1,
items: []
}

т.е., items - пустой. Причем я пробовал и с access_key и без него. 
Кто такое уже делал, подскажите, что у меня не так?    


Ответы

Ответ 1



Все, разобрался. В русской версии документации API неполное описание. Пользуйтесь английской версией!

Ответ 2



Обычно ВК не отдает прямой ссылки на видео Это потому-что используете заголовок запроса "User-Agent", если он пуст то тогда и будут прямые ссылки в files. Сделайте запрос типа: https://api.vk.com/method/video.get?videos=-53956136_169543800&access_token=%access_token% с пустым заголовком "User-Agent", выйдет: { 'response' : [1, { 'duration' : 1452, 'vid' : 169543800, 'views' : 4790, 'owner_id' : -53956136, 'player' : 'https://vk.com/video_ext.php?oid=-53956136&id=169543800&hash=06da65ec2f1a6d00', 'date' : 1408830421, 'link' : 'video-53956136_169543800', 'files' : { 'mp4_240' : 'https://cs543208.vk.me/u222975331/videos/fd8d6c3d4d.240.mp4?extra=d1xg726trlMQIwAZ4X8NTUJRI2kk-uw9TJ66bWZtq_odwiDxYverCALb8PNb_z-zjbPhvX07ftxnZRXZ-li8XiFKJZ_oEJnbrPVPqLrKUiFM9J1FfYFEEm3c5SfRXRDSSU29k7QTkS_7uTxg', 'mp4_720' : 'https://cs543208.vk.me/u222975331/videos/fd8d6c3d4d.720.mp4?extra=d1xg726trlMQIwAZ4X8NTUJRI2kk-uw9TJ66bWZtq_odwiDxYverCALb8PNb_z-zjbPhvX07ftxnZRXZ-li8XiFKJZ_oEJnbrPVPqLrKUiFM9J1FfYFEEm3c5SfRXRDSSU29k7QTkS_7uTxg', 'mp4_360' : 'https://cs543208.vk.me/u222975331/videos/fd8d6c3d4d.360.mp4?extra=d1xg726trlMQIwAZ4X8NTUJRI2kk-uw9TJ66bWZtq_odwiDxYverCALb8PNb_z-zjbPhvX07ftxnZRXZ-li8XiFKJZ_oEJnbrPVPqLrKUiFM9J1FfYFEEm3c5SfRXRDSSU29k7QTkS_7uTxg', 'mp4_480' : 'https://cs543208.vk.me/u222975331/videos/fd8d6c3d4d.480.mp4?extra=d1xg726trlMQIwAZ4X8NTUJRI2kk-uw9TJ66bWZtq_odwiDxYverCALb8PNb_z-zjbPhvX07ftxnZRXZ-li8XiFKJZ_oEJnbrPVPqLrKUiFM9J1FfYFEEm3c5SfRXRDSSU29k7QTkS_7uTxg' }, 'description' : 'Видео предоставлено группой [club53956136|AniZUR Аниме на любой вкус]

Следующая серия: http://vk.com/video-53956136_169543833', 'comments' : 5, 'title' : 'Hunter x Hunter Remake / Хантер x Хантер - 2 сезон 66 серия [Озвучка: Ancord]', 'image' : 'http://cs543208.vk.me/u222975331/video/m_1a4f8d0d.jpg', 'image_medium' : 'http://cs543208.vk.me/u222975331/video/l_7bbad3fc.jpg' } ] } Если нужен постоянный access_token(может быть опасно) вот: https://oauth.vk.com/authorize?client_id=3087106&scope=wall,offline&redirect_uri=http://api.vk.com/blank.html&display=page&response_type=token !Обновлено Новый ВК API теперь требует новый обязательный параметр: версию API: v=5.73(Актуальная на данный момент). И полная ссылка будет выглядеть примерно так: https://api.vk.com/method/video.get?videos=-53956136_169543800&access_token=%access_token%&v=5.73

Ответ 3



смотри, вот такой запрос: https://api.vk.com/method/video.get?v=5.12&videos=71057340_167884774_6e2f5cee5c04b2b898&access_token=myaccesstoken получаю такой ответ: { response = { count = 1; items = ( { comments = 4; date = 1395082963; description = "::::::\U0418\U041d\U0424\U041e\U0420\U041c\U0410\U0426\U0418\U041e\U041d\U041d\U0410\U042f \U0412\U041e\U0419\U041d\U0410:::::::\n:::::http://vkontakte.ru/club4121067:::::"; duration = 64; id = 167884774; "owner_id" = 71057340; "photo_130" = "http://cs540303.vk.me/u12911501/video/s_f1c9b9d6.jpg"; "photo_320" = "http://cs540303.vk.me/u12911501/video/l_074712cb.jpg"; player = "http://vk.com/video_ext.php?oid=71057340&id=167884774&hash=32fa35ec6b845a99"; title = "\U041e\U0442\U0434\U044b\U0445 \U0432 \U041a\U0440\U044b\U043c\U0443 - 2014 \U0423\U043a\U0440\U0430\U0438\U043d\U0430. "; views = 707; } ); }; } Обычно ВК не отдает прямой ссылки на видео, хотя иногда есть исключения (они в словаре files должны быть). В таком случае приходиться пользоваться ссылкой на плеер и открывать ее в браузере.

Ответ 4



Это потому-что используете заголовок запроса "User-Agent", если он пуст то тогда и будут прямые ссылки в files. На данный момент не работает. Доступ к секции "files" возможен лишь при авторизации как доверенное приложение, либо парсингом страницы https://vk.com/dev/video.get

Ответ 5



Возможно дело в owner_id видео. Параметр owner_id можно взять из данных newsfeed.get. То есть owner_id видео может отличаться от source_id поста, которому принадлежит видео, так как может быть перепост видео другой группой или пользователем.

воскресенье, 2 февраля 2020 г.

Как вывести полученный ответ в TextView?

#java #android #vkontakte_api


Я делаю запрос на получение информации о пользователе(имя фамилия):

VKRequest username = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS,"first_name,last_name"));


И как мне вывести полученный ответ в TextView?

Помогите пожалуйста, я ещё новичок в программировании и на stackoverflow впервые:)
    


Ответы

Ответ 1



Если я правильно понимаю, то вы делаете запрос на получение юзеров, тоесть в ваш VKRequest username приходит список пользователей, я полагаю что то похожее на это: response: [{ id: 210700286, first_name: 'Lindsey', last_name: 'Stirling', city: { id: 5331, title: 'Los Angeles' }, photo_50: 'https://pp.vk.me/...f6e/4-funfNRMwg.jpg', verified: 1 }] Возможно ваш запрос должен выглядеть так final VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS, "first_name,last_name")); request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { VKApiUserFull user = ((VKList)response.parsedModel).get(0); //устанавливаем имя пользователя в TextView yourTextView.setText(user.first_name); } });

Ответ 2



Из Request username, Вам нужно достать в String first_name и last_name потом передать их в TextView //находите textView TextView textView = (TextView) findViewById(R.id.colorText); //устанавливаете нужный текст textView.setText("Ваши string first_name и last_name");

Ответ 3



TextView tvUserName = (TextView) findViewById(R.id.tvUserName); tvUserName.setText("имя пользователя");

Ответ 4



У себя в приложении данные я получаю так: private void getMeInfo() { VKApi.users().get().executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { try { JSONObject r = response.json.getJSONArray("response").getJSONObject(0); Intent intent = new Intent(); intent.putExtra("provider", "vkontakte"); intent.putExtra("access_token", access_token.accessToken); intent.putExtra("uid", r.getString("id")); intent.putExtra("email", ""); intent.putExtra("first_name", r.getString("first_name")); intent.putExtra("last_name", r.getString("last_name")); setResult(RESULT_OK, intent); } catch (JSONException ignored) { } finish(); } @Override public void onProgress(VKRequest.VKProgressType progressType, long bytesLoaded, long bytesTotal) { super.onProgress(progressType, bytesLoaded, bytesTotal); } @Override public void onError(VKError error) { new AlertDialog.Builder(VkontakteActivity.this).setMessage(error.errorMessage).show(); } @Override public void attemptFailed(VKRequest request, int attemptNumber, int totalAttempts) { } }); }

пятница, 31 января 2020 г.

python загрузка файлов vk

#python #вконтакте #vkontakte_api


Подключил VK API. Необходимо сделать отправку файлов на сервер как о этом рассказано
на этой странице - http://vk.com/dev/upload_files
P.S. Загрузка файлов на стену пользователя

import vk
from time import sleep
import sys
import urllib.request
import urllib.parse
import base64
import requests

vkapi = vk.API(access_token='token', app_id='id')
sleep(0.5)

data = vkapi.photos.getWallUploadServer(user_id="72374405")
DATA_USER_ID = data['user_id']
DATA_ALBUM_ID = data['album_id']
DATA_UPLOAD_URL = data['upload_url']

#with open("1.jpg", "rb") as image_file:
    #fileD = base64.b64encode(image_file.read())


#files = {'1.jpg': open('1.jpg', 'rb')}
#r = requests.post(DATA_UPLOAD_URL, files=files)
#r.status_code == requests.codes.ok
#print(r)
#html = r.read().decode("utf-8")

#dataP = '1.jpg'
dataP = "photo=" + dataP#.encode("ASCII")
response = urllib.request.urlopen(DATA_UPLOAD_URL,dataP)
html = response.read().decode("utf-8")
print (html)


решеткой помечено то, что пробовал но не сработало, либо не подошло.

Вроде как корректно отработался вариант с 

files = {'1.jpg': open('1.jpg', 'rb')}
r = requests.post(DATA_UPLOAD_URL, files=files)
r.status_code == requests.codes.ok
print(r)
#html = r.read().decode("utf-8")


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

В случае успешного завершения кода выхлоп таков: 

{"server":622624,"photo":"[]","hash":"8112ae8847b27fb1cdf678d3d168e6ae"}


То есть загрузка изображения провальная.

Может кто-либо смог или и так знает как загрузить файл на сервер ВК через POST на
Python3. Поделитесь опытом, советом, замечанием. Если что-то в коде непонятно - пишите;
отвечу.
    


Ответы

Ответ 1



Вот мой вариант размещения фотографии на стене сообщества от имени сообщества. Реализован алгоритм, описанный в официальной документации: # Импортируем необходимые модули import vk import requests # Задаём идентификатор группы, токен доступа, картинку и её описание group_id = 'my_group_id' access_token = 'my_access_token' filename = 'image.jpg' caption = 'Some text' # Авторизуемся в VK session = vk.Session(access_token=access_token) vk_api = vk.API(session) # Получаем адрес сервера для загрузки картинки upload_url = vk_api.photos.getWallUploadServer(group_id=group_id)['upload_url'] # Формируем данные параметров для сохранения картинки на сервере request = requests.post(upload_url, files={'photo': open(filename, "rb")}) params = {'server': request.json()['server'], 'photo': request.json()['photo'], 'hash': request.json()['hash'], 'group_id': group_id} # Сохраняем картинку на сервере и получаем её идентификатор photo_id = vk_api.photos.saveWallPhoto(**params)[0]['id'] # Формируем параметры для размещения картинки в группе и публикуем её params = {'attachments': photo_id, 'message': caption, 'owner_id': '-' + group_id, 'from_group': '1'} vk_api.wall.post(**params)

Ответ 2



Есть библиотека vk_api, у нее есть вспомогательный класс для загрузки файлов VkUpload, а у него есть нужный метод photo_wall. Добавляю пример использования (ссылка на полный скрипт с картинками): import vk_api from vk_api import VkUpload login, password = '', '' # Авторизация vk_session = vk_api.VkApi(login, password) vk_session.auth() upload = VkUpload(vk_session) # Для загрузки изображений # Загрузка картинок на сервера вк и получение их id photos = ['1.jpg', '2.jpg'] photo_list = upload.photo_wall(photos) attachment = ','.join('photo{owner_id}_{id}'.format(**item) for item in photo_list) # Добавление записи на стену vk_session.method("wall.post", { 'owner_id': None, # Посылаем себе на стену 'message': 'Test!', 'attachment': attachment, }) Вот так будет выглядеть запись на стене:

Ответ 3



Как-то разобрался :D import vk from time import sleep import sys import urllib.request import urllib.parse import base64 import requests import json vkapi = vk.API(access_token='token', app_id='app_id') sleep(0.5) data = vkapi.photos.getWallUploadServer(user_id="72374405") DATA_USER_ID = data['user_id'] DATA_ALBUM_ID = data['album_id'] DATA_UPLOAD_URL = data['upload_url'] r = requests.post(DATA_UPLOAD_URL, files={'photo': open('1.jpg',"rb")}) r.status_code == requests.codes.ok params = {'server': r.json()['server'], 'photo': r.json()['photo'], 'hash': r.json()['hash']} wallphoto = vkapi.photos.saveWallPhoto(**params) #attachments.append(wallphoto[0]['id']) photoID = wallphoto[0]['id'] params = {'attachments': 'photo' + '72374405_' + str(photoID), 'message': 'Test'} params['owner_id'] = '72374405' print(params) vkapi.wall.post(**params) Позже уже буду разбираться во всем этом коде и делать его более читаемым. Главное что он сейчас работает :)

пятница, 24 января 2020 г.

Вызов метода messages.removeChatUser - VK Android SDK

#android #android_sdk #vkontakte_api #вконтакте #запрос


В VK API существует такой метод как messages.removeChatUser, позволяющий как исключить
пользователя из беседы, так и покинуть беседу самому. Не могу разобраться, как сделать
запрос к этому методу.
Я начинаю запрос таким образом:

VKRequest request = VKApi.messages().


но после точки есть лишь часть методов и нет removeChatUser. На скриншотах видно,
что в wall их достаточно много, а в messages многие методы отсутствуют. Или я что-то
делаю не так?




Я также пытался сделать запрос к методу следующим образом:

VKRequest request = new VKRequest("messages.removeChatUser", VKParameters.from("chat_id",
2, "user_id", мой id));


Но, кажется, такой способ тоже не прошёл.
Помогите сделать запрос к vk.com/dev/messages/removeChatUser.
    


Ответы

Ответ 1



Может быть "капитаню", но первым делом нужно проверить есть ли доступ "Для вызова этого метода Ваше приложение должно иметь права: messages". Часть методов не реализованы в VK SDK Andoid, поэтому для их вызова необходимо делать запросы. Запрос у вас написан правильно. Пришлите код ошибки, который вам приходит

четверг, 23 января 2020 г.

WebView и получение токена

#android #java #webview #вконтакте #vkontakte_api


Здравствуйте, уважаемые знатоки! Наверное, у меня глупый вопрос, но все же.
Я пытаюсь в андроид-приложении прикрутить авторизацию Вконтакте с помощью WebView.
Мне нужно, чтобы при запуске приложения запускалась активити с WebView, где пользоавтель
мог ввести логин, пароль и после чего получить токен. 
Я делаю так: 
public class LoginActivity extends Activity {

    WebView webview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        webview = (WebView) findViewById(R.id.loginWebView);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.clearCache(true);

        webview.setWebViewClient(new WebViewClient());
        CookieSyncManager.createInstance(this);

        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.removeAllCookie();

        String url = "https://oauth.vk.com/authorize?client_id=123&scope=65544"; 
        webview.loadUrl(url);
    }   
}

В итоге открывается активити, на ней WebView отображает диалог авторизации вконтакте.
А вот что делать дальше, я не знаю. ( Как получить этот токен из вебвью?    


Ответы

Ответ 1



@JuniorTwo, тебе нужно для своего WebView установить WebViewClient. У него есть метод-callback onPageStarted (WebView view, String url, Bitmap favicon). Как видишь, вторым параметром придёт ссылка, в которой будет указан токен. А вот выдрать токен из строки - это уже твоя задача. Сам URL будет типа http://REDIRECT_URI#access_token= 533bacf01e11f55b536a565b57531ad114461ae8736d6506a3&expires_in=86400&user_id=8492

Как получить параметры из URL?

#c_sharp #aspnet #vkontakte_api


При авторизации через API ВКонтакте происходит переадресация на URL вида: 


  http://localhost:58821/Auth#access_token=123456712345123451234512345&expires_in=0&user_id=1234567


Обращение к Request.Url.AbsolutePath, Request.Url.AbsoluteUri или Request.RawUrl
даёт только ссылку на хост. Как я могу получить параметры из данного URL?
Upd.: Вероятно проблема в том что адрес и get параметры разделяются символом '#',
а не '?', поэтому параметры получить не получается. Можно ли как-то получить всю строку?
    


Ответы

Ответ 1



Вы ошиблись при выборе типа авторизации - вам необходимо использовать авторизацию предназначенную не для мобильных приложений(клиентскую), а для сайтов(серверную). При этом, необходимо что бы ваш веб-сервер был доступен извне - если не по домену, то хотя бы по какому-то публичному ip. С localhost серверную авторизацию использовать не получится. Если бы это у вас был клиентский код, то можно было бы добавить себе в проект сборку System.Web и использовать код вроде такого: var uri = new Uri("http://localhost:58821/Auth#access_token=123&expires_in=0&user_id=456"); var fragment = uri.Fragment.TrimStart('#'); // access_token=123&expires_in=0&user_id=456 var access_token = HttpUtility.ParseQueryString(fragment).Get("access_token"); // 123 Однако у вас сайт на ASP.NET, и фрагмент(часть Uri начинающаяся с '#') из серверного кода вы не получите никак - клиентом он не передаётся. В вашем случае использовать авторизацию для мобильных устройств нельзя. Точнее конечно можно выпрашивать у пользователя их настоящие логин/пароль, передавать их вместо пользователя, авторизовывать своё приложение, да сохранять токен - но это плохо попахивает, и обязательно вызовет недоверие у пользователей.

Ответ 2



Два дня убил на то, чтобы решить для себя эту проблему, в итоге решил, правда у меня сервер на java но я думаю это не будет особо большой проблемой для понимания. сервер работает на localhost! итак по шагам: 1 - в vk на странице с настройками приложения нужно включить openAPI и в настройках хостов прописать localhost и страницу на которую будет редирект из метода https://oauth.vk.com/authorize в параметре redirect_uri у меня это выглядит вот так 2 - нужно использовать серверную авторизацию а не клиентскую: ссылка на vk.api т.е. для начала нужно получить code getCode { @Override public String getExactMethod() { return "https://oauth.vk.com/authorize?" + "client_id=" + AppProperty.properties.getProperty("vk.client.id") + "&scope=market" + "&display=popup" + "&redirect_uri=" + AppProperty.properties.getProperty("vk.client.uri.local") + "&response_type=code" + "&v=5.60"; } } таким образом в ответе придет код как обчыный get параметр. я его получаю и обрабатываю в фильтре присваивая константе класса 3 - получив код можно отправлять GET запрос на https://oauth.vk.com/access_token используя HttpClient у меня это выглядит вот так: формирование запроса getAccessToken { @Override public String getExactMethod() { return "https://oauth.vk.com/access_token?" + "client_id=" + AppProperty.properties.getProperty("vk.client.id") + "&client_secret=" + AppProperty.properties.getProperty("vk.client.secure.key") + "&redirect_uri=" + AppProperty.properties.getProperty("vk.client.uri.local") + "&code=" + code; } } где code уже присвоен с прошлого этапа, затем я отправляю сам запрос: public Object sendGetRequest(SimpleRequest request) { HttpGet postRequest = new HttpGet(request.getUri()); JSONObject vkApiJsonResponse = null; try (CloseableHttpClient httpClient = HttpClientBuilder.create().build(); CloseableHttpResponse response = httpClient.execute(postRequest)){ String json_string = EntityUtils.toString(response.getEntity()); vkApiJsonResponse = new JSONObject(json_string); } catch (Exception e) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Ошибка.", e.getMessage())); } return vkApiJsonResponse; } в результате которого возвращается JSON объект, который и содержит токен, срок его жизни и user_id, вот пример возвращаемого значения из моего дебага 4 - profit! :) надеюсь это сэкономит кому ни будь пару бессоных ночей/долгих дней. Всем добра!

Ответ 3



Для получения параметров можно использовать QueryString if ( Request.QueryString.AllKeys.Contains("user_id") ) { var id = Request.QueryString["user_id"]; }

Ответ 4



В ASP.NET есть объект Request, который содержит в себе данные, связанные с текущим запросом. В частности, и параметры запроса тоже. Главный способ их получения - это использование свойства QueryString, представляющее собой коллекцию ключей и значений. Можно также использовать индексатор класса Request например так: Request["myparam"] но в случае с индексатором данные по ключу ищутся не только среди параметров url'а, но еще и среди параметров формы, кук и серверных переменных.

Ответ 5



Часть запроса после # (якорь) может не отправляться на сервер. Получить доступ к "якорю" можно на клиенте через javascript и отправить её, например, на сервер для обработки. JavaScript: var hash = window.location.hash.substring(1); JQuery: var hash = $(location).attr('hash').substring(1);