iOSアプリケーションでVkontakte.ru APIを使用する

この短い記事では、Vkontakte APIをiOSプロジェクトに統合する方法を共有したいと思います。

現在、このトピックに関するインターネット上の情報はほとんどなく、私のアドバイスが誰かを助けるかもしれません。 ユーザーデータを取得するだけでなく、写真、テキスト、リンクを壁に配置する方法、およびキャプチャ入力のケースを紹介します。



例のあるプロジェクトは、github.com- https://github.com/maiorov/VKAPIにあります



VK APIメソッドのドキュメントはここにあります。



このトピックに関する他のソースからの記事:

1. appleinsider.ru

2. imaladec.net



そのため、VK APIを使用したいくつかの手順:

1. UIWebViewを介したユーザー認証とaccessToken'aおよびユーザーIDの取得。

2. VK APIを使用して、データを要求および受信します。

2.1ユーザーの壁にテキストを送信する

2.1.1キャプチャ

2.2画像を壁に投稿する

2.2.1画像アップロード用のVKサーバーURLの取得

2.2.2 POSTリクエストを作成する

2.2.3 VKontakteサーバーに写真を保存するリクエストを作成する

2.2.4壁に写真を置く

3.ユーザーのログアウト



パート0.アプリケーションの登録

結局のところ、VKontakteにはモバイルアプリケーションを作成するためのいくつかのフォームがあるため、操作の最も些細な部分ではありませんでした! 適切に登録するには、リンクhttp://vkontakte.ru/editapp?act=create&site=1を使用する必要があります。アプリケーションのタイプをスタンドアロンアプリケーションを選択します。 設定のパラメーターは省略できます。 アプリケーションIDをコピーするだけです。 私の例では、このパラメーターにappIDが使用されています。



パート1.承認

VK APIでOauth 2.0プロトコルを使用するには、accessTokenとuser_idが必要です。 UIWebView Webブラウザーを介してVKサーバーにリクエストを送信することで受信できます。リクエストに応じて、VKontakteサーバーはユーザー認証フォームを発行します。認証を渡した後、accessToken、user_id(データを入力したユーザーのID) 。 これを行うには、新しいプロジェクトでビューコントローラーを作成します。たとえば、vkLoginViewControllerと名前を付けます。 これは、ユーザーの承認を担当するコントローラーになります;承認が成功すると、受信したパラメーターをNSUserDefaultsに保存し、デリゲートメソッドauthCompleteを呼び出します。



例で詳細なコードを見ることができます。 ここでは、主要なポイントのみを分析します。



コントローラーUIWebView * vkWebViewに追加することにより、リクエストを作成します。

NSString *authLink = [NSString stringWithFormat:@"http://api.vk.com/oauth/authorize?client_id=%@&scope=wall,photos&redirect_uri=http://api.vk.com/blank.html&display=touch&response_type=token", appID]; NSURL *url = [NSURL URLWithString:authLink]; [vkWebView loadRequest:[NSURLRequest requestWithURL:url]];
      
      





ここで、client_idはアプリケーションのID、scope = wall、photosはアプリケーションがユーザーに要求するアクセス権です(壁への壁の配置、写真は壁に画像を配置する必要があります)



