關(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);
}
}