简介
这一系列讲述的是免SDK实现分享、登录、支付等业务。
将会使用ShareSDK Demo进行部分试验。
一、拦截分享参数
1、打开ShareSDK Demo,找到AppDelegate.m 添加如下代码
//头文件不要忘
#import <objc/runtime.h>
//对UIApplication的openURL:方法进行hook
-(void)swizzleOpenUrl{
SEL openUrlSEL=@selector(openURL:);
BOOL (*openUrlIMP)(id,SEL,id) =(BOOL(*)(id,SEL,id))[UIApplication instanceMethodForSelector:openUrlSEL];
static int count=0;
BOOL (^myOpenURL)(id SELF,NSURL * url)=^(id SELF,NSURL *url){
//打印出分享的URL
NSLog(@"\n----------open url: %d----------\n%@\n%@\n",count++,url,@"\n"/*[NSThread callStackSymbols]*/);
//获取系统剪切板
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
//打印获取QQ在剪切板的key 得知key为 com.tencent.mqq.api.apiLargeData
NSLog(@"%@",pasteboard.pasteboardTypes);
//获取QQ在剪切板参数 图片与链接分享时才有值
NSData * qqInfoData = [pasteboard valueForPasteboardType:@"com.tencent.mqq.api.apiLargeData"];
//QQ是使用NSKeyedArchiver序列化数据的
//图片分享是会有file_data previewimagedata,链接分享只有previewimagedata
//qqInfoDic:
//{
// "file_data" = NSData数据
// "previewimagedata" = NSData数据
//}
NSDictionary * qqInfoDic = [NSKeyedUnarchiver unarchiveObjectWithData:qqInfoData];
//图片
NSData * file_data = qqInfoDic[@"file_data"];
UIImage * image = [UIImage imageWithData:file_data];
//缩略图 小于32k
NSData * previewimagedata = qqInfoDic[@"previewimagedata"];
UIImage * previewimage = [UIImage imageWithData:previewimagedata];
return (BOOL)openUrlIMP(SELF,openUrlSEL,url);
};
class_replaceMethod([UIApplication class], openUrlSEL, imp_implementationWithBlock(myOpenURL), NULL);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//只要添加这句
[self swizzleOpenUrl];
}
2、查看控制台打印的URL
文字分享
----------open url: 0----------
mqqapi://share/to_fri?thirdAppDisplayName=U2hhcmVTREtEZW1v&shareType=0&file_type=text&callback_name=QQ05FB8B52&src_type=app&file_data=U2hhcmUgU0RL&version=1&cflag=0&callback_type=scheme&generalpastboard=1&sdkv=3.2.1
图片分享 图片存在剪切板里
----------open url: 1----------
mqqapi://share/to_fri?thirdAppDisplayName=U2hhcmVTREtEZW1v&shareType=0&objectlocation=pasteboard&file_type=img&callback_name=QQ05FB8B52&src_type=app&version=1&description=U2hhcmUgU0RL&cflag=0&callback_type=scheme&generalpastboard=1&sdkv=3.2.1
链接分享 图片存在剪切板里
----------open url: 2----------
mqqapi://share/to_fri?file_type=news&generalpastboard=1&src_type=app&version=1&description=U2hhcmUgU0RLIExpbmsgRGVzYw==&callback_type=scheme&url=aHR0cHM6Ly93d3cubW9iLmNvbQ==&shareType=0&title=U2hhcmUgU0RL&thirdAppDisplayName=U2hhcmVTREtEZW1v&callback_name=QQ05FB8B52&objectlocation=pasteboard&cflag=0&sdkv=3.2.1
3、参数解释
//QQ的URL Scheme
mqqapi
//固定开头
share/to_fri
//我们app的名字(这里要对名字做Base64编码)
thirdAppDisplayName
// 0 QQ好友
shareType
// 分享类型
// text(纯文本)、img(图片,可为图文)、news(链接)
file_type
// 例如QQ05FB8B52 QQ是固定写法,05FB8B52是appId
//需要做8位16进制转换(%08llx)
callback_name
// 客户端分享固定写法 src_type=app
src_type
// 版本号 version=1
version
//cflag = 0
cflag
//callback_type=scheme 固定写法
callback_type
// 固定写法 generalpastboard=1
generalpastboard
//SDK版本
sdkv
//带图片的分享,包括链接、图片分享需要用到
//需要把图片放到剪切板里
//objectlocation=pasteboard 固定写法
objectlocation
// 当file_type为text时,file_data为分享内容(内容需要Base64编码)。file_data直接作为URl参数。
// 当file_type为img时,file_data为UIImage的NSData(即需要将UIImage转成NSData)。QQ好友分享只能一张图片。
//file_data需要放到剪切板里。
file_data
//缩略图(QQ好友分享专属字段,小于32k)
//当file_type为img、news时用到。
previewimagedata
//QQ好友图片分享、链接分享。该参数为分享内容(Base64编码)
description
//当file_type为news时用到,该参数为链接标题
title
//当file_type为news时用到,该参数为网页url(Base64编码)
url
二、构造分享参数
代码仅供参考,部分代码做了封装,需要到demo里的TQQPlatform类查看。
//分享到QQ好友
+ (NSString *)shareToQQParameters:(NSMutableDictionary *)parameters appId:(NSString *)appId onStateChanged:(TStateChangedHandler)stateChangedHandler {
if (stateChangedHandler) {
[TQQPlatform shareInstance].stateChangedHandler = stateChangedHandler;
}
if ([TQQPlatform isQQInstalled]) {
NSString * file_type = @"";
TContentType TPlatformType = [[parameters typeForParams] integerValue];
if (TPlatformType == TContentTypeText) {
//文本类型
file_type = @"text";
}
else if (TPlatformType == TContentTypeImage) {
//图片类型
file_type = @"img";
}
else if (TPlatformType == TContentTypeWebPage) {
//链接
file_type = @"news";
}
//公共参数
NSMutableString *qqInfo = [[NSMutableString alloc] initWithString:@"mqqapi://share/to_fri?thirdAppDisplayName="];
[qqInfo appendString:[NSString base64Encode:kCFBundleDisplayName]];
[qqInfo appendString:@"&shareType=0"];
[qqInfo appendString:@"&file_type="];
[qqInfo appendString:file_type];
[qqInfo appendString:@"&callback_name="];
[qqInfo appendString:[NSString stringWithFormat:@"QQ%08llx",[appId longLongValue]]];
[qqInfo appendString:@"&src_type=app"];
[qqInfo appendString:@"&version=1"];
[qqInfo appendString:@"&cflag=0"];
[qqInfo appendString:@"&callback_type=scheme"];
[qqInfo appendString:@"&sdkv=3.2.1"];
[qqInfo appendString:@"&generalpastboard=1"];
//纯文本时才会有file_data字段
if ([file_type isEqualToString:@"text"]) {
[qqInfo appendString:@"&file_data="];
[qqInfo appendString:[NSString base64Encode:[parameters textForParams]]];
}
//图片分享、链接分享
if ([file_type isEqualToString:@"text"] == NO) {
[qqInfo appendString:@"&objectlocation=pasteboard"];
[qqInfo appendString:@"&description="];
[qqInfo appendString:[NSString base64Encode:[parameters textForParams]]];
[qqInfo appendString:@"&title="];
[qqInfo appendString:[NSString base64Encode:[parameters titleForParams]]];
//图片集合,传入参数可以为UIImage、数组(UIImage、NSString(图片路径)、NSURL(图片路径))
NSMutableArray * img = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:NO];
//如果缩略图为空 就使用大图压缩
NSMutableArray * thumbImg = [parameters thumbImageForParams] == nil ? [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES] : [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
NSDictionary *data = nil;
if ([file_type isEqualToString:@"img"]) {
//图片分享 QQ好友只支持一张,默认选取数组第0位置图片
data=@{@"file_data":img[0],
@"previewimagedata":thumbImg[0]};
}
else if ([file_type isEqualToString:@"news"]) {
//链接分享 QQ好友只支持一张,默认选取数组第0位置图片
data=@{@"previewimagedata":thumbImg[0]};
}
[UIPasteboard setPasteboard:@"com.tencent.mqq.api.apiLargeData" value:data encoding:TPboardEncodingKeyedArchiver];
}
//链接分享
if ([file_type isEqualToString:@"news"]) {
[qqInfo appendString:@"&url="];
[qqInfo appendString:[NSString base64Encode:[parameters[@"URL"] absoluteString]]];
}
return qqInfo;
}
else {
if (stateChangedHandler) {
NSError * err = [NSError errorWithDomain:@"TrochilusErrorDomain" code:-1001 userInfo:@{@"error_message":@"分享平台[QQ]尚未安装QQ或者QQ空间客户端!无法进行分享!"}];
stateChangedHandler(TResponseStateFail,nil,err);
}
}
return nil;
}
三、发起请求
代码仅供参考,部分代码做了封装,需要到demo里的Trochilus类查看。
+ (void)share:(TPlatformType)platformType parameters:(NSMutableDictionary *)parameters onStateChanged:(TStateChangedHandler)stateChangedHandler {
NSString * shareUrl = @"";
switch (platformType) {
case TPlatformSubTypeQQFriend: {
shareUrl = [TQQPlatform shareToQQParameters:parameters
appId:[self platformForKey:@"QQ"][@"appId"]
onStateChanged:^(TResponseState state, NSDictionary *userData, NSError *error) {
if (stateChangedHandler) {
stateChangedHandler(state,userData,error);
}
}];
}
break;
default:
break;
}
[Trochilus sendToURL:shareUrl];
}
+ (void)sendToURL:(NSString *)url {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
});
}
四、QQ客户端回调
代码仅供参考,部分代码做了封装,需要到demo里的TQQPlatform类查看。
//回调
+ (BOOL)handleUrlWithQQ:(NSURL *)url {
if ([url.scheme hasPrefix:@"QQ"]) {
//分享
NSDictionary *dic=[NSMutableDictionary dictionaryWithUrl:url];
if (dic[@"error_description"]) {
[dic setValue:[NSString base64Decode:dic[@"error_description"]] forKey:@"error_description"];
}
if ([dic[@"error"] intValue] == -4) {
if ([TQQPlatform shareInstance].stateChangedHandler) {
[TQQPlatform shareInstance].stateChangedHandler(TResponseStateCancel, nil, nil);
}
}
else if ([dic[@"error"] intValue] == 0) {
//分享成功
if ([TQQPlatform shareInstance].stateChangedHandler) {
[TQQPlatform shareInstance].stateChangedHandler(TResponseStateSuccess, nil, nil);
}
}
else{
//分享失败 失败是什么状态 我也不知道 等测试到再说
NSError *err=[NSError errorWithDomain:@"QQErrorDomain" code:[dic[@"error"] intValue] userInfo:dic];
if ([TQQPlatform shareInstance].stateChangedHandler) {
[TQQPlatform shareInstance].stateChangedHandler(TResponseStateFail, nil, err);
}
}
return YES;
}
return NO;
}
五、参考资料
https://github.com/100apps/openshare
六、Demo
https://github.com/quanweiwang/Trochilus
目录
分享篇
1、我的APP不可能这么胖之QQ好友分享
2、我的APP不可能这么胖之QQ空间分享
3、我的APP不可能这么胖之微信好友分享
4、我的APP不可能这么胖之微信朋友圈分享
5、我的APP不可能这么胖之新浪微博分享
登录篇
6、我的APP不可能这么胖之QQ登录
7、我的APP不可能这么胖之微信登录
8、我的APP不可能这么胖之新浪微博登录
支付篇
9、我的APP不可能这么胖之微信支付
10、我的APP不可能这么胖之支付宝支付
网友评论