После двух дней разочарования и проклятия 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];
Помните любые пропущенные пробелы или запятые, может привести к ошибке.
«Чтобы запустить поток показа, приложение должно получить токен запроса, отправив сообщение SIGNED в POST oauth/request_token. Единственным уникальным параметром в этом запросе является oauth_callback, который должен быть URL-кодированной версией URL-адреса вы хотите, чтобы ваш пользователь был перенаправлен, когда они завершают шаг 2. Остальные параметры добавляются в процессе подписки OAuth ». Так что мне нужно «oauth_signature» и т. Д. Или нет? – Dario
@ Dario You * do. * – 2013-02-16 21:14:06
[Этот документ] (https://dev.twitter.com/docs/auth/creating-signature) указывает, что вам нужен ваш потребительский ключ (без проблем) и токен (я пытаясь получить эту вещь, у меня ее еще нет), чтобы создать ключ для * подписи подписи *. Что я делаю не так? Кстати, спасибо за вашу помощь! – Dario