iOS--原生接入微博、微信和QQ的登錄及分享

關(guān)于第三方的登錄及分享,網(wǎng)上已經(jīng)有很多集成好的框架,比如友盟和Mob。但是呢,有一個(gè)地方得注意,不過(guò)這個(gè)得看產(chǎn)品經(jīng)理了,有些要求比較高,看下圖
友盟QQ登錄
集成三方框架,默認(rèn)會(huì)獲取紅框內(nèi)那些信息。不管是友盟還是Mob,都有這個(gè)問(wèn)題,這個(gè)與技術(shù)客服確認(rèn)過(guò),說(shuō)是騰訊那邊要求的。一般我們只需要獲取用戶的基礎(chǔ)資料即可。考慮到這點(diǎn),再加上包的大小,So,擼起袖子自己接SDK了~~
我比較懶,凡是能用cocoapods導(dǎo)入的,絕不會(huì)手動(dòng)導(dǎo)入,因?yàn)樘砑右蕾噹?kù)什么的,一不小心就bia幾崩潰了。(注意:記得把微博測(cè)試賬號(hào)添加進(jìn)去,不然授權(quán)會(huì)失敗)
  • 去各個(gè)平臺(tái)注冊(cè)應(yīng)用,獲取相應(yīng)的應(yīng)用Id并在Target--> Info-->URL Types 添加各個(gè)平臺(tái)的應(yīng)用Id。
    微博:wb'你的應(yīng)用Id'
    微信:wx'你的應(yīng)用Id'
    QQ: tencent'你的應(yīng)用Id'QQ'你的應(yīng)用Id轉(zhuǎn)十六進(jìn)制'

AppKey轉(zhuǎn)成十六進(jìn)制方法,直接在終端輸入
echo 'ibase=10;obase=16;您的騰訊QQ互聯(lián)應(yīng)用Id'|bc

URL Types配置
  • 針對(duì)iOS9默認(rèn)使用https,現(xiàn)在先還原成http請(qǐng)求方式。

在Info.plist中添加NSAppTransportSecurity類型Dictionary。
在NSAppTransportSecurity下添加NSAllowsArbitraryLoads類型Boolean,值設(shè)為YES

  • 在info里配置以下scheme
    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>mqqOpensdkSSoLogin</string>
        <string>mqzone</string>
        <string>mqq</string>
        <string>mqqapi</string>
        <string>mqqopensdkapiV3</string>
        <string>mqqopensdkapiV2</string>
        <string>mqqapiwallet</string>
        <string>mqqwpa</string>
        <string>mqqbrowser</string>
        <string>wtloginmqq2</string>
        <string>sinaweibo</string>
        <string>sinaweibohd</string>
        <string>sinaweibosso</string>
        <string>sinaweibohdsso</string>
        <string>weibosdk</string>
        <string>weibosdk2.5</string>
        <string>weixin</string>
        <string>wechat</string>
    </array>
 
  • 導(dǎo)入sdk(cocoapods的用法這里我就不介紹了)
    pod 'TencentOpenApiSDK'
    pod 'WeiboSDK'
    pod 'WechatOpenSDK'
  • 代碼接入
在AppDelegate中導(dǎo)入頭文件
#import <TencentOpenAPI/TencentOAuth.h>
#import <TencentOpenAPI/QQApiInterface.h>
#import "WXApi.h"

@interface AppDelegate ()<QQApiInterfaceDelegate,WXApiDelegate,WeiboSDKDelegate>

@end

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [WXApi registerApp:@"您的應(yīng)用Id"];
    [WeiboSDK registerApp:@"您的應(yīng)用Id"];
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    
    if ([url.absoluteString hasPrefix:@"tencent"]) {
        [QQApiInterface handleOpenURL:url delegate:self];
        return [TencentOAuth HandleOpenURL:url];
    }else if ([url.absoluteString hasPrefix:@"wx"]){
        [WXApi handleOpenURL:url delegate:(id<WXApiDelegate>)self];
    }else if ([url.absoluteString hasPrefix:@"wb"]){
        [WeiboSDK handleOpenURL:url delegate:self];
    }
    
    return YES;
}