webViewDidFinishLoad関数で、VKサーバーから応答を取得します。

 -(void)webViewDidFinishLoad:(UIWebView *)webView { //      if ([vkWebView.request.URL.absoluteString rangeOfString:@"access_token"].location != NSNotFound) { NSString *accessToken = [self stringBetweenString:@"access_token=" andString:@"&" innerString:[[[webView request] URL] absoluteString]]; //  id ,    NSArray *userAr = [[[[webView request] URL] absoluteString] componentsSeparatedByString:@"&user_id="]; NSString *user_id = [userAr lastObject]; NSLog(@"User id: %@", user_id); if(user_id){ [[NSUserDefaults standardUserDefaults] setObject:user_id forKey:@"VKAccessUserId"]; } if(accessToken){ [[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"VKAccessToken"]; //    .  expires_in=86400   ,     . //   ,   ,          [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"VKAccessTokenDate"]; [[NSUserDefaults standardUserDefaults] synchronize]; } NSLog(@"vkWebView response: %@",[[[webView request] URL] absoluteString]); [(ViewController *)delegate authComplete]; [self dismissModalViewControllerAnimated:YES]; } else if ([vkWebView.request.URL.absoluteString rangeOfString:@"error"].location != NSNotFound) { NSLog(@"Error: %@", vkWebView.request.URL.absoluteString); [self dismissModalViewControllerAnimated:YES]; } }
      
      







その後、必要なものすべてを取得しました:accessToken、user_id。 そして、認証が正常に完了したことをデリゲートに伝え、このコントローラーは不要になり、削除します。

 [(ViewController *)delegate authComplete]; [self dismissModalViewControllerAnimated:YES];
      
      







パート2. APIリクエスト

今から楽しみが始まります! ViewControllerの例では、APIの操作方法を理解できるいくつかの関数を用意しました。



2.1ユーザーの壁にテキストを送信する

たとえば、テキストを壁に送信する機能を考えてみましょう。

 - (void) sendText { NSString *user_id = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessUserId"]; NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessToken"]; NSString *text = @"   API !"; //        NSString *sendTextMessage = [NSString stringWithFormat:@"https://api.vk.com/method/wall.post?owner_id=%@&access_token=%@&message=%@", user_id, accessToken, [self URLEncodedString:text]]; NSLog(@"sendTextMessage: %@", sendTextMessage); //            NSDictionary *result = [self sendRequest:sendTextMessage withCaptcha:NO]; //       NSString *errorMsg = [[result objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"   !"]; } }
      
      





簡単にするために、NSUserDefaultsにデータを保存します。 承認が完了しました。つまり、リクエストを行うために必要なものはすべて揃っています。 wall.postメソッドを使用して、ユーザーID(owner_id)とトークン(access_token)を渡し、最初にURLEncodedString関数を介してメッセージパラメーターのテキストメッセージを実行します。

 //         - (NSString *)URLEncodedString:(NSString *)str { NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8); [result autorelease]; return result; }
      
      







リクエストを準備したら、関数を使用してサーバーに送信する必要があります。
 [self sendRequest:sendTextAndLinkMessage withCaptcha:NO];
      
      



ご覧のとおり、この関数はwithCaptchaパラメーターを受け入れます。(BOOL)サーバーがユーザーにアクションを確認するためにcaptchaの入力を要求する場合、これが必要になります。 これまでにキャプチャが必要ないため、NOを転送します。



実際、リクエスト送信機能自体:

 - (NSDictionary *) sendRequest:(NSString *)reqURl withCaptcha:(BOOL)captcha { //      ,      captcha_sid  captcha_key if(captcha == YES){ NSString *captcha_sid = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_sid"]; NSString *captcha_user = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_user"]; //      .  ,      . reqURl = [reqURl stringByAppendingFormat:@"&captcha_sid=%@&captcha_key=%@", captcha_sid, [self URLEncodedString: captcha_user]]; } NSLog(@"Sending request: %@", reqURl); NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:reqURl] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; //      NSURLConnection,     NSData NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; //    ,        JSONKit  NSDictionary if(responseData){ NSDictionary *dict = [[JSONDecoder decoder] parseJSONData:responseData]; //       NSString *errorMsg = [[dict objectForKey:@"error"] objectForKey:@"error_msg"]; NSLog(@"Server response: %@ \nError: %@", dict, errorMsg); //    .      Captcha needed,     . if([errorMsg isEqualToString:@"Captcha needed"]){ isCaptcha = YES; //     NSString *captcha_sid = [[dict objectForKey:@"error"] objectForKey:@"captcha_sid"]; NSString *captcha_img = [[dict objectForKey:@"error"] objectForKey:@"captcha_img"]; [[NSUserDefaults standardUserDefaults] setObject:captcha_img forKey:@"captcha_img"]; [[NSUserDefaults standardUserDefaults] setObject:captcha_sid forKey:@"captcha_sid"]; //  url         [[NSUserDefaults standardUserDefaults] setObject:reqURl forKey:@"request"]; [[NSUserDefaults standardUserDefaults] synchronize]; [self getCaptcha]; } return dict; } return nil; }
      
      





この関数はサーバーからNSDictionary応答を返します;デフォルトではVKontakteがJSON形式で応答するためJSONKitを使用して生成します。



キャプチャ

突然サーバーがユーザーがcaptchaを入力する必要があると判断した場合、ユーザーはリクエストに応じてエラーを返します:Captcha required and parameters-captcha_sid(これはcaptcha idです)、captcha_img(captcha画像へのリンク)。 これらのパラメーターを準備し、サーバーがこのように応答するリクエストを保存すると同時に、captcha入力関数を呼び出します。
 [self getCaptcha];
      
      





もっと詳しく考えてみましょう。

 - (void) getCaptcha { NSString *captcha_img = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_img"]; UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@" :\n\n\n\n\n" message:@"\n" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(12.0, 45.0, 130.0, 50.0)] autorelease]; imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:captcha_img]]]; [myAlertView addSubview:imageView]; UITextField *myTextField = [[[UITextField alloc] initWithFrame:CGRectMake(12.0, 110.0, 260.0, 25.0)] autorelease]; [myTextField setBackgroundColor:[UIColor whiteColor]]; //   myTextField.autocorrectionType = UITextAutocorrectionTypeNo; //   myTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; myTextField.tag = 33; [myAlertView addSubview:myTextField]; [myAlertView show]; [myAlertView release]; } - (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(isCaptcha && buttonIndex == 1){ isCaptcha = NO; UITextField *myTextField = (UITextField *)[actionSheet viewWithTag:33]; [[NSUserDefaults standardUserDefaults] setObject:myTextField.text forKey:@"captcha_user"]; NSLog(@"Captcha entered: %@",myTextField.text); //           NSString *request = [[NSUserDefaults standardUserDefaults] objectForKey:@"request"]; NSDictionary *newRequestDict =[self sendRequest:request withCaptcha:YES]; NSString *errorMsg = [[newRequestDict objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"     !"]; } } }
      
      





UIImageViewとUITextFieldを追加した標準のUIAlertViewとcaptcha_imgパラメーターを使用して、ユーザーにcaptchaを入力する機会を与えます。 captchaが入力された後、UIAlertViewデリゲート関数で、ユーザーがNSUserDefaultsに入力した内容をcaptcha_userキーで保存し、以前に保存されたリクエストURLを使用して、今度はパラメーターでwithCaptcha:YESを指定して再度実行します。 その結果、リクエストを送信する前に、captcha_sidおよびcaptcha_keyパラメーターが追加されます(ユーザーが入力したもの):

 - (NSDictionary *) sendRequest:(NSString *)reqURl withCaptcha:(BOOL)captcha { //      ,      captcha_sid  captcha_key if(captcha == YES){ NSString *captcha_sid = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_sid"]; NSString *captcha_user = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_user"]; //      .  ,      . reqURl = [reqURl stringByAppendingFormat:@"&captcha_sid=%@&captcha_key=%@", captcha_sid, [self URLEncodedString: captcha_user]]; } ...
      
      





Captchaが入力され、リクエストが送信されました。テキストはユーザーのウォールに正常に投稿される必要があります。



2.2画像を壁に投稿する

多くの場合、アプリケーションの写真をユーザーの壁に配置する必要があります。 この問題を解決するには、次の手順を実行する必要があります。

  1. VKontakteサーバーのURLをリクエストして、画像( photos.getWallUploadServer )をダウンロードします
  2. サーバーの応答で受信したリンクを使用して、POSTメソッドを使用して画像を送信します
  3. 応答ハッシュ、写真、サーバーを受信した後、壁に写真を保存するコマンドを送信します( photos.saveWallPhoto
  4. 応答で写真IDを受け取った後、 wall.postを使用して壁に写真を投稿するリクエストを行います。ここで、写真IDを添付ファイルとして指定します。




2.2.1画像アップロード用のVKサーバーURLの取得

 - (IBAction)sendImageAction:(id)sender { if(!isAuth) return; UIImage *image = [UIImage imageNamed:@"test.jpg"]; NSString *user_id = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessUserId"]; NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessToken"]; //  1 NSString *getWallUploadServer = [NSString stringWithFormat:@"https://api.vk.com/method/photos.getWallUploadServer?owner_id=%@&access_token=%@", user_id, accessToken]; NSDictionary *uploadServer = [self sendRequest:getWallUploadServer withCaptcha:NO]; //      NSString *upload_url = [[uploadServer objectForKey:@"response"] objectForKey:@"upload_url"]; ...
      
      





ここで、画像をダウンロードするためのリンクを受信したら、添付された画像を使用してPOSTリクエストを行う必要があります。 これを行うには、画像をNSDataに変換し、関数を使用してリクエストを作成します
 [self sendPOSTRequest:upload_url withImageData:imageData];
      
      







2.2.2 POSTリクエストを作成する

 ... //  2 //    NSData NSData *imageData = UIImageJPEGRepresentation(image, 1.0f); NSDictionary *postDictionary = [self sendPOSTRequest:upload_url withImageData:imageData]; //     hash, photo, server NSString *hash = [postDictionary objectForKey:@"hash"]; NSString *photo = [postDictionary objectForKey:@"photo"]; NSString *server = [postDictionary objectForKey:@"server"]; ...
      
      





このでは、POST要求を形成する関数を確認できます。



2.2.3 VKontakteサーバーに写真を保存するリクエストを作成する

 ... //  3 //        ,    id  NSString *saveWallPhoto = [NSString stringWithFormat:@"https://api.vk.com/method/photos.saveWallPhoto?owner_id=%@&access_token=%@&server=%@&photo=%@&hash=%@", user_id, accessToken,server,photo,hash]; NSDictionary *saveWallPhotoDict = [self sendRequest:saveWallPhoto withCaptcha:NO]; NSDictionary *photoDict = [[saveWallPhotoDict objectForKey:@"response"] lastObject]; NSString *photoId = [photoDict objectForKey:@"id"]; ...
      
      





応答として、ダウンロードした写真の写真IDを取得します。これで、通常のwall.postリクエストを行うことができます。ここで、添付パラメーターとして写真IDを指定します。 それでもリンクを追加する必要がある場合は、写真IDの後に十分です。カンマで指定します。



2.2.4壁に写真を置く

 ... //  4 //      NSString *postToWallLink = [NSString stringWithFormat:@"https://api.vk.com/method/wall.post?owner_id=%@&access_token=%@&message=%@&attachment=%@", user_id, accessToken, [self URLEncodedString:@"      "], photoId]; NSDictionary *postToWallDict = [self sendRequest:postToWallLink withCaptcha:NO]; NSString *errorMsg = [[postToWallDict objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"   !"]; } // !     !
      
      







パート3.ユーザーのログアウト

ログアウトするには、VKontakteサーバーにリクエストを送信するだけです:

 NSString *logout = @"http://api.vk.com/oauth/logout";
      
      





ログアウト機能の例:

 - (IBAction)logout:(id)sender { //   logout NSString *logout = @"http://api.vk.com/oauth/logout"; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:logout] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; if(responseData){ NSDictionary *dict = [[JSONDecoder decoder] parseJSONData:responseData]; NSLog(@"Logout: %@", dict); //    ,    isAuth = NO; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessUserId"]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessToken"]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessTokenDate"]; [[NSUserDefaults standardUserDefaults] synchronize]; [self sendSuccessWithMessage:@"  !"]; } }
      
      







VKontakteがエラーで応答するという事実にもかかわらず、ユーザーはまだ終了します:)

 Logout: { error = "invalid_client"; "error_description" = "client_id is incorrect"; }
      
      







おわりに

この記事がVkontakte APIの学習に役立つことを願っています。 私はコメント、追加を喜んでいるでしょう。



All Articles