axmol/plugin/plugins/weibo/proj.ios/SinaWeibo/SinaWeibo.m

553 lines
19 KiB
Mathematica
Raw Normal View History

//
// SinaWeibo.m
// sinaweibo_ios_sdk
//
// Created by Wade Cheng on 4/19/12.
// Copyright (c) 2012 SINA. All rights reserved.
//
#import "SinaWeibo.h"
#import "SinaWeiboRequest.h"
#import "SinaWeiboAuthorizeView.h"
#import "SinaWeiboConstants.h"
@interface SinaWeibo ()
@property (nonatomic, copy) NSString *appKey;
@property (nonatomic, copy) NSString *appSecret;
@property (nonatomic, copy) NSString *appRedirectURI;
@end
@implementation SinaWeibo
@synthesize userID;
@synthesize accessToken;
@synthesize expirationDate;
@synthesize refreshToken;
@synthesize ssoCallbackScheme;
@synthesize delegate;
@synthesize appKey;
@synthesize appSecret;
@synthesize appRedirectURI;
#pragma mark - Memory management
/**
* @description ssoSinaWeibo
* @param _appKey: appkey
* @param _appSecrect: appsecrect
* @param _appRedirectURI:
* @return SinaWeibo
*/
- (id)initWithAppKey:(NSString *)_appKey appSecret:(NSString *)_appSecrect
appRedirectURI:(NSString *)_appRedirectURI
andDelegate:(id<SinaWeiboDelegate>)_delegate
{
return [self initWithAppKey:_appKey appSecret:_appSecrect appRedirectURI:_appRedirectURI ssoCallbackScheme:nil andDelegate:_delegate];
}
/**
* @description ssoSinaWeibo
* @param _appKey: appkey
* @param _appSecrect: appsecrect
* @param _ssoCallbackScheme: ssoURL Types
* nil, sinaweibosso.your_app_key;
* @param _appRedirectURI:
* @return SinaWeibo
*/
- (id)initWithAppKey:(NSString *)_appKey appSecret:(NSString *)_appSecrect
appRedirectURI:(NSString *)_appRedirectURI
ssoCallbackScheme:(NSString *)_ssoCallbackScheme
andDelegate:(id<SinaWeiboDelegate>)_delegate
{
if ((self = [super init]))
{
self.appKey = _appKey;
self.appSecret = _appSecrect;
self.appRedirectURI = _appRedirectURI;
self.delegate = _delegate;
if (!_ssoCallbackScheme)
{
_ssoCallbackScheme = [NSString stringWithFormat:@"sinaweibosso.%@://", self.appKey];
}
self.ssoCallbackScheme = _ssoCallbackScheme;
requests = [[NSMutableSet alloc] init];
}
return self;
}
- (void)dealloc
{
delegate = nil;
for (SinaWeiboRequest* _request in requests)
{
_request.sinaweibo = nil;
}
[request disconnect];
[request release], request = nil;
[userID release], userID = nil;
[accessToken release], accessToken = nil;
[expirationDate release], expirationDate = nil;
[appKey release], appKey = nil;
[appSecret release], appSecret = nil;
[appRedirectURI release], appRedirectURI = nil;
[ssoCallbackScheme release], ssoCallbackScheme = nil;
[super dealloc];
}
/**
* @description
*/
- (void)removeAuthData
{
self.accessToken = nil;
self.userID = nil;
self.expirationDate = nil;
NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray* sinaweiboCookies = [cookies cookiesForURL:
[NSURL URLWithString:@"https://open.weibo.cn"]];
for (NSHTTPCookie* cookie in sinaweiboCookies)
{
[cookies deleteCookie:cookie];
}
}
#pragma mark - Private methods
- (void)requestAccessTokenWithAuthorizationCode:(NSString *)code
{
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
self.appKey, @"client_id",
self.appSecret, @"client_secret",
@"authorization_code", @"grant_type",
self.appRedirectURI, @"redirect_uri",
code, @"code", nil];
[request disconnect];
[request release], request = nil;
request = [[SinaWeiboRequest requestWithURL:kSinaWeiboWebAccessTokenURL
httpMethod:@"POST"
params:params
delegate:self] retain];
[request connect];
}
- (void)requestDidFinish:(SinaWeiboRequest *)_request
{
[requests removeObject:_request];
_request.sinaweibo = nil;
}
- (void)requestDidFailWithInvalidToken:(NSError *)error
{
if ([delegate respondsToSelector:@selector(sinaweibo:accessTokenInvalidOrExpired:)])
{
[delegate sinaweibo:self accessTokenInvalidOrExpired:error];
}
}
- (void)notifyTokenExpired:(id<SinaWeiboRequestDelegate>)requestDelegate
{
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
@"Token expired", NSLocalizedDescriptionKey, nil];
NSError *error = [NSError errorWithDomain:kSinaWeiboSDKErrorDomain
code:21315
userInfo:userInfo];
if ([delegate respondsToSelector:@selector(sinaweibo:accessTokenInvalidOrExpired:)])
{
[delegate sinaweibo:self accessTokenInvalidOrExpired:error];
}
if ([requestDelegate respondsToSelector:@selector(request:didFailWithError:)])
{
[requestDelegate request:nil didFailWithError:error];
}
}
- (void)logInDidCancel
{
if ([delegate respondsToSelector:@selector(sinaweiboLogInDidCancel:)])
{
[delegate sinaweiboLogInDidCancel:self];
}
}
- (void)logInDidFinishWithAuthInfo:(NSDictionary *)authInfo
{
NSString *access_token = [authInfo objectForKey:@"access_token"];
NSString *uid = [authInfo objectForKey:@"uid"];
NSString *remind_in = [authInfo objectForKey:@"remind_in"];
NSString *refresh_token = [authInfo objectForKey:@"refresh_token"];
if (access_token && uid)
{
if (remind_in != nil)
{
int expVal = [remind_in intValue];
if (expVal == 0)
{
self.expirationDate = [NSDate distantFuture];
}
else
{
self.expirationDate = [NSDate dateWithTimeIntervalSinceNow:expVal];
}
}
self.accessToken = access_token;
self.userID = uid;
self.refreshToken = refresh_token;
if ([delegate respondsToSelector:@selector(sinaweiboDidLogIn:)])
{
[delegate sinaweiboDidLogIn:self];
}
}
}
- (void)logInDidFailWithErrorInfo:(NSDictionary *)errorInfo
{
NSString *error_code = [errorInfo objectForKey:@"error_code"];
if ([error_code isEqualToString:@"21330"])
{
[self logInDidCancel];
}
else
{
if ([delegate respondsToSelector:@selector(sinaweibo:logInDidFailWithError:)])
{
NSString *error_description = [errorInfo objectForKey:@"error_description"];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
errorInfo, @"error",
error_description, NSLocalizedDescriptionKey, nil];
NSError *error = [NSError errorWithDomain:kSinaWeiboSDKErrorDomain
code:[error_code intValue]
userInfo:userInfo];
[delegate sinaweibo:self logInDidFailWithError:error];
}
}
}
#pragma mark - Validation
/**
* @description
* @return YESNO
*/
- (BOOL)isLoggedIn
{
return userID && accessToken && expirationDate;
}
/**
* @description
* @return YESNO
*/
- (BOOL)isAuthorizeExpired
{
NSDate *now = [NSDate date];
return ([now compare:expirationDate] == NSOrderedDescending);
}
/**
* @description
* @return YESNO
*/
- (BOOL)isAuthValid
{
return ([self isLoggedIn] && ![self isAuthorizeExpired]);
}
#pragma mark - LogIn / LogOut
/**
* @description SinaWeibo
*/
- (void)logIn
{
if ([self isAuthValid])
{
if ([delegate respondsToSelector:@selector(sinaweiboDidLogIn:)])
{
[delegate sinaweiboDidLogIn:self];
}
}
else
{
[self removeAuthData];
ssoLoggingIn = NO;
// open sina weibo app
UIDevice *device = [UIDevice currentDevice];
if ([device respondsToSelector:@selector(isMultitaskingSupported)] &&
[device isMultitaskingSupported])
{
NSDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
self.appKey, @"client_id",
self.appRedirectURI, @"redirect_uri",
self.ssoCallbackScheme, @"callback_uri", nil];
// iPad
NSString *appAuthBaseURL = kSinaWeiboAppAuthURL_iPad;
if (SinaWeiboIsDeviceIPad())
{
NSString *appAuthURL = [SinaWeiboRequest serializeURL:appAuthBaseURL
params:params httpMethod:@"GET"];
ssoLoggingIn = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appAuthURL]];
}
// iPhone
if (!ssoLoggingIn)
{
appAuthBaseURL = kSinaWeiboAppAuthURL_iPhone;
NSString *appAuthURL = [SinaWeiboRequest serializeURL:appAuthBaseURL
params:params httpMethod:@"GET"];
ssoLoggingIn = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appAuthURL]];
}
}
if (!ssoLoggingIn)
{
// open authorize view
NSDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
self.appKey, @"client_id",
@"code", @"response_type",
self.appRedirectURI, @"redirect_uri",
@"mobile", @"display", nil];
SinaWeiboAuthorizeView *authorizeView = \
[[SinaWeiboAuthorizeView alloc] initWithAuthParams:params
delegate:self];
[authorizeView show];
[authorizeView release];
}
}
}
/**
* @description 退退
*/
- (void)logOut
{
[self removeAuthData];
if ([delegate respondsToSelector:@selector(sinaweiboDidLogOut:)])
{
[delegate sinaweiboDidLogOut:self];
}
}
#pragma mark - Send request with token
/**
* @description APItoken
* @param url:
* @param params:
* @param httpMethod: httpGETPOST
* @param _delegate: SinaweiboRequestDelegate
* @return SinaWeiboRequest
*/
- (SinaWeiboRequest *)requestWithURL:(NSString *)url
params:(NSMutableDictionary *)params
httpMethod:(NSString *)httpMethod
delegate:(id<SinaWeiboRequestDelegate>)_delegate
{
if (params == nil)
{
params = [NSMutableDictionary dictionary];
}
if ([self isAuthValid])
{
[params setValue:self.accessToken forKey:@"access_token"];
NSString *fullURL = [kSinaWeiboSDKAPIDomain stringByAppendingString:url];
SinaWeiboRequest *_request = [SinaWeiboRequest requestWithURL:fullURL
httpMethod:httpMethod
params:params
delegate:_delegate];
_request.sinaweibo = self;
[requests addObject:_request];
[_request connect];
return _request;
}
else
{
//notify token expired in next runloop
[self performSelectorOnMainThread:@selector(notifyTokenExpired:)
withObject:_delegate
waitUntilDone:NO];
return nil;
}
}
#pragma mark - SinaWeiboAuthorizeView Delegate
- (void)authorizeView:(SinaWeiboAuthorizeView *)authView didRecieveAuthorizationCode:(NSString *)code
{
[self requestAccessTokenWithAuthorizationCode:code];
}
- (void)authorizeView:(SinaWeiboAuthorizeView *)authView didFailWithErrorInfo:(NSDictionary *)errorInfo
{
[self logInDidFailWithErrorInfo:errorInfo];
}
- (void)authorizeViewDidCancel:(SinaWeiboAuthorizeView *)authView
{
[self logInDidCancel];
}
#pragma mark - SinaWeiboRequest Delegate
- (void)request:(SinaWeiboRequest *)_request didFailWithError:(NSError *)error
{
if (_request == request)
{
if ([delegate respondsToSelector:@selector(sinaweibo:logInDidFailWithError:)])
{
[delegate sinaweibo:self logInDidFailWithError:error];
}
[request release], request = nil;
}
}
- (void)request:(SinaWeiboRequest *)_request didFinishLoadingWithResult:(id)result
{
if (_request == request)
{
NSLog(@"access token result = %@", result);
[self logInDidFinishWithAuthInfo:result];
[request release], request = nil;
}
}
#pragma mark - Application life cycle
/**
* @description 退
*/
- (void)applicationDidBecomeActive
{
if (ssoLoggingIn)
{
// user open the app manually
// clean sso login state
ssoLoggingIn = NO;
if ([delegate respondsToSelector:@selector(sinaweiboLogInDidCancel:)])
{
[delegate sinaweiboLogInDidCancel:self];
}
}
}
/**
* @description ssossosso
* @param url:
* @return YES
*/
- (BOOL)handleOpenURL:(NSURL *)url
{
NSString *urlString = [url absoluteString];
if ([urlString hasPrefix:self.ssoCallbackScheme])
{
if (!ssoLoggingIn)
{
// sso callback after user have manually opened the app
// ignore the request
}
else
{
ssoLoggingIn = NO;
if ([SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"sso_error_user_cancelled"])
{
if ([delegate respondsToSelector:@selector(sinaweiboLogInDidCancel:)])
{
[delegate sinaweiboLogInDidCancel:self];
}
}
else if ([SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"sso_error_invalid_params"])
{
if ([delegate respondsToSelector:@selector(sinaweibo:logInDidFailWithError:)])
{
NSString *error_description = @"Invalid sso params";
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
error_description, NSLocalizedDescriptionKey, nil];
NSError *error = [NSError errorWithDomain:kSinaWeiboSDKErrorDomain
code:kSinaWeiboSDKErrorCodeSSOParamsError
userInfo:userInfo];
[delegate sinaweibo:self logInDidFailWithError:error];
}
}
else if ([SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"error_code"])
{
NSString *error_code = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"error_code"];
NSString *error = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"error"];
NSString *error_uri = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"error_uri"];
NSString *error_description = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"error_description"];
NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
error, @"error",
error_uri, @"error_uri",
error_code, @"error_code",
error_description, @"error_description", nil];
[self logInDidFailWithErrorInfo:errorInfo];
}
else
{
NSString *access_token = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"access_token"];
NSString *expires_in = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"expires_in"];
NSString *remind_in = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"remind_in"];
NSString *uid = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"uid"];
NSString *refresh_token = [SinaWeiboRequest getParamValueFromUrl:urlString paramName:@"refresh_token"];
NSMutableDictionary *authInfo = [NSMutableDictionary dictionary];
if (access_token) [authInfo setObject:access_token forKey:@"access_token"];
if (expires_in) [authInfo setObject:expires_in forKey:@"expires_in"];
if (remind_in) [authInfo setObject:remind_in forKey:@"remind_in"];
if (refresh_token) [authInfo setObject:refresh_token forKey:@"refresh_token"];
if (uid) [authInfo setObject:uid forKey:@"uid"];
[self logInDidFinishWithAuthInfo:authInfo];
}
}
}
return YES;
}
@end
BOOL SinaWeiboIsDeviceIPad()
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return YES;
}
#endif
return NO;
}