// 處理來(lái)自微信和QQ的響應(yīng)(方法名相同,合并,用id接收參數(shù))
- (void)onResp:(id )resp {
    //WX授權(quán)登錄的類。
    if ([resp isKindOfClass:[SendAuthResp class]]) {   
        SendAuthResp *response = (SendAuthResp *)resp;
        if (response.errCode == 0) {
            // 微信登錄成功
            SendAuthResp *aresp = (SendAuthResp *)resp;
            NSString *code = aresp.code;
            //@TODO 這個(gè)code需要保存下來(lái)傳給后臺(tái)
        }else{
            // 微信登錄失敗
            NSLog(@"error %@",response.errStr);
        }
    }
    //微信分享 微信回應(yīng)給第三方應(yīng)用程序的類
    if ([resp isKindOfClass:[SendMessageToWXResp class]]) { 
        SendMessageToWXResp *response = (SendMessageToWXResp *)resp;
        NSLog(@"error code %d  error msg %@  lang %@   country %@",response.errCode,response.errStr,response.lang,response.country);
        if (response.errCode == 0) {
            // 分享成功
        }else{
            // 分享失敗
        }
    }
    //QQ分享回調(diào)
    if ([resp isKindOfClass: [SendMessageToQQResp class]]) {  
        SendMessageToQQResp * tmpResp = (SendMessageToQQResp *)resp;
        if (tmpResp.type == ESENDMESSAGETOQQRESPTYPE && [tmpResp.result integerValue] == 0) {
            // 分享成功
        }else {
            // 分享失敗
        }
    }
}

// 處理來(lái)自微博的響應(yīng)
- (void)didReceiveWeiboResponse:(WBBaseResponse *)response {
    //用戶登錄的回調(diào)
    if ([response isKindOfClass:WBAuthorizeResponse.class]) {  
        NSLog(@"用戶登錄的回調(diào) = 微博 userInfo = %@",response.userInfo);
        if (response.statusCode == WeiboSDKResponseStatusCodeSuccess) {
            NSDictionary *userInfo = response.userInfo;
            NSString *accessToken=[userInfo objectForKey:@"access_token"];
            //@TODO 微博返回的access_token需要保存下來(lái)給后臺(tái)
         }else {
            //登錄失敗
        }
    }
    //微博分享的回調(diào)
    if ([response isKindOfClass:WBSendMessageToWeiboResponse.class]) {  
        WBSendMessageToWeiboResponse *res = (WBSendMessageToWeiboResponse *)response;
        NSLog(@"weibo response %ld",(long)res.statusCode);
    }
}

// 處理來(lái)自QQ的請(qǐng)求(貌似用不到)
- (void)onReq:(QQBaseReq *)req {
       NSLog(@"%@",req);
}

/* 處理來(lái)自QQ的響應(yīng) 方法名沖突 與微信合并
- (void)onResp:(QQBaseResp *)resp {
}
*/

// 處理QQ在線狀態(tài)的回調(diào)(貌似用不到)
- (void)isOnlineResponse:(NSDictionary *)response {
}

// 處理來(lái)自微博的請(qǐng)求(貌似用不到)
- (void)didReceiveWeiboRequest:(WBBaseRequest *)request {
}

===========登錄==========

#import <TencentOpenAPI/TencentOAuth.h>
#import "WXApi.h"
#import "WeiboSDK.h"

@interface LoginVC ()<TencentSessionDelegate>
{
    TencentOAuth *_tencentOAuth;
    NSMutableArray *_permissionArray; //權(quán)限列表
}

@implementation LoginVC
#pragma mark -------- 第三方登錄 --------
// 微信登錄
- (IBAction)weixinLoginAct:(id)sender {
    if ([WXApi isWXAppInstalled]) {
        //構(gòu)造SendAuthReq結(jié)構(gòu)體
        SendAuthReq* req =[[SendAuthReq alloc] init] ;
        req.scope = @"snsapi_userinfo,snsapi_base";
        req.state = @"0744";
        //第三方向微信終端發(fā)送一個(gè)SendAuthReq消息結(jié)構(gòu)
        [WXApi sendReq:req];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝微信"];
    }
}
//QQ登錄
- (IBAction)qqLoginAct:(id)sender {
    if ([TencentOAuth iphoneQQInstalled]) {
        _tencentOAuth = [[TencentOAuth alloc] initWithAppId:kQQ_APP_ID andDelegate:self];
        //設(shè)置權(quán)限
        _permissionArray = [NSMutableArray arrayWithObjects:kOPEN_PERMISSION_GET_USER_INFO, nil];
        _tencentOAuth.redirectURI=@"www.qq.com";
        // 登錄操作
        [_tencentOAuth authorize:_permissionArray inSafari:YES];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝QQ"];
    }
}
//微博登錄
- (IBAction)sinaLoginAct:(id)sender {
    if ([WeiboSDK isWeiboAppInstalled]) {
        WBAuthorizeRequest *request = [WBAuthorizeRequest request];
        request.redirectURI = kWB_REDIRECT_URL;
        request.scope = @"all";
        request.userInfo = @{@"SSO_From": @"LoginVC",
                             @"Other_Info_1": [NSNumber numberWithInt:123],
                             @"Other_Info_2": @[@"obj1", @"obj2"],
                             @"Other_Info_3": @{@"key1": @"obj1", @"key2": @"obj2"}};
        [WeiboSDK sendRequest:request];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝微博"];
    }
}

