2013-02-16 3 views
1

Я пытаюсь получить маркер запроса из Twitter с этим кодом:Как заставить NSURLRequest получить токен запроса Twitter?

NSMutableURLRequest *mURLRequest = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"]]; 
mURLRequest.HTTPMethod = @"POST /oauth/request_token HTTP/1.1"; 
[mURLRequest setValue:@"User-Agent" forHTTPHeaderField:@"Coupled HTTP"]; 
[mURLRequest setValue:@"OAuth oauth_callback=\"http%3A%2F%2Fbytolution.com\"" forHTTPHeaderField:@"Authorization"]; 
[mURLRequest setValue:@"api.twitter.com" forHTTPHeaderField:@"Host"]; 
[mURLRequest setValue:@"Accept" forHTTPHeaderField:@"*/*"]; 

NSHTTPURLResponse *urlResponse; 
NSError *error; 
NSError *serializationError; 
NSData *responseData = [NSURLConnection sendSynchronousRequest:mURLRequest returningResponse:&urlResponse error:&error]; 
NSLog(@"data: %@, response:%@, error: %@", [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&serializationError], urlResponse.allHeaderFields, error); 

Но я вернусь есть:

data: (null), response:{ Connection = close; "Content-Length" = 0; }, error: (null)

Here является Twitter`s документация по этой теме.

Благодарим за помощь!

ответ

1

несколько ошибок (не уверен, если список будет завершен, это то, что я нашел на первый взгляд):

  • метод HTTP должен быть просто @"POST", не @"POST foo", @"POST or I will kill you" или что-нибудь еще;
  • Аналогичным образом, @"OAuth oauth_callback=\"" должно быть @"oauth_callback=\"";
  • Вы не включаете все необходимые поля заголовка, например oauth_consumer_key, oauth_signature, oauth_signature_method, oauth_nonce и oauth_timestamp;
  • Это не возвращает JSON. Он возвращает URL-кодированный ответ, что-то вроде примера в official documentation.
+0

«Чтобы запустить поток показа, приложение должно получить токен запроса, отправив сообщение SIGNED в POST oauth/request_token. Единственным уникальным параметром в этом запросе является oauth_callback, который должен быть URL-кодированной версией URL-адреса вы хотите, чтобы ваш пользователь был перенаправлен, когда они завершают шаг 2. Остальные параметры добавляются в процессе подписки OAuth ». Так что мне нужно «oauth_signature» и т. Д. Или нет? – Dario

+0

@ Dario You * do. * – 2013-02-16 21:14:06

+0

[Этот документ] (https://dev.twitter.com/docs/auth/creating-signature) указывает, что вам нужен ваш потребительский ключ (без проблем) и токен (я пытаясь получить эту вещь, у меня ее еще нет), чтобы создать ключ для * подписи подписи *. Что я делаю не так? Кстати, спасибо за вашу помощь! – Dario

2

После двух дней разочарования и проклятия Twitter я, наконец, смог это сделать. Вот моя реализация. Класс, который будет использоваться для запроса, будет «BL_TwitterRequest». Это делается только для получения токена запроса твиттера.

BL_TwitterRequest.h:

#import <Foundation/Foundation.h> 

@interface BL_Request : NSObject <NSURLConnectionDelegate> 

@property (nonatomic, strong) NSMutableData *webData; 

-(void) makeRequest; 

Добавить следующую категорию NSString в верхней части класса реализации (BL_TwitterRequest.m). Это будет использоваться для получения кодированной версии NSString.

@implementation NSString (NSString_Extended) 

- (NSString *)urlencode { 
    NSMutableString *output = [NSMutableString string]; 
    const unsigned char *source = (const unsigned char *)[self UTF8String]; 
    int sourceLen = strlen((const char *)source); 
    for (int i = 0; i < sourceLen; ++i) { 
     const unsigned char thisChar = source[i]; 
     if (thisChar == ' '){ 
      [output appendString:@"+"]; 
     } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 
        (thisChar >= 'a' && thisChar <= 'z') || 
        (thisChar >= 'A' && thisChar <= 'Z') || 
        (thisChar >= '0' && thisChar <= '9')) { 
      [output appendFormat:@"%c", thisChar]; 
     } else { 
      [output appendFormat:@"%%%02X", thisChar]; 
     } 
    } 
    return output; 
} 

@end 

Добавить функцию ниже в "BL_TwitterRequest.m". Он будет использоваться для генерации oAuth nonce. Функция в основном генерирует случайную строку заданной длины.

-(NSString*) generateRandomStringOfLength:(int)length { 

    NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    NSMutableString *randomString = [NSMutableString stringWithCapacity: length]; 
    for (int i = 0; i < length; i++) { 
     [randomString appendFormat: @"%C", [letters characterAtIndex: arc4random() % [letters length]]]; 
    } 

    return randomString; 
} 

Включите библиотеку Base64 от here. Все, что вам нужно сделать, это перетащить файлы «Base64.h» и «Base64.m» в ваш проект. Добавить следующие импорты:

#include <CommonCrypto/CommonDigest.h> 
#include <CommonCrypto/CommonHMAC.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#import "Base64.h" 

Добавить еще одну функцию, как указано ниже. Это будет использоваться для получения значения HMAC-SHA1.

- (NSString *)hmacsha1:(NSString *)data secret:(NSString *)key { 

    const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; 
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; 

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH]; 

    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC); 

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; 

    NSString *hash = [HMAC base64EncodedString]; 

    return hash; 
} 

Теперь для основной функции, которая сделает запрос.

-(void) makeRequest { 

    _webData = [[NSMutableData alloc]init]; // WILL BE USED BY NSURLConnection 

    NSString *httpMethod = @"POST"; 
    NSString *baseURL = @"https://api.twitter.com/oauth/request_token"; 
    NSString *oauthConsumerKey = @"YOUR_CONSUMER_KEY"; 
    NSString *oauthConsumerSecret = @"YOUR_CONSUMER_SECRET"; 
    NSString *oauth_timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date]timeIntervalSince1970]]; 
    NSString *oauthNonce = [self generateRandomStringOfLength:42]; 
    NSString *oauthSignatureMethod = @"HMAC-SHA1"; 
    NSString *oauthVersion = @"1.0"; 
    NSString *oauthCallback = @"YOUR_TWITTER_CALLBACK_URL"; 

    //1. PERCENT CODE EVERY KEY AND VALUE THAT WILL BE SIGNED AND 
    // APPEND KEY AND VALUE WITH = AND & 

    NSMutableString *parameterString = [[NSMutableString alloc]initWithFormat:@""]; 

    [parameterString appendFormat:@"oauth_callback=%@", [oauthCallback urlencode]]; 
    [parameterString appendFormat:@"&oauth_consumer_key=%@", [oauthConsumerKey urlencode]]; 
    [parameterString appendFormat:@"&oauth_nonce=%@", [oauthNonce urlencode]]; 
    [parameterString appendFormat:@"&oauth_signature_method=%@", [oauthSignatureMethod urlencode]]; 
    [parameterString appendFormat:@"&oauth_timestamp=%@", [oauth_timestamp urlencode]]; 
    [parameterString appendFormat:@"&oauth_version=%@", [oauthVersion urlencode]]; 

    //2. CREATE SIGNATURE STRING WITH HTTP METHOD AND ENCODED BASE URL AND PARAMETER STRING 

    NSString *signatureBaseString = [NSString stringWithFormat:@"%@&%@&%@", httpMethod, [baseURL urlencode], [parameterString urlencode]]; 

    //3. GET THE SIGNING KEY NOW FROM CONSUMER SECRET 

    NSString *signingKey = [NSString stringWithFormat:@"%@&", [oauthConsumerSecret urlencode]]; 

    //4. GET THE OUTPUT OF THE HMAC ALOGRITHM 

    NSString *oauthSignature = [self hmacsha1:signatureBaseString secret:signingKey]; 

    // TIME TO MAKE THE CALL NOW 

    NSMutableString *urlString = [[NSMutableString alloc]initWithFormat:@""]; 

    [urlString appendFormat:@"%@", baseURL]; 

    // INITIALIZE AUTHORIZATION HEADER 

    NSMutableString *authHeader = [[NSMutableString alloc]initWithFormat:@""]; 

    [authHeader appendFormat:@"OAuth "]; // MIND THE SPACE AFTER 'OAuth' 

    [authHeader appendFormat:@"oauth_nonce=\"%@\",", [oauthNonce urlencode]]; 
    [authHeader appendFormat:@"oauth_callback=\"%@\",", [oauthCallback urlencode]]; 
    [authHeader appendFormat:@"oauth_signature_method=\"%@\",", [oauthSignatureMethod urlencode]]; 
    [authHeader appendFormat:@"oauth_timestamp=\"%@\",", [oauth_timestamp urlencode]]; 
    [authHeader appendFormat:@"oauth_consumer_key=\"%@\",", [oauthConsumerKey urlencode]]; 
    [authHeader appendFormat:@"oauth_signature=\"%@\",", [oauthSignature urlencode]]; 
    [authHeader appendFormat:@"oauth_version=\"%@\"", [oauthVersion urlencode]]; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:urlString]] ; 

    [request setHTTPMethod:httpMethod]; 

    [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; 

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; 

    [connection start]; 

} 

Теперь просто реализуйте методы делегата NSURLConnection, чтобы получить ответ.

#pragma mark - Connection Delegate 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    [_webData appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    NSString *resultString = [[NSString alloc]initWithData:_webData encoding:NSUTF8StringEncoding]; 

    NSLog(@"RESULT STRING : %@", resultString); 
} 

Если все идет хорошо 'resultString' будет иметь oauth_token и oauth_token_secret.

Чтобы сделать вызов просто сделать следующее:

BL_TwitterRequest *twitterRequest = [[BL_TwitterRequest alloc]init]; 
[twitterRequest makeRequest]; 

Помните любые пропущенные пробелы или запятые, может привести к ошибке.

Смежные вопросы