简介
这一系列讲述的是免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];
//打印获取微信在剪切板的key 得知key为 content
NSLog(@"%@",pasteboard.pasteboardTypes);
//获取微信在剪切板参数 微信所有内容都放在剪切板里,这与QQ是不同的
NSData * wechatInfoData = [pasteboard valueForPasteboardType:@"content"];
//微信是使用NSPropertyListSerialization做序列化的,这与QQ是不同的
NSDictionary * wechatInfo = [NSPropertyListSerialization propertyListWithData:wechatInfoData options:0 format:NULL error:nil];
NSLog(@"%@",wechatInfo);
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
//weixin 微信 url scheme
//app 固定写法
//wx4868b35061f87885 app id
//sendreq 固定写法
weixin://app/wx4868b35061f87885/sendreq/?
3、参数解释
以下为微信好友分享参数,需要放到剪切板里
//外壳一个字典
{
//微信app id
wx4868b35061f87885 = {
//文字分享为1020 其余都是1010
command = 1020;
//固定写法
result = 1;
//固定写法
returnFromApp = 0;
//0 微信好友 1微信朋友圈
scene = 0;
//sdk版本号
sdkver = "1.7.7";
//文字分享时为分享内容
//链接、网络音频、网络视频、应用消息、表情、文件时为标题
title = "Share SDK";
//图片、链接、音频、视频、应用消息、表情、文件时为分享内容
description = "Share SDK";
//图片分享时为分享图片的NSData数据(微信好友只能一张)
//应用分享时为未知
//表情分享时为分享表情的NSData数据(微信好友只能一张)
//文件分享时为分享文件的NSData数据
fileData = NSData数据
//图片分享为 2
//链接分享为 5
//网络音频分享为 3
//网络视频分享为 4
//应用消息分享为 7
//表情分享为 8
//文件分享为 6
//小程序分享为 36
objectType = 2;
//缩略图(小于32kb)
//图片、链接、音频、视频、应用消息、表情、文件、小程序使用
thumbData = NSData数据
//链接时为网页地址
//网络音频时为网络音频地址
//网络视频时为网络音频地址
//应用消息时为网页地址
mediaUrl = "https://www.mob.com";
//扩展信息 应用消息分享时用到
extInfo = "<xml>extend info</xml>";
//小程序用到 跳转到页面路径
appBrandPath = "/page/API/pages/share/share";
//小程序用到 小程序的名称
appBrandUserName = "gh_d43f693ca31f";
//文件分享时用到 为文件类型
fileExt = mp4
};
}
二、构造分享参数
代码仅供参考,部分代码做了封装,需要到demo里的TWeChatPlatform类查看。
//微信好友分享
+ (NSString *)shareToWechatSessionParameters:(NSMutableDictionary *)parameters appId:(NSString *)appId onStateChanged:(TStateChangedHandler)stateChangedHandler {
[TWeChatPlatform shareInstance].appid = appId;
if (stateChangedHandler) {
[TWeChatPlatform shareInstance].stateChangedHandler = stateChangedHandler;
}
if ([TWeChatPlatform isWeChatInstalled]) {
TContentType TPlatformType = [[parameters typeForParams] integerValue];
NSDictionary * wechatDic = nil;
if (TPlatformType == TContentTypeText) {
//文本
wechatDic = @{@"command" : @"1020",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"title" : [parameters textForParams]};
}
else if (TPlatformType == TContentTypeImage && [parameters emoticonDataForParams] == nil) {
//图片
NSAssert([parameters imagesForParams], @"图片分享,图片不能为空");
NSArray * imageArray = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:NO];
NSArray * thumbData = [parameters thumbImageForParams] == nil ? [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES] : [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"fileData" : imageArray[0],
@"objectType" : @"2",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"thumbData" : thumbData[0]
};
}
else if (TPlatformType == TContentTypeWebPage) {
//链接
NSArray * thumbData;
if ([parameters thumbImageForParams] == nil && [parameters imagesForParams] != nil) {
//缩略图为空 大图不为空
thumbData = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES];
}
else {
//缩略图 或者 没缩略图都走这个
thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
}
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"thumbData" : thumbData[0],
@"mediaUrl" : [parameters urlForParams].absoluteString,
@"objectType" : @"5",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"title" : [parameters titleForParams]
};
}
else if (TPlatformType == TContentTypeAudio) {
//音频
NSArray * thumbData;
if ([parameters thumbImageForParams] == nil && [parameters imagesForParams] != nil) {
//缩略图为空 大图不为空
thumbData = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES];
}
else {
//缩略图 或者 没缩略图都走这个
thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
}
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"thumbData" : thumbData[0],
@"mediaUrl" : [parameters urlForParams].absoluteString,
@"objectType" : @"3",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"title" : [parameters titleForParams]
};
}
else if (TPlatformType == TContentTypeVideo) {
//视频
NSArray * thumbData;
if ([parameters thumbImageForParams] == nil && [parameters imagesForParams] != nil) {
//缩略图为空 大图不为空
thumbData = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES];
}
else {
//缩略图 或者 没缩略图都走这个
thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
}
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"thumbData" : thumbData[0],
@"mediaUrl" : [parameters urlForParams].absoluteString,
@"objectType" : @"4",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"title" : [parameters titleForParams]
};
}
else if (TPlatformType == TContentTypeApp) {
//应用消息
NSArray * thumbData;
if ([parameters thumbImageForParams] == nil && [parameters imagesForParams] != nil) {
//缩略图为空 大图不为空
thumbData = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES];
}
else {
//缩略图 或者 没缩略图都走这个
thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
}
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"thumbData" : thumbData[0],
@"mediaUrl" : [parameters urlForParams].absoluteString,
@"objectType" : @"7",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"title" : [parameters titleForParams],
@"extInfo" : [parameters extInfoForParams],
@"fileData" : [parameters fileDataForParams]
};
}
else if (TPlatformType == TContentTypeImage && [parameters emoticonDataForParams]) {
//表情图片
NSAssert([parameters emoticonDataForParams], @"emoticonData 不能为空,传表情图片");
NSData * imageData = [NSData dataWithContentsOfFile:[parameters emoticonDataForParams]];
NSArray * thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
wechatDic = @{@"command" : @"1010",
@"description" : [parameters textForParams],
@"fileData" : imageData,
@"objectType" : @"8",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"thumbData" : thumbData[0]
};
}
else if (TPlatformType == TContentTypeFile) {
//文件 仅微信可用
NSArray * thumbData;
if ([parameters thumbImageForParams] == nil && [parameters imagesForParams] != nil) {
//缩略图为空 大图不为空
thumbData = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES];
}
else {
//缩略图 或者 没缩略图都走这个
thumbData = [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
}
NSAssert([parameters sourceFileData], @"文件路径不能为空");
NSString * sourceFile = [parameters sourceFileData];
NSData * sourceFileData = [NSData dataWithContentsOfFile:sourceFile];
wechatDic = @{@"command" : @"1010",
@"fileData" : sourceFileData,
@"objectType" : @"6",
@"result" : @"1",
@"returnFromApp" : @"0",
@"scene" : @"0",
@"sdkver" : @"1.7.7",
@"thumbData" : thumbData[0],
@"fileExt" : [parameters sourceFileExtension],
@"title" : [parameters titleForParams],
@"description" : [parameters textForParams]
};
}
[UIPasteboard setPasteboard:@"content" value:@{appId : wechatDic} encoding:TPboardEncodingPropertyListSerialization];
return [NSString stringWithFormat:@"weixin://app/%@/sendreq/?",appId];
}
else {
if (stateChangedHandler) {
NSError * err = [NSError errorWithDomain:@"TrochilusErrorDomain" code:-1002 userInfo:@{@"error_message":@"分享平台[微信]尚未安装客户端!无法进行分享!"}];
stateChangedHandler(TResponseStateFail,nil,err);
}
}
return nil;
}
三、发起请求
代码仅供参考,部分代码做了封装,需要到demo里的Trochilus类查看。
+ (void)share:(TPlatformType)platformType parameters:(NSMutableDictionary *)parameters onStateChanged:(TStateChangedHandler)stateChangedHandler {
NSString * shareUrl = @"";
switch (platformType) {
case TPlatformSubTypeWechatSession: {
//微信朋友
shareUrl = [TWeChatPlatform shareToWechatSessionParameters:parameters
appId:[self platformForKey:weChat][@"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]];
});
}
四、微信客户端回调
代码仅供参考,部分代码做了封装,需要到demo里的TWeChatPlatform类查看。
微信的分享返回值也是放在剪切板里。
+ (BOOL)handleUrlWithWeChat:(NSURL *)url {
if ([url.scheme hasPrefix:@"wx"]) {
//获取剪切板内容
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
NSLog(@"%@",pasteboard.pasteboardTypes);
//微信分享
// {
// wx4868b35061f87885 = {
// command = 2020;
// country = CN;
// language = "zh_CN";
// result = 0;
// returnFromApp = 0;
// sdkver = "1.5";
// };
// }
//获取剪切板内容 content 是通过上面打印得知的
NSData * wechatData = [pasteboard valueForPasteboardType:@"content"];
//微信的NSData序列号方式为NSPropertyListSerialization
NSDictionary * wechatInfo = [NSPropertyListSerialization propertyListWithData:wechatData options:0 format:NULL error:nil];
NSLog(@"%@",wechatInfo);
//获取微信返回值
NSDictionary * wechatResponse = wechatInfo[[TWeChatPlatform shareInstance].appid];
if ([wechatResponse[@"result"] integerValue] == 0) {
//分享成功
if ([TWeChatPlatform shareInstance].stateChangedHandler) {
[TWeChatPlatform shareInstance].stateChangedHandler(TResponseStateSuccess,nil,nil);
}
}
else if ([wechatResponse[@"result"] integerValue] == -2) {
//用户点击取消并返回
if ([TWeChatPlatform shareInstance].stateChangedHandler) {
[TWeChatPlatform shareInstance].stateChangedHandler(TResponseStateCancel,nil,nil);
}
}
else {
//分享失败
NSError * err = [NSError errorWithDomain:@"WechatDomain" code:[wechatResponse[@"result"] integerValue] userInfo:wechatResponse];
if ([TWeChatPlatform shareInstance].stateChangedHandler) {
[TWeChatPlatform 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不可能这么胖之支付宝支付
网友评论