#pragma mark -------- 登錄回調(diào) --------
//success 回調(diào)
- (void)tencentDidLogin {
    
    /* Access Token憑證,用于后續(xù)訪問(wèn)各開放接口*/
    if (_tencentOAuth.accessToken) {
        
        NSLog(@"accessToken is %@---openId:%@",_tencentOAuth.accessToken,_tencentOAuth.openId);

        // 獲取用戶信息。調(diào)用這個(gè)方法,qq的sdk會(huì)自動(dòng)調(diào)用
        // - (void)getUserInfoResponse:(APIResponse *)response
        // 這個(gè)方法就是用戶信息的回調(diào)方法
        [_tencentOAuth getUserInfo];
        //@TODO 走自己服務(wù)器的登錄流程
    }else {
        NSLog(@"accessToken 沒有獲取成功");
    }
}

//fail
- (void)tencentDidNotLogin:(BOOL)cancelled {
    if (cancelled) {
        NSLog(@"用戶點(diǎn)擊取消按鈕,主動(dòng)退出登錄");
    }else {
        NSLog(@"其他原因,導(dǎo)致登錄失敗");
    }
}

//登錄時(shí)網(wǎng)絡(luò)有問(wèn)題的回調(diào)
- (void)tencentDidNotNetWork {
    NSLog(@"沒有網(wǎng)絡(luò)啦啦啦啦啦");
}

/**
 獲取用戶信息的回調(diào)
 @param response .jsonResponse里面是用戶詳細(xì)
 nickname  昵稱
 gender    性別
 figureurl 頭像
 */
- (void)getUserInfoResponse:(APIResponse *)response {
    NSLog(@"user info is %@", response.jsonResponse);
}
@end
這里講一下我們項(xiàng)目里的登錄流程

1.分別調(diào)用三方SDK,登錄成功后在能在回調(diào)里得到所需要的東西。微博會(huì)返回一個(gè)access_Token,微信返回一個(gè)code,QQ要返回一個(gè)code和openId。
2.把以上獲得的字段通過(guò)自己服務(wù)器的登錄接口傳給后臺(tái),后臺(tái)再去調(diào)用各個(gè)平臺(tái)獲取用戶信息的接口并和自己服務(wù)器的賬戶體系綁定。

===========分享==========

一般我們分享都是采用文字+圖片+url鏈接,微信和QQ都比較簡(jiǎn)單,但是微博規(guī)定多媒體(url鏈接)與圖片不可以同時(shí)存在,下面會(huì)提到在這種情況下如何實(shí)現(xiàn)鏈接分享。
導(dǎo)入以下頭文件,并聲明tencentOAuth
.h
#import <TencentOpenAPI/QQApiInterfaceObject.h>
#import <TencentOpenAPI/QQApiInterface.h>
#import <TencentOpenAPI/TencentOAuth.h>
#import "weiboSDK.h"
#import "WXApi.h"

@property (nonatomic, strong) TencentOAuth *tencentOAuth;

.m
#pragma mark -------- wx share --------
- (void)shareToWeChatFriend:(UIButton *)btn {
    if ([WXApi isWXAppInstalled] && [WXApi isWXAppSupportApi]) {
        SendMessageToWXReq *sendReq = [[SendMessageToWXReq alloc] init];
        sendReq.bText = NO;//不使用文本信息
        sendReq.scene = 0;//0 = 好友列表; 1 = 朋友圈 ;2 = 收藏
        //創(chuàng)建分享內(nèi)容對(duì)象
        WXMediaMessage *urlMessage = [WXMediaMessage message];
        urlMessage.title = @"分享的標(biāo)題";//分享標(biāo)題
        urlMessage.description = @"分享的內(nèi)容";//分享描述
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"分享的圖片url"]];
        [urlMessage setThumbImage:[UIImage imageWithData:data]];//分享圖片,使用SDK的setThumbImage方法可壓縮圖片大小
        //創(chuàng)建多媒體對(duì)象
        WXWebpageObject *webObj = [WXWebpageObject object];
        webObj.webpageUrl = @"分享鏈接url";//分享鏈接
        //完成發(fā)送對(duì)象實(shí)例
        urlMessage.mediaObject = webObj;
        sendReq.message = urlMessage;
        [WXApi sendReq:sendReq];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝微信"];
    }
}

