Repository: mozillo/react-native-open-share Branch: master Commit: b72b86f352cf Files: 18 Total size: 56.9 KB Directory structure: gitextract_yyd66mot/ ├── README.md ├── index.js ├── package.json └── src/ ├── OpenShare+Alipay.h ├── OpenShare+Alipay.m ├── OpenShare+QQ.h ├── OpenShare+QQ.m ├── OpenShare+Renren.h ├── OpenShare+Renren.m ├── OpenShare+Weibo.h ├── OpenShare+Weibo.m ├── OpenShare+Weixin.h ├── OpenShare+Weixin.m ├── OpenShare.h ├── OpenShare.m ├── OpenShareHeader.h ├── SocietyLoginManager.h └── SocietyLoginManager.m ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # react-native-open-share Integrate wechat,weibo,qq,alipay [share,payment,login] to your react native application. ### built from [OpenShare](https://github.com/100apps/openshare) ## Screen Shot ##Installation 1.Run `npm install https://github.com/mozillo/react-native-open-share.git --save` in your project directory. 2.Select your project , and find your [ ProjectName ] directory , Select it and right click "New Group", and rename it to "OpenShare", right click "Add Files to 'App' ...", select all files under the ./node_modules/react-native-open-share/src/ directory , and added them to OpenShare group. 3.Edit Info.plist, Open As => Source code, append ***new Info.plist code*** content after ``` ``` new Info.plist code: ``` CFBundleURLTypes CFBundleURLName RNShare CFBundleURLSchemes wxd930ea5d5a258f4f tencent1103194207 tencent1103194207.content QQ41C1685F wb402180334 renrenshare228525 fb776442542471056 ``` 4.Edit AppDelegate.m : Add header file: ``` #import "OpenShareHeader.h" ``` Add these code to "(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions" : ``` [OpenShare connectQQWithAppId:@"1103194207"]; [OpenShare connectWeiboWithAppKey:@"402180334"]; [OpenShare connectWeixinWithAppId:@"wxd930ea5d5a258f4f"]; [OpenShare connectRenrenWithAppId:@"228525" AndAppKey:@"1dd8cba4215d4d4ab96a49d3058c1d7f"]; ``` and add this method after "(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions" block: ``` -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ //第二步:添加回调 if ([OpenShare handleOpenURL:url]) { return YES; } //这里可以写上其他OpenShare不支持的客户端的回调,比如支付宝等。 return YES; } ``` ###Done. ## Usage example: ``` 'use strict'; var React = require('react-native'); var { AppRegistry, StyleSheet, Text, View, TouchableOpacity, DeviceEventEmitter, AlertIOS, } = React; var openShare = require('react-native-open-share'); var App = React.createClass({ _wechatLogin: function() { var _this = this; openShare.wechatLogin(); if(!_this.wechatLogin) { _this.wechatLogin = DeviceEventEmitter.addListener( 'managerCallback', (response) => { AlertIOS.alert( 'response', JSON.stringify(response) ); _this.wechatLogin.remove(); delete _this.wechatLogin; } ); } }, render: function() { return ( WeChat Login Welcome to React Native! To get started, edit index.ios.js Press Cmd+R to reload,{'\n'} Cmd+D or shake for dev menu ); } }); var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, }); AppRegistry.registerComponent('App', () => App); ``` ## current API ``` openShare.qqLogin(); openShare.wechatLogin(); openShare.weiboLogin(); ``` ##Other ``` wechat access token request: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code wechat user profile request: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID ================================================ FILE: index.js ================================================ module.exports = require('react-native').NativeModules.SocietyLoginManager ================================================ FILE: package.json ================================================ { "name": "react-native-open-share", "version": "0.1.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/mozillo/react-native-open-share.git" }, "keywords": [ "share", "react-native" ], "author": "mozillo", "license": "ISC", "bugs": { "url": "https://github.com/mozillo/react-native-open-share/issues" }, "homepage": "https://github.com/mozillo/react-native-open-share#readme" } ================================================ FILE: src/OpenShare+Alipay.h ================================================ // // OpenShare+Alipay.h // openshare // // Created by LiuLogan on 15/6/4. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare.h" @interface OpenShare (Alipay) +(void)connectAlipay; +(void)AliPay:(NSString*)link Success:(paySuccess)success Fail:(payFail)fail; @end ================================================ FILE: src/OpenShare+Alipay.m ================================================ // // OpenShare+Alipay.m // openshare // // Created by LiuLogan on 15/6/4. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare+Alipay.h" @implementation OpenShare (Alipay) static NSString* schema=@"Alipay"; /** * 支付宝支付参数都是从服务器获得的,所以不需要注册key。但是还是需要先connect向OpenShare注册,以便回调。 */ +(void)connectAlipay{ [self set:schema Keys:@{@"schema":schema}]; } +(BOOL)isAlipayInstalled{ return [self canOpen:@"alipay://"]; } +(void)AliPay:(NSString*)link Success:(paySuccess)success Fail:(payFail)fail{ [self setPaySuccessCallback:success]; [self setPayFailCallback:fail]; if ([self isAlipayInstalled]) { //支付宝为了用户体验,会把截屏放在支付的后面当背景,可选项。当然也可以用其他的自己生成的UIImage,比如[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Default@2x" ofType:@"png"]] UIImage *screenShot= [self screenshot]; //获取到fromAppUrlScheme,来设置截屏。 NSString *linkStr=[self urlDecode:[link substringFromIndex:NSMaxRange([link rangeOfString:@"?"])]]; NSDictionary *linkDic=[NSJSONSerialization JSONObjectWithData:[linkStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; [[UIPasteboard generalPasteboard] setData:[NSKeyedArchiver archivedDataWithRootObject:@{@"image_data" :UIImagePNGRepresentation(screenShot),@"scheme" :linkDic[@"fromAppUrlScheme"]}] forPasteboardType:@"com.alipay.alipayClient.screenImage"]; //END 设置截屏(可以不设置,注释掉这块代码即可。)。 [self openURL:link]; } } +(BOOL)Alipay_handleOpenURL{ NSURL* url=[self returnedURL]; if ([url.absoluteString rangeOfString:@"//safepay/"].location != NSNotFound) { NSError *err; NSDictionary *ret=[NSJSONSerialization JSONObjectWithData:[[self urlDecode:url.query]dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&err]; if (err||ret[@"memo"]==[NSNull null]||[ret[@"memo"][@"ResultStatus"] intValue]!=9000) { if ([self payFailCallback]) { [self payFailCallback](ret,err?:[NSError errorWithDomain:@"alipay_pay" code:ret[@"memo"]!=[NSNull null]?[ret[@"memo"][@"ResultStatus"] intValue]:-1 userInfo:ret]); } }else{ if ([self paySuccessCallback]) { [self paySuccessCallback](ret); } } return YES; }else{ return NO; } } @end ================================================ FILE: src/OpenShare+QQ.h ================================================ // // OpenShare+QQ.h // openshare // // Created by LiuLogan on 15/5/15. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare.h" @interface OpenShare (QQ) /** * 连接QQ平台。可以分享到:qq好友/qq空间。只需要appId:http://op.open.qq.com/index.php?mod=appinfo&act=main&appid=1103194207#mobile|center * 需要添加CFBundleURLSchemes: * * tencent1103194207 * tencent1103194207.content * QQ41C1685F 16进制表示的appid,可以通过new Number(1103194207).toString(16).toUpperCase()获取。 * @param appId 所申请的应用的APP ID */ +(void)connectQQWithAppId:(NSString *)appId; +(BOOL)isQQInstalled; +(void)shareToQQFriends:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToQQZone:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToQQFavorites:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToQQDataline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)QQAuth:(NSString*)scope Success:(authSuccess)success Fail:(authFail)fail; /** * 打开WPA临时会话 * * @param qqNumber 要聊天的QQ号 */ +(void)chatWithQQNumber:(NSString*)qqNumber; /** * 打开某个群聊天。QQ客户端登录的QQ号,必须是groupNumber的成员才能聊天。 * * @param groupNumber 群号码 */ +(void)chatInQQGroup:(NSString*)groupNumber; /** * 是否能处理这个openUrl,如果能就返回YES,并且按照callback处理,否则返回NO,交给下一个处理。 * * @param url openURL * @param success success callback * @param fail fail callback * * @return 是否能处理给定的url */ +(BOOL)QQ_handleOpenURL; @end ================================================ FILE: src/OpenShare+QQ.m ================================================ // // OpenShare+QQ.m // openshare // // Created by LiuLogan on 15/5/15. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare+QQ.h" @implementation OpenShare (QQ) static NSString* schema=@"QQ"; enum { kQQAPICtrlFlagQZoneShareOnStart = 0x01, kQQAPICtrlFlagQZoneShareForbid = 0x02, kQQAPICtrlFlagQQShare = 0x04, kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏 kQQAPICtrlFlagQQShareDataline = 0x10, //数据线 }; +(void)connectQQWithAppId:(NSString *)appId{ [self set:schema Keys:@{@"appid":appId,@"callback_name":[NSString stringWithFormat:@"QQ%02llx",[appId longLongValue]]}]; } +(BOOL)isQQInstalled{ return [self canOpen:@"mqqapi://"]; } +(void)shareToQQFriends:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genShareUrl:msg to:0]]; } } +(void)shareToQQZone:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genShareUrl:msg to:kQQAPICtrlFlagQZoneShareOnStart]]; } } +(void)shareToQQFavorites:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genShareUrl:msg to:kQQAPICtrlFlagQQShareFavorites]]; } } +(void)shareToQQDataline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genShareUrl:msg to:kQQAPICtrlFlagQQShareDataline]]; } } +(void)QQAuth:(NSString*)scope Success:(authSuccess)success Fail:(authFail)fail{ if ([self beginAuth:schema Success:success Fail:fail]) { NSDictionary *authData=@{@"app_id" : [self keyFor:schema][@"appid"], @"app_name" : [self CFBundleDisplayName], //@"bundleid":[self CFBundleIdentifier],//或者有,或者正确(和后台配置一致),建议不填写。 @"client_id" :[self keyFor:schema][@"appid"], @"response_type" : @"token", @"scope" : scope,//@"get_user_info,get_simple_userinfo,add_album,add_idol,add_one_blog,add_pic_t,add_share,add_topic,check_page_fans,del_idol,del_t,get_fanslist,get_idollist,get_info,get_other_info,get_repost_list,list_album,upload_pic,get_vip_info,get_vip_rich_info,get_intimate_friends_weibo,match_nick_tips_weibo", @"sdkp" :@"i", @"sdkv" : @"2.9", @"status_machine" : [[UIDevice currentDevice] model], @"status_os" : [[UIDevice currentDevice] systemVersion], @"status_version" : [[UIDevice currentDevice] systemVersion] }; [self setGeneralPasteboard:[@"com.tencent.tencent" stringByAppendingString:[self keyFor:schema][@"appid"]] Value:authData encoding:OSPboardEncodingKeyedArchiver]; [self openURL:[NSString stringWithFormat:@"mqqOpensdkSSoLogin://SSoLogin/tencent%@/com.tencent.tencent%@?generalpastboard=1",[self keyFor:schema][@"appid"],[self keyFor:schema][@"appid"]]]; } } /** * 把msg分享到shareTO * * @param msg OSmessage * @param shareTo 0是好友/1是QQ空间。 * * @return 需要打开的url */ +(NSString*)genShareUrl:(OSMessage*)msg to:(int)shareTo{ NSMutableString *ret=[[NSMutableString alloc] initWithString:@"mqqapi://share/to_fri?thirdAppDisplayName="]; [ret appendString:[self base64Encode:[self CFBundleDisplayName]]]; [ret appendString:@"&version=1&cflag="]; [ret appendFormat:@"%d",shareTo]; [ret appendString:@"&callback_type=scheme&generalpastboard=1"]; [ret appendString:@"&callback_name="]; [ret appendString:[self keyFor:schema][@"callback_name"]]; [ret appendString:@"&src_type=app&shareType=0&file_type="]; //修正如果有link,则默认是news分享类型。 if (msg.link&&!msg.multimediaType) { msg.multimediaType=OSMultimediaTypeNews; } if ([msg isEmpty:@[@"image",@"link" ] AndNotEmpty:@[@"title"]]) { //纯文本分享。 [ret appendString:@"text&file_data="]; [ret appendString:[self base64AndUrlEncode:msg.title]]; }else if([msg isEmpty:@[@"link"] AndNotEmpty:@[@"title",@"image",@"desc"]]){ //图片分享 NSDictionary *data=@{@"file_data":[self dataWithImage:msg.image], @"previewimagedata":msg.thumbnail? [self dataWithImage:msg.thumbnail] :[self dataWithImage:msg.image scale:CGSizeMake(36, 36)] }; [self setGeneralPasteboard:@"com.tencent.mqq.api.apiLargeData" Value:data encoding: OSPboardEncodingKeyedArchiver]; [ret appendString:@"img&title="]; [ret appendString:[self base64Encode:msg.title]]; [ret appendString:@"&objectlocation=pasteboard&description="]; [ret appendString:[self base64Encode:msg.desc]]; }else if ([msg isEmpty:nil AndNotEmpty:@[@"title",@"desc",@"image",@"link",@"multimediaType"]]) { //新闻/多媒体分享(图片加链接)发送新闻消息 预览图像数据,最大1M字节 URL地址,必填,最长512个字符 via QQApiInterfaceObject.h NSDictionary *data=@{@"previewimagedata":[self dataWithImage:msg.image]}; [self setGeneralPasteboard:@"com.tencent.mqq.api.apiLargeData" Value:data encoding: OSPboardEncodingKeyedArchiver]; NSString *msgType=@"news"; if (msg.multimediaType==OSMultimediaTypeAudio) { msgType=@"audio"; }else if(msg.multimediaType==OSMultimediaTypeVideo){ //QQ没有video类型。客户端会自动判断。 // msgType=@"video"; } [ret appendFormat:@"%@&title=%@&url=%@&description=%@&objectlocation=pasteboard",msgType,[self base64AndUrlEncode:msg.title],[self base64AndUrlEncode:msg.link],[self base64AndUrlEncode:msg.desc]]; } return ret; } +(BOOL)QQ_handleOpenURL{ NSURL* url=[self returnedURL]; if ([url.scheme hasPrefix:@"QQ"]) { //分享 NSDictionary *dic=[self parseUrl:url]; if (dic[@"error_description"]) { [dic setValue:[self base64Decode:dic[@"error_description"]] forKey:@"error_description"]; } if ([dic[@"error"] intValue]!=0) { NSError *err=[NSError errorWithDomain:@"response_from_qq" code:[dic[@"error"] intValue] userInfo:dic]; if ([self shareFailCallback]) { [self shareFailCallback]([self message],err); } }else{ if ([self shareSuccessCallback]) { [self shareSuccessCallback]([self message]); } } return YES; }else if([url.scheme hasPrefix:@"tencent"]){ //登陆auth NSDictionary *ret=[self generalPasteboardData:[@"com.tencent.tencent" stringByAppendingString:[self keyFor:schema][@"appid"]] encoding:OSPboardEncodingKeyedArchiver]; if (ret[@"ret"]&&[ret[@"ret"] intValue]==0) { if ( [self authSuccessCallback]) { [self authSuccessCallback](ret); } }else{ NSError *err=[NSError errorWithDomain:@"auth_from_QQ" code:-1 userInfo:ret]; if ([self authFailCallback]) { [self authFailCallback](ret,err); } } return YES; } else{ return NO; } } +(void)chatWithQQNumber:(NSString*)qqNumber{ [self openURL:[NSString stringWithFormat:@"mqqwpa://im/chat?uin=%@&thirdAppDisplayName=%@&callback_name=%@&src_type=app&version=1&chat_type=wpa&callback_type=scheme",qqNumber,[self base64Encode:[self CFBundleDisplayName]],[self keyFor:schema][@"callback_name"]]]; } +(void)chatInQQGroup:(NSString*)groupNumber{ [self openURL:[NSString stringWithFormat:@"mqqwpa://im/chat?uin=%@&thirdAppDisplayName=%@&callback_name=%@&src_type=app&version=1&chat_type=group&callback_type=scheme",groupNumber,[self base64Encode:[self CFBundleDisplayName]],[self keyFor:schema][@"callback_name"]]]; } @end ================================================ FILE: src/OpenShare+Renren.h ================================================ // // OpenShare+Renren.h // openshare // // Created by LiuLogan on 15/5/19. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare.h" @interface OpenShare (Renren) +(void)connectRenrenWithAppId:(NSString *)appId AndAppKey:(NSString*)appKey; +(BOOL)isRenrenInstalled; +(void)shareToRenrenSession:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToRenrenTimeline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; @end ================================================ FILE: src/OpenShare+Renren.m ================================================ // // OpenShare+Renren.m // openshare // // Created by LiuLogan on 15/5/19. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare+Renren.h" @implementation OpenShare (Renren) static NSString* schema=@"Renren"; +(void)connectRenrenWithAppId:(NSString *)appId AndAppKey:(NSString*)appKey{ [self set:schema Keys:@{@"appid":appId,@"appkey":appKey}]; } +(BOOL)isRenrenInstalled{ return [self canOpen:@"renrenshare://share"]; } +(void)shareToRenrenSession:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genRenrenShareUrl:msg to:0]]; } } +(void)shareToRenrenTimeline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genRenrenShareUrl:msg to:1]]; } } +(NSString*)genRenrenShareUrl:(OSMessage*)msg to:(int)shareTo{ NSString *msgType=@"Text"; NSMutableDictionary *dic=[[NSMutableDictionary alloc] initWithDictionary:@{@"title":msg.title}]; if(msg.multimediaType==OSMultimediaTypeAudio){ dic[@"description"]=msg.desc?:msg.title; dic[@"thumbData"]= msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(36, 36)]; dic[@"url"]=msg.link; msgType=@"Voice"; }else if(msg.multimediaType==OSMultimediaTypeVideo){ dic[@"description"]=msg.desc?:msg.title; dic[@"thumbData"]= msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(36, 36)]; dic[@"url"]=msg.link; msgType=@"Video"; }else{ if ([msg isEmpty:nil AndNotEmpty:@[@"image",@"link"]]) { //图文 dic[@"description"]=msg.desc?:msg.title; dic[@"thumbData"]= msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(36, 36)]; dic[@"url"]=msg.link; msgType=@"ImgText"; }else if ([msg isEmpty:@[@"link"] AndNotEmpty:@[@"image"]]) { //图片 dic[@"imageData"]= [self dataWithImage:msg.image]; dic[@"thumbData"]= msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(36, 36)]; msgType=@"ImgText"; }else if ([msg isEmpty:@[@"link"] AndNotEmpty:@[@"image"]]) { //文本 dic[@"text"]=msg.desc?:msg.title; if (msg.link) { dic[@"url"]=msg.link; } msgType=@"Text"; } } [[UIPasteboard generalPasteboard] setData:[NSPropertyListSerialization dataWithPropertyList:dic format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil] forPasteboardType:@"renren_share"]; return [NSString stringWithFormat:@"renrenshare://share?sdk_ver=1.0&app_id=%@&app_key=%@&callback=renrenshare%@&msgType=%@&target=%d&msgVer=1.0&msgData=renren_share",[self keyFor:schema][@"appid"],[self keyFor:schema][@"appkey"],[self keyFor:schema][@"appid"],msgType,shareTo]; } /** * 人人网回调,人人网不传回分享结果。 * * @return 是否是人人网打开的 */ +(BOOL)Renren_handleOpenURL{ NSURL* url=[self returnedURL]; if ([url.scheme hasPrefix:@"renrenshare"]) { if ([self shareSuccessCallback]) { [self shareSuccessCallback]([self message]); } return YES; }else{ return NO; } } @end ================================================ FILE: src/OpenShare+Weibo.h ================================================ // // OpenShare+Weibo.h // openshare // // Created by LiuLogan on 15/5/18. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare.h" @interface OpenShare (Weibo) /** * 可以点击「编辑」修改Bundle ID,要和这里的一致,否则auth的时候会返回error_code=21338 * * @param appKey 申请到的appKey */ +(void)connectWeiboWithAppKey:(NSString *)appKey; +(BOOL)isWeiboInstalled; /** * 分享到微博,微博只支持三种类型:文本/图片/链接。根据OSMessage自动判定想分享的类型。 * * @param msg 要分享的msg * @param success 分享成功回调 * @param fail 分享失败回调 */ +(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; /** * 微博登录OAuth * * @param scope scope,如果不填写,默认是all * @param redirectURI 必须填写,可以通过http://open.weibo.com/apps/402180334/info/advanced编辑(后台不验证,但是必须填写一致) * @param success 登录成功回调 * @param fail 登录失败回调 */ +(void)WeiboAuth:(NSString*)scope redirectURI:(NSString*)redirectURI Success:(authSuccess)success Fail:(authFail)fail; @end ================================================ FILE: src/OpenShare+Weibo.m ================================================ // // OpenShare+Weibo.m // openshare // // Created by LiuLogan on 15/5/18. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare+Weibo.h" @implementation OpenShare (Weibo) static NSString *schema=@"Weibo"; +(void)connectWeiboWithAppKey:(NSString *)appKey{ [self set:schema Keys:@{@"appKey":appKey}]; } +(BOOL)isWeiboInstalled{ return [self canOpen:@"weibosdk://request"]; } +(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if (![self beginShare:schema Message:msg Success:success Fail:fail]) { return; } NSDictionary *message; if ([msg isEmpty:@[@"link" ,@"image"] AndNotEmpty:@[@"title"] ]) { //text类型分享 message= @{ @"__class" : @"WBMessageObject", @"text" :msg.title }; }else if ([msg isEmpty:@[@"link" ] AndNotEmpty:@[@"title",@"image"] ]) { //图片类型分享 message=@{ @"__class" : @"WBMessageObject", @"imageObject":@{ @"imageData":[self dataWithImage:msg.image] }, @"text" : msg.title }; }else if ([msg isEmpty:nil AndNotEmpty:@[@"title",@"link" ,@"image"] ]) { //链接类型分享 message=@{ @"__class" : @"WBMessageObject", @"mediaObject":@{ @"__class" : @"WBWebpageObject", @"description": msg.desc?:msg.title, @"objectID" : @"identifier1", @"thumbnailData":msg.thumbnail ? [self dataWithImage:msg.thumbnail] : [self dataWithImage:msg.image scale:CGSizeMake(100, 100)], @"title": msg.title, @"webpageUrl":msg.link } }; } NSString *uuid=[[NSUUID UUID] UUIDString]; NSArray *messageData=@[ @{@"transferObject":[NSKeyedArchiver archivedDataWithRootObject:@{ @"__class" :@"WBSendMessageToWeiboRequest", @"message":message, @"requestID" :uuid, }]}, @{@"userInfo":[NSKeyedArchiver archivedDataWithRootObject:@{}]}, @{@"app":[NSKeyedArchiver archivedDataWithRootObject:@{ @"appKey" : [self keyFor:schema][@"appKey"],@"bundleID" : [self CFBundleIdentifier]}]} ]; [UIPasteboard generalPasteboard].items=messageData; [self openURL:[NSString stringWithFormat:@"weibosdk://request?id=%@&sdkversion=003013000",uuid]]; } +(void)WeiboAuth:(NSString*)scope redirectURI:(NSString*)redirectURI Success:(authSuccess)success Fail:(authFail)fail{ if (![self beginAuth:schema Success:success Fail:fail]) { return; } NSString *uuid=[[NSUUID UUID] UUIDString]; NSArray *authData=@[ @{@"transferObject":[NSKeyedArchiver archivedDataWithRootObject:@{ @"__class" :@"WBAuthorizeRequest", @"redirectURI":redirectURI, @"requestID" :uuid, @"scope": scope?:@"all" }]}, @{@"userInfo":[NSKeyedArchiver archivedDataWithRootObject:@{ @"mykey":@"as you like", @"SSO_From" : @"SendMessageToWeiboViewController" }] }, @{@"app":[NSKeyedArchiver archivedDataWithRootObject:@{ @"appKey" :[self keyFor:schema][@"appKey"], @"bundleID" : [self CFBundleIdentifier], @"name" :[self CFBundleDisplayName] }] } ]; [UIPasteboard generalPasteboard].items=authData; [self openURL:[NSString stringWithFormat:@"weibosdk://request?id=%@&sdkversion=003013000",uuid]]; } +(BOOL)Weibo_handleOpenURL{ NSURL* url=[self returnedURL]; if ([url.scheme hasPrefix:@"wb"]) { NSArray *items=[UIPasteboard generalPasteboard].items; NSMutableDictionary *ret=[NSMutableDictionary dictionaryWithCapacity:items.count]; for (NSDictionary *item in items) { for (NSString *k in item) { ret[k]=[k isEqualToString:@"sdkVersion"]?item[k]:[NSKeyedUnarchiver unarchiveObjectWithData:item[k]]; } } NSDictionary *transferObject=ret[@"transferObject"]; if ([transferObject[@"__class"] isEqualToString:@"WBAuthorizeResponse"]) { //auth if ([transferObject[@"statusCode"] intValue]==0) { if ([self authSuccessCallback]) { [self authSuccessCallback](transferObject); } }else{ if ([self authFailCallback]) { NSError *err=[NSError errorWithDomain:@"weibo_auth_response" code:[transferObject[@"statusCode"] intValue] userInfo:transferObject]; [self authFailCallback](transferObject,err); } } }else if ([transferObject[@"__class"] isEqualToString:@"WBSendMessageToWeiboResponse"]) { //分享回调 if ([transferObject[@"statusCode"] intValue]==0) { if ([self shareSuccessCallback]) { [self shareSuccessCallback]([self message]); } }else{ if ([self shareFailCallback]) { NSError *err=[NSError errorWithDomain:@"weibo_share_response" code:[transferObject[@"statusCode"] intValue] userInfo:transferObject]; [self shareFailCallback]([self message],err); } } } return YES; } else{ return NO; } } @end ================================================ FILE: src/OpenShare+Weixin.h ================================================ // // OpenShare+Weixin.h // openshare // // Created by LiuLogan on 15/5/18. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare.h" @interface OpenShare (Weixin) /** * https://open.weixin.qq.com 在这里申请 * * @param appId AppID */ +(void)connectWeixinWithAppId:(NSString *)appId; +(BOOL)isWeixinInstalled; +(void)shareToWeixinSession:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToWeixinTimeline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)shareToWeixinFavorite:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(void)WeixinAuth:(NSString*)scope Success:(authSuccess)success Fail:(authFail)fail; +(void)WeixinPay:(NSString*)link Success:(paySuccess)success Fail:(payFail)fail; @end ================================================ FILE: src/OpenShare+Weixin.m ================================================ // // OpenShare+Weixin.m // openshare // // Created by LiuLogan on 15/5/18. // Copyright (c) 2015年 OpenShare . All rights reserved. // #import "OpenShare+Weixin.h" @implementation OpenShare (Weixin) static NSString *schema=@"Weixin"; +(void)connectWeixinWithAppId:(NSString *)appId{ [self set:schema Keys:@{@"appid":appId}]; } +(BOOL)isWeixinInstalled{ return [self canOpen:@"weixin://"]; } +(void)shareToWeixinSession:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genWeixinShareUrl:msg to:0]]; } } +(void)shareToWeixinTimeline:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genWeixinShareUrl:msg to:1]]; } } +(void)shareToWeixinFavorite:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self beginShare:schema Message:msg Success:success Fail:fail]) { [self openURL:[self genWeixinShareUrl:msg to:2]]; } } /** * 把msg分享到shareTO * * @param msg OSmessage * @param shareTo 0是好友/1是QQ空间。 * * @return 需要打开的url */ +(NSString*)genWeixinShareUrl:(OSMessage*)msg to:(int)shareTo{ NSMutableDictionary *dic=[[NSMutableDictionary alloc] initWithDictionary:@{@"result":@"1",@"returnFromApp" :@"0",@"scene" : [NSString stringWithFormat:@"%d",shareTo],@"sdkver" : @"1.5",@"command" : @"1010"}]; if (msg.multimediaType==OSMultimediaTypeNews) { msg.multimediaType=0; } if (!msg.multimediaType) { //不指定类型 if ([msg isEmpty:@[@"image",@"link", @"file"] AndNotEmpty:@[@"title"]]) { //文本 dic[@"command"]=@"1020"; dic[@"title"]=msg.title; }else if([msg isEmpty:@[@"link"] AndNotEmpty:@[@"image"]]){ //图片 dic[@"title"]=msg.title?:@""; dic[@"fileData"]= [self dataWithImage:msg.image]; dic[@"thumbData"]=msg.thumbnail ? [self dataWithImage:msg.thumbnail] : [self dataWithImage:msg.image scale:CGSizeMake(100, 100)]; dic[@"objectType"]=@"2"; }else if([msg isEmpty:nil AndNotEmpty:@[@"link",@"title",@"image"]]){ //有链接。 dic[@"description"]=msg.desc?:msg.title; dic[@"mediaUrl"]=msg.link; dic[@"objectType"]=@"5"; dic[@"thumbData"]=msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(100, 100)]; dic[@"title"] =msg.title; } else if ([msg isEmpty:@[@"link"] AndNotEmpty:@[@"file"]]) { //gif dic[@"fileData"]= msg.file ? msg.file : [self dataWithImage:msg.image]; dic[@"thumbData"]=msg.thumbnail ? [self dataWithImage:msg.thumbnail] : [self dataWithImage:msg.image scale:CGSizeMake(100, 100)]; dic[@"objectType"]=@"8"; } }else if(msg.multimediaType==OSMultimediaTypeAudio){ //music dic[@"description"]=msg.desc?:msg.title; dic[@"mediaUrl"]=msg.link; dic[@"mediaDataUrl"]=msg.mediaDataUrl; dic[@"objectType"]=@"3"; dic[@"thumbData"]=msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(100, 100)];; dic[@"title"] =msg.title; }else if(msg.multimediaType==OSMultimediaTypeVideo){ //video dic[@"description"]=msg.desc?:msg.title; dic[@"mediaUrl"]=msg.link; dic[@"objectType"]=@"4"; dic[@"thumbData"]=msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(100, 100)];; dic[@"title"] =msg.title; }else if(msg.multimediaType==OSMultimediaTypeApp){ //app dic[@"description"]=msg.desc?:msg.title; if(msg.extInfo)dic[@"extInfo"]=msg.extInfo; dic[@"fileData"]=[self dataWithImage:msg.image]; dic[@"mediaUrl"]=msg.link; dic[@"objectType"]=@"7"; dic[@"thumbData"]=msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(100, 100)];; dic[@"title"] =msg.title; }else if(msg.multimediaType==OSMultimediaTypeFile){ //file dic[@"description"]=msg.desc?:msg.title; dic[@"fileData"]=msg.file; dic[@"objectType"]=@"6"; dic[@"fileExt"]=msg.fileExt?:@""; dic[@"thumbData"]=msg.thumbnail? [self dataWithImage:msg.thumbnail]:[self dataWithImage:msg.image scale:CGSizeMake(100, 100)];; dic[@"title"] =msg.title; } NSData *output=[NSPropertyListSerialization dataWithPropertyList:@{[self keyFor:schema][@"appid"]:dic} format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil]; [[UIPasteboard generalPasteboard] setData:output forPasteboardType:@"content"]; return [NSString stringWithFormat:@"weixin://app/%@/sendreq/?",[self keyFor:schema][@"appid"]]; } /** * 注意:微信登录权限仅限已获得认证的开发者申请,请先进行开发者认证 * * @param scope scope * @param success 登录成功回调 * @param fail 登录失败回调 */ +(void)WeixinAuth:(NSString*)scope Success:(authSuccess)success Fail:(authFail)fail{ if ([self beginAuth:schema Success:success Fail:fail]) { [self openURL:[NSString stringWithFormat:@"weixin://app/%@/auth/?scope=%@&state=Weixinauth",[self keyFor:schema][@"appid"],scope]]; } } /** * 微信支付,不同于分享和登录,由于参数是服务器生成的,所以不需要connect。 * * @param link 服务器返回的link,以供直接打开 * @param success 微信支付成功的回调 * @param fail 微信支付失败的回调 */ +(void)WeixinPay:(NSString*)link Success:(paySuccess)success Fail:(payFail)fail{ [self setPaySuccessCallback:success]; [self setPayFailCallback:fail]; [self openURL:link]; } +(BOOL)Weixin_handleOpenURL{ NSURL* url=[self returnedURL]; if ([url.scheme hasPrefix:@"wx"]) { NSDictionary *retDic=[NSPropertyListSerialization propertyListWithData:[[UIPasteboard generalPasteboard] dataForPasteboardType:@"content"]?:[[NSData alloc] init] options:0 format:0 error:nil][[self keyFor:schema][@"appid"]]; NSLog(@"retDic\n%@",retDic); if ([url.absoluteString rangeOfString:@"://oauth"].location != NSNotFound) { //login succcess if ([self authSuccessCallback]) { [self authSuccessCallback]([self parseUrl:url]); } }else if([url.absoluteString rangeOfString:@"://pay/"].location != NSNotFound){ NSDictionary *urlMap=[self parseUrl:url]; if ([urlMap[@"ret"] intValue]==0) { if ([self paySuccessCallback]) { [self paySuccessCallback](urlMap); } }else{ if ([self payFailCallback]) { [self payFailCallback](urlMap,[NSError errorWithDomain:@"weixin_pay" code:[urlMap[@"ret"] intValue] userInfo:retDic]); } } }else{ if (retDic[@"state"]&&[retDic[@"state"] isEqualToString:@"Weixinauth"]&&[retDic[@"result"] intValue]!=0) { //登录失败 if ([self authFailCallback]) { [self authFailCallback](retDic,[NSError errorWithDomain:@"weixin_auth" code:[retDic[@"result"] intValue] userInfo:retDic]); } }else if([retDic[@"result"] intValue]==0){ //分享成功 if ([self shareSuccessCallback]) { [self shareSuccessCallback]([self message]); } }else{ //分享失败 if ([self shareFailCallback]) { [self shareFailCallback]([self message],[NSError errorWithDomain:@"weixin_share" code:[retDic[@"result"] intValue] userInfo:retDic]); } } } return YES; }else{ return NO; } } @end ================================================ FILE: src/OpenShare.h ================================================ // // OpenShare.h // openshare // // Created by LiuLogan on 15/5/13. // Copyright (c) 2015年 OpenShare. All rights reserved. // #import #import /** 分享类型,除了news以外,还可能是video/audio/app等。 */ typedef enum : NSUInteger { OSMultimediaTypeNews, OSMultimediaTypeAudio, OSMultimediaTypeVideo, OSMultimediaTypeApp, OSMultimediaTypeFile, OSMultimediaTypeUndefined } OSMultimediaType; /** * OSMessage保存分享消息数据。 */ @interface OSMessage : NSObject @property NSString* title; @property NSString* desc; @property NSString* link; @property UIImage *image; @property UIImage *thumbnail; @property OSMultimediaType multimediaType; //for 微信 @property NSString* extInfo; @property NSString* mediaDataUrl; @property NSString* fileExt; @property (nonatomic, strong) NSData *file; /// 微信分享gif/文件 /** * 判断emptyValueForKeys的value都是空的,notEmptyValueForKeys的value都不是空的。 * * @param emptyValueForKeys 空值的key * @param notEmptyValueForKeys 非空值的key * * @return YES/NO */ -(BOOL)isEmpty:(NSArray*)emptyValueForKeys AndNotEmpty:(NSArray*)notEmptyValueForKeys; @end typedef void (^shareSuccess)(OSMessage * message); typedef void (^shareFail)(OSMessage * message,NSError *error); typedef void (^authSuccess)(NSDictionary * message); typedef void (^authFail)(NSDictionary * message,NSError *error); typedef void (^paySuccess)(NSDictionary * message); typedef void (^payFail)(NSDictionary * message,NSError *error); /** 粘贴板数据编码方式,目前只有两种: 1. [NSKeyedArchiver archivedDataWithRootObject:data]; 2. [NSPropertyListSerialization dataWithPropertyList:data format:NSPropertyListBinaryFormat_v1_0 options:0 error:&err]; */ typedef enum : NSUInteger { OSPboardEncodingKeyedArchiver, OSPboardEncodingPropertyListSerialization, } OSPboardEncoding; @interface OpenShare : NSObject /** * 设置平台的key * * @param platform 平台名称 * @param key NSDictionary格式的key */ +(void)set:(NSString*)platform Keys:(NSDictionary *)key; /** * 获取平台的key * * @param platform 平台名称,每个category自行决定。 * * @return 平台的key(NSDictionary或nil) */ +(NSDictionary *)keyFor:(NSString*)platform; /** * 通过UIApplication打开url * * @param url 需要打开的url */ +(void)openURL:(NSString*)url; +(BOOL)canOpen:(NSString*)url; /** * 处理被打开时的openurl * * @param url openurl * * @return 如果能处理,就返回YES。够则返回NO */ +(BOOL)handleOpenURL:(NSURL*)url; +(shareSuccess)shareSuccessCallback; +(shareFail)shareFailCallback; +(void)setShareSuccessCallback:(shareSuccess)suc; +(void)setShareFailCallback:(shareFail)fail; +(NSURL*)returnedURL; +(NSDictionary*)returnedData; +(void)setReturnedData:(NSDictionary*)retData; +(NSMutableDictionary *)parseUrl:(NSURL*)url; +(void)setMessage:(OSMessage*)msg; +(OSMessage*)message; +(BOOL)beginShare:(NSString*)platform Message:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail; +(BOOL)beginAuth:(NSString*)platform Success:(authSuccess)success Fail:(authFail)fail; +(NSString*)base64Encode:(NSString *)input; +(NSString*)base64Decode:(NSString *)input; +(NSString*)CFBundleDisplayName; +(NSString*)CFBundleIdentifier; +(void)setGeneralPasteboard:(NSString*)key Value:(NSDictionary*)value encoding:(OSPboardEncoding)encoding; +(NSDictionary*)generalPasteboardData:(NSString*)key encoding:(OSPboardEncoding)encoding; +(NSString*)base64AndUrlEncode:(NSString *)string; +(NSString*)urlDecode:(NSString*)input; + (UIImage *)screenshot; +(authSuccess)authSuccessCallback; +(authFail)authFailCallback; +(void)setPaySuccessCallback:(paySuccess)suc; +(void)setPayFailCallback:(payFail)fail; +(paySuccess)paySuccessCallback; +(payFail)payFailCallback; + (NSData *)dataWithImage:(UIImage *)image; + (NSData *)dataWithImage:(UIImage *)image scale:(CGSize)size; @end ================================================ FILE: src/OpenShare.m ================================================ // // OpenShare.m // openshare // // Created by LiuLogan on 15/5/13. // Copyright (c) 2015年 OpenShare. All rights reserved. // #import "OpenShare.h" @implementation OpenShare /** * 用于保存各个平台的key。每个平台需要的key/appid不一样,所以用dictionary保存。 */ static NSMutableDictionary *keys; +(void)set:(NSString*)platform Keys:(NSDictionary *)key{ if (!keys) { keys=[[NSMutableDictionary alloc] init]; } keys[platform]=key; } +(NSDictionary *)keyFor:(NSString*)platform{ return [keys valueForKey:platform]?keys[platform]:nil; } +(void)openURL:(NSString*)url{ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; } +(BOOL)canOpen:(NSString*)url{ return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:url]]; } +(BOOL)handleOpenURL:(NSURL*)openUrl{ returnedURL=openUrl; for (NSString *key in keys) { SEL sel=NSSelectorFromString([key stringByAppendingString:@"_handleOpenURL"]); if ([self respondsToSelector:sel]) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector:sel]]; [invocation setSelector:sel]; [invocation setTarget:self]; [invocation invoke]; BOOL returnValue; [invocation getReturnValue:&returnValue]; if (returnValue) {//如果这个url能处理,就返回YES,否则,交给下一个处理。 return YES; } }else{ NSLog(@"fatal error: %@ is should have a method: %@",key,[key stringByAppendingString:@"_handleOpenURL"]); } } return NO; } #pragma mark 分享/auth以后,应用被调起,回调。 static NSURL* returnedURL; static NSDictionary *returnedData; static shareSuccess shareSuccessCallback; static shareFail shareFailCallback; static authSuccess authSuccessCallback; static authFail authFailCallback; static paySuccess paySuccessCallback; static payFail payFailCallback; static OSMessage *message; +(shareSuccess)shareSuccessCallback{ return shareSuccessCallback; } +(shareFail)shareFailCallback{ return shareFailCallback; } +(void)setShareSuccessCallback:(shareSuccess)suc{ shareSuccessCallback=suc; } +(void)setShareFailCallback:(shareFail)fail{ shareFailCallback=fail; } +(void)setPaySuccessCallback:(paySuccess)suc{ paySuccessCallback=suc; } +(void)setPayFailCallback:(payFail)fail{ payFailCallback=fail; } +(paySuccess)paySuccessCallback{ return paySuccessCallback; } +(payFail)payFailCallback{ return payFailCallback; } +(NSURL*)returnedURL{ return returnedURL; } +(NSDictionary*)returnedData{ return returnedData; } +(void)setReturnedData:(NSDictionary*)retData{ returnedData=retData; } +(void)setMessage:(OSMessage*)msg{ message=msg; } +(OSMessage*)message{ return message?:[[OSMessage alloc] init]; } +(authSuccess)authSuccessCallback{ return authSuccessCallback; } +(authFail)authFailCallback{ return authFailCallback; } +(BOOL)beginShare:(NSString*)platform Message:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{ if ([self keyFor:platform]) { message=msg; shareSuccessCallback=success; shareFailCallback=fail; return YES; }else{ NSLog(@"please connect%@ before you can share to it!!!",platform); return NO; } } +(BOOL)beginAuth:(NSString*)platform Success:(authSuccess)success Fail:(authFail)fail{ if ([self keyFor:platform]) { authSuccessCallback=success; authFailCallback=fail; return YES; }else{ NSLog(@"please connect%@ before you can share to it!!!",platform); return NO; } } #pragma mark 公共实用方法 +(NSMutableDictionary *)parseUrl:(NSURL*)url{ NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init]; NSArray *urlComponents = [[url query] componentsSeparatedByString:@"&"]; for (NSString *keyValuePair in urlComponents) { NSRange range=[keyValuePair rangeOfString:@"="]; [queryStringDictionary setObject:range.length>0?[keyValuePair substringFromIndex:range.location+1]:@"" forKey:(range.length?[keyValuePair substringToIndex:range.location]:keyValuePair)]; } return queryStringDictionary; } +(NSString*)base64Encode:(NSString *)input{ return [[input dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]; } +(NSString*)base64Decode:(NSString *)input{ return [[NSString alloc ] initWithData:[[NSData alloc] initWithBase64EncodedString:input options:0] encoding:NSUTF8StringEncoding]; } +(NSString*)CFBundleDisplayName{ return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; } +(NSString*)CFBundleIdentifier{ return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; } +(void)setGeneralPasteboard:(NSString*)key Value:(NSDictionary*)value encoding:(OSPboardEncoding)encoding{ if (value&&key) { NSData *data=nil; NSError *err; switch (encoding) { case OSPboardEncodingKeyedArchiver: data=[NSKeyedArchiver archivedDataWithRootObject:value]; break; case OSPboardEncodingPropertyListSerialization: data=[NSPropertyListSerialization dataWithPropertyList:value format:NSPropertyListBinaryFormat_v1_0 options:0 error:&err]; default: NSLog(@"encoding not implemented"); break; } if (err) { NSLog(@"error when NSPropertyListSerialization: %@",err); }else if (data){ [[UIPasteboard generalPasteboard] setData:data forPasteboardType:key]; } } } +(NSDictionary*)generalPasteboardData:(NSString*)key encoding:(OSPboardEncoding)encoding{ NSData *data=[[UIPasteboard generalPasteboard] dataForPasteboardType:key]; NSDictionary *dic=nil; if (data) { NSError *err; switch (encoding) { case OSPboardEncodingKeyedArchiver: dic= [NSKeyedUnarchiver unarchiveObjectWithData:data]; break; case OSPboardEncodingPropertyListSerialization: dic=[NSPropertyListSerialization propertyListWithData:data options:0 format:0 error:&err]; default: break; } if (err) { NSLog(@"error when NSPropertyListSerialization: %@",err); } } return dic; } +(NSString*)base64AndUrlEncode:(NSString *)string{ return [[self base64Encode:string] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; } +(NSString*)urlDecode:(NSString*)input{ return [[input stringByReplacingOccurrencesOfString:@"+" withString:@" "]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } /** * 截屏功能。via:http://stackoverflow.com/a/8017292/3825920 * * @return 对当前窗口截屏。(支付宝可能需要) */ + (UIImage *)screenshot { CGSize imageSize = CGSizeZero; UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (UIInterfaceOrientationIsPortrait(orientation)) { imageSize = [UIScreen mainScreen].bounds.size; } else { imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); } UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); CGContextRef context = UIGraphicsGetCurrentContext(); for (UIWindow *window in [[UIApplication sharedApplication] windows]) { CGContextSaveGState(context); CGContextTranslateCTM(context, window.center.x, window.center.y); CGContextConcatCTM(context, window.transform); CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y); if (orientation == UIInterfaceOrientationLandscapeLeft) { CGContextRotateCTM(context, M_PI_2); CGContextTranslateCTM(context, 0, -imageSize.width); } else if (orientation == UIInterfaceOrientationLandscapeRight) { CGContextRotateCTM(context, -M_PI_2); CGContextTranslateCTM(context, -imageSize.height, 0); } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { CGContextRotateCTM(context, M_PI); CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); } if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; } else { [window.layer renderInContext:context]; } CGContextRestoreGState(context); } UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } + (NSData *)dataWithImage:(UIImage *)image { return UIImageJPEGRepresentation(image, 1); } + (NSData *)dataWithImage:(UIImage *)image scale:(CGSize)size { UIGraphicsBeginImageContext(size); [image drawInRect:CGRectMake(0,0, size.width, size.height)]; UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return UIImageJPEGRepresentation(scaledImage, 1); } - (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size{ UIGraphicsBeginImageContext(size); [image drawInRect:CGRectMake(0,0, size.width, size.height)]; UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } @end @implementation OSMessage -(BOOL)isEmpty:(NSArray*)emptyValueForKeys AndNotEmpty:(NSArray*)notEmptyValueForKeys{ @try { if (emptyValueForKeys) { for (NSString *key in emptyValueForKeys) { if ([self valueForKeyPath:key]) { return NO; } } } if (notEmptyValueForKeys) { for (NSString *key in notEmptyValueForKeys) { if (![self valueForKey:key]) { return NO; } } } return YES; } @catch (NSException *exception) { NSLog(@"isEmpty error:\n %@",exception); return NO; } } @end ================================================ FILE: src/OpenShareHeader.h ================================================ // // OpenShareHeader.h // openshare // // Created by LiuLogan on 15/5/15. // Copyright (c) 2015年 OpenShare . All rights reserved. // #ifndef openshare_OpenShareHeader_h #define openshare_OpenShareHeader_h #import "OpenShare+QQ.h" #import "OpenShare+Weibo.h" #import "OpenShare+Weixin.h" #import "OpenShare+Renren.h" #import "OpenShare+Alipay.h" #endif ================================================ FILE: src/SocietyLoginManager.h ================================================ // // CallBackTestManager.h // MarryNovo // // Created by Mot on 15/11/4. // Copyright © 2015年 Facebook. All rights reserved. // #import "RCTBridgeModule.h" //重写NSLog,Debug模式下打印日志和当前行数 #if DEBUG #define NSLog(FORMAT, ...) fprintf(stderr,"\nfunction:%s line:%d\n%s\n", __FUNCTION__, __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]); #else #define NSLog(FORMAT, ...) nil #endif #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] //DEBUG 模式下打印日志,当前行 并弹出一个警告 #ifdef DEBUG # define ULog(fmt, ...) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%s\n [Line %d] ", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; } #else # define ULog(...) #endif @interface SocietyLoginManager : NSObject @end ================================================ FILE: src/SocietyLoginManager.m ================================================ // // CallBackTestManager.m // MarryNovo // // Created by Mot on 15/11/4. // Copyright © 2015年 Facebook. All rights reserved. // #import "SocietyLoginManager.h" #import "RCTEventDispatcher.h" #import "OpenShareHeader.h" @implementation SocietyLoginManager @synthesize bridge = _bridge; RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(call) { [self _callback]; } RCT_EXPORT_METHOD(qqLogin) { [self _callQQLogin]; } RCT_EXPORT_METHOD(wechatLogin) { [self _callWeichatLogin]; } RCT_EXPORT_METHOD(weiboLogin) { [self _callWeiboLogin]; } - (void)_callback { NSLog(@"Success call native modules"); } -(void)_callQQLogin { [OpenShare QQAuth:@"get_user_info" Success:^(NSDictionary *message) { [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"QQ登录成功", @"res": message } ]; } Fail:^(NSDictionary *message, NSError *error) { [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"QQ登录失败", @"res": message, @"error": error, } ]; }]; } -(void)_callWeichatLogin { [OpenShare WeixinAuth:@"snsapi_userinfo" Success:^(NSDictionary *message) { [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"微信登录成功", @"res": message } ]; } Fail:^(NSDictionary *message, NSError *error) { [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"微信登录失败", @"res": message, @"error": error, } ]; }]; } //处理 返回数据中的expirationDate值,因为值的格式有问题,转换成 string 后才能符合 json 的格式要求。 ********开始******** //Commit by Parry at 2016-01-26 - (NSMutableDictionary*)change: (NSDictionary *)message { NSMutableDictionary* data = [message mutableCopy]; if ([message objectForKey:@"expirationDate"]) { NSDateFormatter *dateToStringFormatter = [[NSDateFormatter alloc] init]; [dateToStringFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *date= [data objectForKey:@"expirationDate"]; NSString *strDate = [dateToStringFormatter stringFromDate:date]; data = [message mutableCopy]; [data setObject:strDate forKey:@"expirationDate"]; } return data; } //处理 返回数据中的expirationDate值,因为值的格式有问题,转换成 string 后才能符合 json 的格式要求。 ********结束******** -(void)_callWeiboLogin { [OpenShare WeiboAuth:@"all" redirectURI:@"http://sns.whalecloud.com" Success:^(NSDictionary *message) { NSMutableDictionary* data = [self change:message]; [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"微博登录成功", @"res": data, } ]; } Fail:^(NSDictionary *message, NSError *error) { NSMutableDictionary* data = [self change:message]; [self.bridge.eventDispatcher sendDeviceEventWithName:@"managerCallback" body:@{ @"title": @"微博登录失败", @"res": data, @"error": error } ]; }]; } @end