本内容将记录 微博
的登录和分享功能,当然微博也有支付功能,但是微博的支付功能使用的还是比较少的,一般使用马大大的 支付宝
或者小马的 微信
作为第三方支付功能。
微博开放平台链接地址: https://open.weibo.com/
微博iOS-SDK文档 (具体使用可看微博SDK开发文档): https://github.com/sinaweibosdk/weibo_ios_sdk
移动端接入+SDK功能特性: http://open.weibo.com/wiki/%E7%A7%BB%E5%8A%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%8E%A5%E5%85%A5
最新版本的微博登录需要实现以下步骤:
- 在新浪微博公共开放平台并注册应用(https://open.weibo.com/)
- 需要在 "我的应用"=> "应用信息"=>"高级信息"中填写应用的默认授权回调页
https://api.weibo.com/oauth2/default.html
- 已选择应用为
iphone
平台,并正确填写Bundle id
和apple id
(要与Xcode 工程中的bundle相对应)
在上面的各个步骤中是需要完成对新浪微博的开发者的注册和应用的注册并提交审核;最后我们需要达到的效果是拿到我们需要的应用对应的 AppKey
和AppSecert
这两个用于我们接下来的整个应用开发。
集成 weibosdk 并添加Xcode项目的各项配置-->
1. 设置工程回调的 URL Scheme
在 Targets->Info->URL Types
中 点击 +
新增用于微博的URL Scheme回调
Identifier
可随便填写,URL Schemes
-> wb+AppKey(如:we222222)
2. 添加 weibo SDK文件到工程
根据教程我们可以使用直接添加weibo SDK或者使用cocoapods吧weiboSDK添加入项目中去。我一般不论使用微博/微信/QQ登录或者支付等导入功能时一般选择直接拖入,一来这样其实比pod入工程更加方便管理,而且不会随着官方的更新而更新,避免导致未知的错误。
微博SDK下载地址为--github: https://github.com/sinaweibosdk/weibo_ios_sdk
一般 拖入工程的SDK包括如下内容:
3. 在SDK拖入工程后,给工程中添加必要的配置 Frameworks and Libraries
和 Build Setting
为了避免静态库中类加载 不全造成程序崩溃,在 Target->Buid Settings->Linking 下 Other Linker Flags
项添加 -ObjC
参数。
在⼯程中修改Other Linker Flags后,需要修改编译步骤的链接库设置,避免链接阶
段由于库的设置错误导致程序崩溃。添加必要的 FrameWorks/Libraries,
添加步骤为: Target->Build Phases->Link Binary with Libraries
/Target->General->Link Frameworks and Libraries
总共需要添加这些库:
Photos.framework
QuartzCore.framework
ImageIO.framework、
SystemConfiguration.framework、
Security.framework、
CoreTelephony.framework、
CoreText.framework、
UIKit.framework、
Foundation.framework、
CoreGraphics.framework 、
libz.dylib、
libsqlite3.dylib。
4. 在 Info.plist 文件中 添加白名单
LSApplicationQueriesSchemes
-->
在所有配置完成后具体添加实现微博登录的代码:
1. 在 AppDelegate.m
中实现
1. import `#import "WeiboSDK.h"`
2. `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`
加入
[WeiboSDK enableDebugMode:YES];
[WeiboSDK registerApp:kSinaweiboAppKey]; // 注册应用时申请的AppKey
3. /* 微博登录使用 -- 必须使用下面方法,否则会报错 */
加入代码: // 此处的 `WeiboSDKVCDelegate` 是自定义的 WebiboSDk delegate 类
// 此处的 [WeiboSDKVCDelegate class] 作为代理需要使用类方法作为类的代理响应
// 若为 [[WeiboSDKVCDelegate alloc]init] 则可实现代理的对象方法,否则会出现 `unrecognizer selector`
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if ([WeiboSDK handleOpenURL:url delegate:[[WeiboSDKVCDelegate alloc]init]]) {
return YES;
}
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
// [[WeiboSDKVCDelegate alloc]init]
// (id)[WeiboSDKVCDelegate class]
if ([WeiboSDK handleOpenURL:url delegate:[[WeiboSDKVCDelegate alloc]init]]) {
return YES;
}
return YES;
}
2. 实现微博的SDK delegate响应
`WeiboSDKVCDelegate.m`
/**
收到一个来自微博客户端程序的请求
收到微博的请求后,第三方应用应该按照请求类型进行处理,处理完后必须通过 [WeiboSDK sendResponse:] 将结果回传给微博
@param request 具体的请求对象
*/
- (void)didReceiveWeiboRequest:(WBBaseRequest *)request{ //向微博发送请求
NSLog(@" %@",request.class);
}
#pragma mark - didReceiveWeiboResponse
/**
微博分享 与 微博登录,成功与否都会走这个方法。 用户根据自己的业务进行处理。
收到一个来自微博客户端程序的响应
收到微博的响应后,第三方应用可以通过响应类型、响应的数据和 WBBaseResponse.userInfo 中的数据完成自己的功能
@param response 具体的响应对象
*/
- (void)didReceiveWeiboResponse:(WBBaseResponse *)response{
NSLog(@"log--didReceiveWeiboResponse:%@",response);
// 此代理方法不可使用 -- 由于AppDelegate中的调用对象和被回调控制器中的对象属于同一个类但不同属于同一对象造成
// if ([_weiboDelegate respondsToSelector:@selector(weiboLoginByResponse:)]) {
// [_weiboDelegate weiboLoginByResponse:response];
// }
// 分享时回调使用
if ([response isKindOfClass:WBSendMessageToWeiboResponse.class])
{
[[NSNotificationCenter defaultCenter]postNotificationName:@"didReceiveWeiboWBSendMessageToWeiboResponse" object:response];
// NSString *title = NSLocalizedString(@"发送结果", nil);
// NSString *message = [NSString stringWithFormat:@"%@: %d\n%@: %@\n%@: %@", NSLocalizedString(@"响应状态", nil), (int)response.statusCode, NSLocalizedString(@"响应UserInfo数据", nil), response.userInfo, NSLocalizedString(@"原请求UserInfo数据", nil),response.requestUserInfo];
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
// message:message
// delegate:nil
// cancelButtonTitle:NSLocalizedString(@"确定", nil)
// otherButtonTitles:nil];
// WBSendMessageToWeiboResponse* sendMessageToWeiboResponse = (WBSendMessageToWeiboResponse*)response;
// NSString* accessToken = [sendMessageToWeiboResponse.authResponse accessToken];
// if (accessToken)
// {
// self.wbtoken = accessToken;
// }
// NSString* userID = [sendMessageToWeiboResponse.authResponse userID];
// if (userID) {
// self.wbCurrentUserID = userID;
// }
// [alert show];
} // 登录时回调使用
else if ([response isKindOfClass:WBAuthorizeResponse.class])
{
// 发送登录成功或者失败或者某种情况的通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"didReceiveWeiboResponseInWBAuthorizeResponse" object:response];
// NSString *title = NSLocalizedString(@"认证结果", nil);
//
// // request/response string
// NSString *message = [NSString stringWithFormat:@"%@: %d\nresponse.userId: %@\nresponse.accessToken: %@\n%@: %@\n%@: %@", NSLocalizedString(@"响应状态", nil), (int)response.statusCode,[(WBAuthorizeResponse *)response userID], [(WBAuthorizeResponse *)response accessToken], NSLocalizedString(@"响应UserInfo数据", nil), response.userInfo, NSLocalizedString(@"原请求UserInfo数据", nil), response.requestUserInfo];
// alert show
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
// message:message
// delegate:nil
// cancelButtonTitle:NSLocalizedString(@"确定", nil)
// otherButtonTitles:nil];
//
// [alert show];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:@"出现错误"
delegate:nil
cancelButtonTitle:NSLocalizedString(@"确定", nil)
otherButtonTitles:nil];
[alert show];
}
}
3. 具体的VC中实现
调⽤SendRequest 的⽅法后会跳转到微博程序。
如果当前微博客户端没有账号,则进⼊登录界⾯;如果当前微博客户端已经有账户,则进⼊账户管理界⾯,选择要向第三⽅授权的账户。
当授权完成后会回调给第三⽅应⽤程序,第三⽅实现WeiboSDKDelegate 的
didReceiveWeiboResponse ⽅式监听此次请求的 response.
此中UserInfo内容为⽤户⾃定义(可不填写),微博回调Response中会 通过
requestUserInfo包含原 request.userInfo 中的所有数据,⽤于第三⽅⾃定义操作或request
区分。
如果最后在实现微博SDK的回调中获得到 error_code=21338 并且出现sso package or login error
那就是因为当前的Bundle ID和微博开放平台注册的应用的Bundle ID不一致导致的。
微博登录
#pragma mark - weibo sdk login
- (void)ssoButtonPressed{
/* SSO 授权认证(有客户端跳转,有网页打开) */
WBAuthorizeRequest *request = [WBAuthorizeRequest request]; //
request.redirectURI = @"https://api.weibo.com/oauth2/default.html"; // 这里的redirectURL 需要与微博开放平台创建的应用的重定向地址一致
request.scope = @"all";
// request.userInfo 可不传 -- 在登录完成后会在回调中返回这里的数据,若未填写
request.userInfo = @{@"ShareMessageFrom": @"WeiboViewController",
@"Other_Info_1": [NSNumber numberWithInt:123],
@"Other_Info_2": @[@"obj1", @"obj2"],
@"Other_Info_3": @{@"key1": @"obj1", @"key2": @"obj2"}};
[WeiboSDK sendRequest:request];
}
#pragma mark NSNotification delegate login use
//登录的代理
- (void)weiboLoginByResponseInWBAuthorize:(NSNotification *)userInfo{
WBAuthorizeResponse *response = userInfo.object;
NSLog(@"log--微博登录代理:%@",response);
// 可能需要使用到的参数
NSString *wbtoken = [response accessToken];
NSString *wbRefreshToken = [response refreshToken];
NSString *wbCurrentUserID = [response userID];
// 赋值
self.wbtoken = wbtoken;
}
- (void)weiboWBSendMessageToWeiboResponse:(NSNotification *)userInfo{
WBSendMessageToWeiboResponse *response = userInfo.object;
NSString *accessToken = [response.authResponse accessToken];
NSString *weCurrentUserID = [response.autoContentAccessingProxy userID];
}
微博登出 ++ 实现相应的 WBHttpRequestDelegate
代理方法
#pragma mark - weibo sdk log out
- (void)ssoOutButtonPressed
{
if (self.wbtoken.length !=0 && self.wbtoken) {
// 需要登录成功是时返回的token
[WeiboSDK logOutWithToken:self.wbtoken delegate:self withTag:@"testUser"];
// 在退出成功清空
// 点击退出登录wbtoken清空
}else{
NSLog(@"您还未登录");
}
}
#pragma mark WBHttpRequestDelegate -- log out use
- (void)request:(WBHttpRequest *)request didFinishLoadingWithResult:(NSString *)result
{
NSString *trueStr = @"{\"result\":\"true\"}";
if ([result isEqualToString:trueStr]) {
self.wbtoken = nil; // 点击退出登录wbtoken清空
}
NSString *title = nil;
UIAlertView *alert = nil;
title = NSLocalizedString(@"收到网络回调", nil);
alert = [[UIAlertView alloc] initWithTitle:title
message:[NSString stringWithFormat:@"%@",result]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"确定", nil)
otherButtonTitles:nil];
[alert show];
}
- (void)request:(WBHttpRequest *)request didFailWithError:(NSError *)error;
{
NSString *title = nil;
UIAlertView *alert = nil;
title = NSLocalizedString(@"请求异常", nil);
alert = [[UIAlertView alloc] initWithTitle:title
message:[NSString stringWithFormat:@"%@",error]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"确定", nil)
otherButtonTitles:nil];
[alert show];
}
微博分享 ++ 实现相应的 WBMediaTransferProtocol
代理方法
#pragma mark - weibo share message
- (void)shareButtonPressed{
// 判断各种情况下是否可以发送 || 在实际使用中可以判定特定的对象是否为空来决定是否执行此次的分享功能
if (!self.textSwitch.on && !self.imageSwitch.on && !self.mediaSwitch.on && !self.videoSwitch.on && !self.storySwitch.on) {
return;
}
if ((self.textSwitch.on || self.mediaSwitch.on) && (!self.imageSwitch.on && !self.videoSwitch.on) && self.storySwitch.on) {
// self.storySwitch.on 打开无意思作用
//只有文字和多媒体的时候打开分享到story开关,只会呼起发布器,没有意义
return;
}
self.messageObject = [self getMessageObject];
if (!self.imageSwitch.on && !self.videoSwitch.on) {
[self messageShare];
}else
{
if (!_indicatorView) {
_indicatorView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
_indicatorView.center = self.view.center;
[self.view addSubview:_indicatorView];
_indicatorView.color = [UIColor blueColor];
}
[_indicatorView startAnimating];
[_indicatorView setHidesWhenStopped:YES];
}
}
- (WBMessageObject *)getMessageObject{
WBMessageObject *message = [WBMessageObject message];
if (self.textSwitch.on)
{
message.text = NSLocalizedString(@"这是测试一条通过WeiboSDK发送文字到微博--testDemo!", nil);
}
if (self.imageSwitch.on)
{
// WBImageObject *image = [WBImageObject object];
// image.imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image_1" ofType:@"jpg"]];
// message.imageObject = image;
UIImage *image = [UIImage imageNamed:@"WeiboSDK.bundle/images/empty_failed.png"];
UIImage *image1 = [UIImage imageNamed:@"WeiboSDK.bundle/images/common_button_white.png"];
UIImage *image2 = [UIImage imageNamed:@"WeiboSDK.bundle/images/common_button_white_highlighted.png"];
NSArray *imageArray = [NSArray arrayWithObjects:image,image1,image2, nil];
WBImageObject *imageObject = [WBImageObject object];
if (self.storySwitch.on) {
imageObject.isShareToStory = YES;
imageArray = [NSArray arrayWithObject:image];
}
imageObject.delegate = self;
[imageObject addImages:imageArray];
message.imageObject = imageObject;
}
if (self.mediaSwitch.on)
{
WBWebpageObject *webpage = [WBWebpageObject object];
webpage.objectID = @"identifier1";
webpage.title = NSLocalizedString(@"分享网页标题", nil);
webpage.description = [NSString stringWithFormat:NSLocalizedString(@"分享网页内容简介-%.0f", nil), [[NSDate date] timeIntervalSince1970]];
webpage.thumbnailData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image_2" ofType:@"jpg"]];
webpage.webpageUrl = @"http://weibo.com/p/1001603849727862021333?rightmod=1&wvr=6&mod=noticeboard";
message.mediaObject = webpage;
}
if (self.videoSwitch.on) {
WBNewVideoObject *videoObject = [WBNewVideoObject object];
if (self.storySwitch.on) {
videoObject.isShareToStory = YES;
}
NSURL *videoUrl = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"apm" ofType:@"mov"]];
videoObject.delegate = self;
[videoObject addVideo:videoUrl];
message.videoObject = videoObject;
}
return message;
}
-(void)messageShare
{
WBAuthorizeRequest *authRequest = [WBAuthorizeRequest request];
authRequest.redirectURI = @"https://api.weibo.com/oauth2/default.html";
authRequest.scope = @"all";
WBSendMessageToWeiboRequest *request = [WBSendMessageToWeiboRequest requestWithMessage:self.messageObject authInfo:authRequest access_token:self.wbtoken];
request.userInfo = @{@"ShareMessageFrom": @"WeiboViewController",
@"Other_Info_1": [NSNumber numberWithInt:456],
@"Other_Info_2": @[@"obj1", @"obj2"],
@"Other_Info_3": @{@"key1": @"obj1", @"key2": @"obj2"}};
if (![WeiboSDK sendRequest:request]) {
[_indicatorView stopAnimating];
}
}
#pragma mark WBMediaTransferProtocol -- share message use
-(void)wbsdk_TransferDidReceiveObject:(id)object
{
[_indicatorView stopAnimating];
[self messageShare];
}
-(void)wbsdk_TransferDidFailWithErrorCode:(WBSDKMediaTransferErrorCode)errorCode andError:(NSError*)error
{
[_indicatorView stopAnimating];
}