#pragma mark -------- qq share --------
- (void)shareToQQ:(UIButton *)btn {
    if ([TencentOAuth iphoneQQInstalled]) {
        self.tencentOAuth = [[TencentOAuth alloc] initWithAppId:kQQ_APP_ID andDelegate:nil];
        NSURL *pageURL = [NSURL URLWithString:@"分享鏈接url"];
        NSURL *previewURL = [NSURL URLWithString:@"分享的圖片url"];
        QQApiNewsObject *newsObjc = [QQApiNewsObject objectWithURL: pageURL title:@"分享的標(biāo)題" description:@"分享的內(nèi)容" previewImageURL:previewURL];
        [newsObjc setCflag:kQQAPICtrlFlagQQShare];
        SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObjc];
        QQApiSendResultCode sent = [QQApiInterface sendReq:req];
        [self handleSendResult:sent];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝QQ"];
    }
}

- (void)shareToQZone:(UIButton *)btn {
    if ([TencentOAuth iphoneQQInstalled]) {
        self.tencentOAuth = [[TencentOAuth alloc] initWithAppId:kQQ_APP_ID andDelegate:nil];
        NSURL *pageURL = [NSURL URLWithString:@"分享鏈接url"];
        NSURL *imgURL = [NSURL URLWithString:@"分享的圖片url"];
        QQApiNewsObject *objc = [QQApiNewsObject objectWithURL:pageURL title:@"分享的標(biāo)題" description:@"分享的內(nèi)容" previewImageURL:imgURL];
        [objc setCflag:kQQAPICtrlFlagQZoneShareOnStart];
        SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:objc];
        QQApiSendResultCode sent = [QQApiInterface SendReqToQZone:req];
        [self handleSendResult:sent];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝QQ"];
    }
}

#pragma mark -------- weibo share --------
- (void)shareToWeibo:(UIButton *)btn {
    if ([WeiboSDK isWeiboAppInstalled]) {
        WBMessageObject *message = [WBMessageObject message];
       // 把網(wǎng)頁(yè)鏈接拼接在標(biāo)題里,微博會(huì)自動(dòng)識(shí)別
        message.text = [NSString stringWithFormat:@"%@%@",分享的標(biāo)題,分享鏈接url];
        WBImageObject *imgObject = [WBImageObject object];
        imgObject.imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_imgURLStr]];
        message.imageObject = imgObject;
        WBAuthorizeRequest *authRequest = [WBAuthorizeRequest request];
        authRequest.redirectURI = kWB_REDIRECT_URL;
        authRequest.scope = @"all";
        WBSendMessageToWeiboRequest *request = [WBSendMessageToWeiboRequest requestWithMessage:message authInfo:authRequest access_token:nil];
        request.userInfo = @{@"ShareMessageFrom": @"ShareManager",
                             @"Other_Info_1": [NSNumber numberWithInt:123],
                             @"Other_Info_2": @[@"obj1", @"obj2"],
                             @"Other_Info_3": @{@"key1": @"obj1", @"key2": @"obj2"}};
        //    request.shouldOpenWeiboAppInstallPageIfNotInstalled = NO;
        [WeiboSDK sendRequest:request];
    }else {
        [MBProgressHUD showErrorMsg:@"未安裝微博"];
    }
}

#pragma mark -------- privite method --------
- (void)handleSendResult:(QQApiSendResultCode)sendResult {

    if (sendResult == EQQAPISENDSUCESS) {
        
        NSLog(@"分享成功--- %d",sendResult);
    }else {
        NSLog(@"分享失敗--- %d",sendResult);
    }
}
關(guān)于第三方登錄與分享,差不多就這些。所有代碼都已附上,所以demo就不上傳了。有問(wèn)題歡迎在下面留言,希望對(duì)你有幫助。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,687評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容