2017-05-02 11:43:57 XiaoYuWen1242466468 阅读数 2094

第一步: 用cocoapods导入框架

target 'tests' do
         # U-Share SDK UI模块(分享面板,建议添加)
         pod ‘UMengUShare/UI’

         # 集成微信(完整版14.4M)
         pod ‘UMengUShare/Social/WeChat'

         # 集成QQ(完整版7.6M)
         pod ‘UMengUShare/Social/QQ'

         # 集成新浪微博(完整版25.3M)
         pod ‘UMengUShare/Social/Sina'

         # 集成Facebook/Messenger
         pod ‘UMengUShare/Social/Facebook'

         # 集成Twitter
         pod ‘UMengUShare/Social/Twitter'

         # 集成腾讯微博
         pod ‘UMengUShare/Social/TencentWeibo'

         # 加入IDFA获取
        pod ‘UMengUShare/Plugin/IDFA'
     end

第二步:设置白名单 和https 设置  

打开info.plist文件
 HTTPS 设置
          <key>NSAppTransportSecurity</key>
   
<dict>
       
<key>NSAllowsArbitraryLoads</key>
       
<true/>
    </dict>

     白名单设置

    <key>LSApplicationQueriesSchemes</key>
   
<array>
       
<string>linkedin</string>
       
<string>linkedin-sdk2</string>
       
<string>linkedin-sdk</string>
       
<string>wechat</string>
       
<string>weixin</string>
       
<string>sinaweibohd</string>
       
<string>sinaweibo</string>
       
<string>sinaweibosso</string>
       
<string>weibosdk</string>
       
<string>weibosdk2.5</string>
       
<string>mqqapi</string>
       
<string>mqq</string>
       
<string>mqqOpensdkSSoLogin</string>
       
<string>mqqconnect</string>
       
<string>mqqopensdkdataline</string>
       
<string>mqqopensdkgrouptribeshare</string>
       
<string>mqqopensdkfriend</string>
       
<string>mqqopensdkapi</string>
       
<string>mqqopensdkapiV2</string>
       
<string>mqqopensdkapiV3</string>
       
<string>mqqopensdkapiV4</string>
       
<string>mqzoneopensdk</string>
       
<string>wtloginmqq</string>
       
<string>wtloginmqq2</string>
       
<string>mqqwpa</string>
       
<string>mqzone</string>
       
<string>mqzonev2</string>
       
<string>mqzoneshare</string>
       
<string>wtloginqzone</string>
       
<string>mqzonewx</string>
       
<string>mqzoneopensdkapiV2</string>
       
<string>mqzoneopensdkapi19</string>
       
<string>mqzoneopensdkapi</string>
       
<string>mqqbrowser</string>
       
<string>mttbrowser</string>
       
<string>TencentWeibo</string>
       
<string>tencentweiboSdkv2</string>
       
<string>alipay</string>
       
<string>alipayshare</string>
       
<string>renrenios</string>
       
<string>renrenapi</string>
       
<string>renren</string>
       
<string>renreniphone</string>
       
<string>laiwangsso</string>
       
<string>yixin</string>
       
<string>yixinopenapi</string>
       
<string>yixinoauth</string>
       
<string>yixinfav</string>
       
<string>laiwangsso</string>
       
<string>instagram</string>
       
<string>whatsapp</string>
       
<string>line</string>
       
<string>tumblr</string>
       
<string>fbapi</string>
       
<string>fb-messenger-api</string>
       
<string>fbauth2</string>
       
<string>fbshareextension</string>
       
<string>kakao6d5e4ca98ba3b944020c2c90953318e9</string>
       
<string>kakaokompassauth</string>
       
<string>storykompassauth</string>
       
<string>kakaolink</string>
       
<string>kakaotalk-4.5.0</string>
       
<string>kakaostory-2.9.0</string>
       
<string>pinterestsdk.v1</string>
       
<string>dingtalk</string>
       
<string>dingtalk-open</string>
       
<!-- 印象笔记 -->
       
<string>evernote</string>
       
<string>en</string>
       
<string>enx</string>
       
<string>evernotecid</string>
       
<string>evernotemsg</string>
       
<!-- 有道云笔记-->
       
<string>youdaonote</string>
       
<string>ynotedictfav</string>
       
<string>com.youdao.note.todayViewNote</string>
       
<string>ynotesharesdk</string>
       
<!-- gplus-->
       
<string>gplus</string>
       
<!-- pocket-->
       
<string>pocket</string>
       
<string>readitlater</string>
       
<string>pocket-oauth-v1</string>
       
<string>fb131450656879143</string>
       
<string>en-readitlater-5776</string>
       
<string>com.ideashower.ReadItLaterPro3</string>
       
<string>com.ideashower.ReadItLaterPro</string>
       
<string>com.ideashower.ReadItLaterProAlpha</string>
       
<string>com.ideashower.ReadItLaterProEnterprise</string>
       
<!-- vk-->
       
<string>vk</string>
       
<string>vk-share</string>
       
<string>vkauthorize</string>
       
<!-- facebookMessage-->
       
<string>fbauth</string>
       
<string>fbauth2</string>
       
<string>fb-messenger-api20140430</string>
       
<string>fb-messenger-platform</string>
       
<string>fb-messenger-platform-20150128</string>
       
<string>fb-messenger-platform-20150218</string>
       
<string>fb-messenger-platform-20150305</string>
       
<string>fb-messenger-share</string>
    </array>

     schedule设置
          <key>CFBundleURLTypes</key>
   
<array>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string></string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>wb3921700954</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>weixin</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>wxdc1e388c3822c80b</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>tencent1105821097</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>alipayShare</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>ap2015111700822536</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>yixinSocialSDK</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>yx35664bdff4db42c2b7be1e29390c1a06</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>QQ41E97DA9</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>yx35664bdff4db42c2b7be1e29390c1a06</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>li4768945</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>Laiwang</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>8112117817424282305</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>fb506027402887373</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>rmcom.umeng.SocialSDK</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>qzoneScheme</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>mqzone</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>tencentApiIdentifier</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>tencent100424468.content</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>liyinIdentifier</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>li4768945</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>kakao6d5e4ca98ba3b944020c2c90953318e9</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>dingtalk</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>dingoalmlnohc0wggfedpk</string>
           
</array>
       
</dict>
       
<dict>
           
<key>CFBundleTypeRole</key>
           
<string>Editor</string>
           
<key>CFBundleURLName</key>
           
<string>vk5786123</string>
           
<key>CFBundleURLSchemes</key>
           
<array>
               
<string>vk5786123</string>
           
</array>
       
</dict>
    </array>

第三步:appdelegate中初始化 (设置友盟appkey 和分享的各个平台的id 和 password)

导入头文件
#import <UMSocialCore/UMSocialCore.h>
[[UMSocialManager defaultManager] setUmSocialAppkey:@"574eadf0e0f55aecbc003450a"];
    
    
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_WechatSession appKey:@"wxdc1e388c3822c80b" appSecret:@"3baf1193c85774b3fd9d18447d76cab0" redirectURL:@"http://mobile.umeng.com/social"];
    /*
     * 移除相应平台的分享,如微信收藏
     */
    //[[UMSocialManager defaultManager] removePlatformProviderWithPlatformTypes:@[@(UMSocialPlatformType_WechatFavorite)]];
    
    /* 设置分享到QQ互联的appID
     * U-Share SDK为了兼容大部分平台命名,统一用appKey和appSecret进行参数设置,而QQ平台仅需将appID作为U-Share的appKey参数传进即可。
     */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_QQ appKey:@"1105821097"/*设置QQ平台的appID*/  appSecret:nil redirectURL:@"http://mobile.umeng.com/social"];
    
    /* 设置新浪的appKey和appSecret */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Sina appKey:@"3921700954"  appSecret:@"04b48b094faeb16683c32669824ebdad" redirectURL:@"https://sns.whalecloud.com/sina2/callback"];
    
    /* 钉钉的appKey */
    [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_DingDing appKey:@"dingoalmlnohc0wggfedpk" appSecret:nil redirectURL:nil];
    
    /* 支付宝的appKey */
    [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_AlipaySession appKey:@"2015111700822536" appSecret:nil redirectURL:@"http://mobile.umeng.com/social"];
    
    
    /* 设置易信的appKey */
    [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_YixinSession appKey:@"yx35664bdff4db42c2b7be1e29390c1a06" appSecret:nil redirectURL:@"http://mobile.umeng.com/social"];
    
    /* 设置点点虫(原来往)的appKey和appSecret */
    [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_LaiWangSession appKey:@"8112117817424282305" appSecret:@"9996ed5039e641658de7b83345fee6c9" redirectURL:@"http://mobile.umeng.com/social"];
    
    /* 设置领英的appKey和appSecret */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Linkedin appKey:@"81t5eiem37d2sc"  appSecret:@"7dgUXPLH8kA8WHMV" redirectURL:@"https://api.linkedin.com/v1/people"];
    
    /* 设置Twitter的appKey和appSecret */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Twitter appKey:@"fB5tvRpna1CKK97xZUslbxiet"  appSecret:@"YcbSvseLIwZ4hZg9YmgJPP5uWzd4zr6BpBKGZhf07zzh3oj62K" redirectURL:nil];
    
    /* 设置Facebook的appKey和UrlString */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Facebook appKey:@"506027402887373"  appSecret:nil redirectURL:@"http://www.umeng.com/social"];
    
    /* 设置Pinterest的appKey */
    [[UMSocialManager defaultManager] setPlaform:UMSocialPlatformType_Pinterest appKey:@"4864546872699668063"  appSecret:nil redirectURL:nil];
    
    /* dropbox的appKey */
    [[UMSocialManager defaultManager] setPlaform: UMSocialPlatformType_DropBox appKey:@"k4pn9gdwygpy4av" appSecret:@"td28zkbyb9p49xu" redirectURL:@"https://mobile.umeng.com/social"];
    
    /* vk的appkey */
    [[UMSocialManager defaultManager]  setPlaform:UMSocialPlatformType_VKontakte appKey:@"5786123" appSecret:nil redirectURL:nil];

更换你的友盟key 和各个平台的key secret

第四步:在需要做分享的界面调用分享面板(点击button 调用该代码)

[UMSocialUIManager setPreDefinePlatforms:@[@(UMSocialPlatformType_Sina),@(UMSocialPlatformType_QQ),@(UMSocialPlatformType_Qzone),@(UMSocialPlatformType_WechatTimeLine),@(UMSocialPlatformType_WechatSession),@(UMSocialPlatformType_Facebook),@(UMSocialPlatformType_Twitter)]]; // 设置需要分享的平台
   
    //显示分享面板
    [UMSocialUIManager showShareMenuViewInWindowWithPlatformSelectionBlock:^(UMSocialPlatformType platformType, NSDictionary *userInfo) {
        // 根据获取的platformType确定所选平台进行下一步操作
        NSLog(@"回调");
        NSLog(@"%ld",(long)platformType);
        NSLog(@"%@",userInfo);
       
   
        //创建分享消息对象
        UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
       
        //创建网页内容对象
        NSString* thumbURL =  @"https://mobile.umeng.com/images/pic/home/social/img-1.png";
        UMShareWebpageObject *shareObject = [UMShareWebpageObject shareObjectWithTitle:@"博文你个逗比" descr:@"哈哈哈哈哈" thumImage:thumbURL];
        //设置网页地址
        shareObject.webpageUrl = @"http://mobile.umeng.com/social";
       
        //分享消息对象设置分享内容对象
        messageObject.shareObject = shareObject;
       
        //调用分享接口
        [[UMSocialManager defaultManager] shareToPlatform:platformType messageObject:messageObject currentViewController:self completion:^(id data, NSError *error) {
            NSLog(@"调用分享接口");
            if (error) {
                NSLog(@"调用失败%@",error);
                UMSocialLogInfo(@"************Share fail with error %@*********",error);
            }else{
                NSLog(@"调用成功");
                if ([data isKindOfClass:[UMSocialShareResponse class]]) {
                    UMSocialShareResponse *resp = data;
                    //分享结果消息
                    UMSocialLogInfo(@"response message is %@",resp.message);
                    //第三方原始返回的数据
                    UMSocialLogInfo(@"response originalResponse data is %@",resp.originalResponse);
                   
                }else{
                    UMSocialLogInfo(@"response data is %@",data);
                }
            }
            //        [self alertWithError:error];
        }];
    }];



2018-04-26 14:16:18 u014599371 阅读数 865

文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork

关于第三方登录/分享的接入, 很多时候使用的是友盟或者ShareSDK; 但并不是每次都想使用这些第三方的服务的, 这里作者整理了微信, QQ, 新浪微博原生第三方的接入:

[Swift]原生第三方接入: 微信篇--集成/登录/分享/支付
[Swift]原生第三方接入: QQ篇--集成/登录/分享
[Swift]原生第三方接入: 新浪微博篇--集成/登录/分享

一. 集成

1.1 新建应用

首先, 想要使用腾讯相关的功能, 您必须注册成为腾讯认证的开发者, 并且在腾讯开放平台创建了应用, 即已经获取到了相应的 ** APPID ** 和 ** APPKEY **.

1.2. 集成SDK

个人感觉腾讯的文档不太友好, 先给出官方文档地址官方SDK下载地址下载最新的文档及SDK. 将下载后的SDK中的 TencentOpenApi_IOS_Bundle.bundle 和 TencentOpenAPI.framework,添加到项目工程目录.

添加系统依赖库

到Build Phases -> Link Binary With Libraries, 添加以下系统库 :

  • Security.framework
  • SystemConfiguration.framework
  • CoreGraphics.Framework
  • CoreTelephony.framework
  • libiconv.dylib
  • libsqlite3.dylib
  • libstdc++.dylib
  • libz.dylib
    后面四个下新版Xcode中为:
  • libiconv.tbd
  • libsqlite3.tbd
  • libstdc++.tbd
  • libz.tbd
添加 TencentOpenApi_IOS_Bundle.bundle

然后来到Build Phases -> Copy Bundle Resources
将 TencentOpenApi_IOS_Bundle.bundle 添加进来(一般会自动添加到这里, 看下有没有即可, 没有的话, 点击 + 添加)

添加 -fobjc-arc

来到Build Settings -> Other Linker Flags
添加 -fobjc-arc
PS: 如果这里已有其他内容, 加个空格粘贴进去即可, 个人尝试可行.

添加URL Scheme

来到Info-> URL Types, 点击左下角的 + 新加一个Scheme

格式: tencent+AppID
例如你的AppID为: 123456789
则你的Scheme为: tencent123456789

添加URL Scheme
适配iOS 9+ , 添加Scheme白名单
  • ** 方式一 **

在Info.plist文件内新加字段: LSApplicationQueriesSchemes, 类型为Array(数组)
然后添加内容, 类型为String(字符串)
QQ需要添加以下字段:

  • mqqOpensdkSSoLogin,
  • mqqopensdkapiV2,
  • mqqopensdkapiV3,
  • wtloginmqq2,
  • mqq,
  • mqqapi
  • mqqopensdkdataline

QZONE 需要添加:

  • mqzoneopensdk,
  • mqzoneopensdkapi,
  • mqzoneopensdkapi19,
  • mqzoneopensdkapiV2,
  • mqqOpensdkSSoLogin,
  • mqqopensdkapiV2,
  • mqqopensdkapiV3,
  • wtloginmqq2,
  • mqqapi,
  • mqqwpa,
  • mqzone,
  • mqq
  • mqqopensdkapiV4
  • mqqopensdkdataline

如果同时需要QQ和Qzone, 只需要添加Qzone即可;

  • ** 方式二 **

或者, 在Info.plist文件右键, Open as... -> Source Code, 可打开文件, 进行编辑, 在倒数第三行(即: </dict> 标签的上面)的空白处添加以下代码:

<key>LSApplicationQueriesSchemes</key>
<array>
        <string>mqzoneopensdk</string>
        <string>mqzoneopensdkapi</string>
        <string>mqzoneopensdkapi19</string>
        <string>mqzoneopensdkapiV2</string>
        <string>mqqOpensdkSSoLogin</string>
        <string>mqqopensdkapiV2</string>
        <string>mqqopensdkapiV3</string>
        <string>wtloginmqq2</string>
        <string>mqqapi</string>
        <string>mqqwpa</string>
        <string>mqzone</string>
        <string>mqq</string>
        <string>mqqopensdkapiV4</string>
                <string> mqqopensdkdataline </string>
</array>

如果还有其他平台的白名单需要添加, 例如微信, 新浪微博, 只需要在<array></array>标签内添加对应的字段即可;

PS: Info.plist文件显示为Source Code后, 如果还想显示原来的列表格式, 可以: 邮件 -> Open as.. -> Property List 即可.

适配iOS 9+, 网络请求
  • **方式一: 暂时回退到HTTP请求 **
    在Info.plist文件中添加字段: ** NSAppTransportSecurity , 类型为字典;
    然后添加一个Key:
    NSAllowsArbitraryLoads **, 类型为Boolean, 值为 YES
回退到HTTP

或者以Source Code 打开Info.plist文件, 空白处添加以下代码:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
  • ** 方式二: 设置域 **

在项目的info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。
然后给它添加一个值: NSExceptionDomains,类型为字典类型;
把需要的支持的域添加給NSExceptionDomains
其中域作为Key,类型为字典类型。
每个域下面需要设置3个属性:
NSIncludesSubdomains、
NSExceptionRequiresForwardSecrecy、NSExceptionAllowsInsecureHTTPLoads。

均为Boolean类型,值分别为YES、NO、YES

QQ需要设置的域为:

QQ域

或者以Source Code 打开Info.plist文件, 空白处添加以下代码:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>qq.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>

PS: 这种方式需要对每个要以HTTP方式访问的域名进行设置, 比较麻烦, 建议使用第一种方式.

到此, 集成及适配结束...

PS: 在使用相关API的时候, 需要新建桥接头文件, 或者在已有桥接头文件内引用其头文件:

#import <TencentOpenAPI/TencentOAuth.h>
#import <TencentOpenAPI/QQApiInterfaceObject.h>
#import <TencentOpenAPI/QQApiInterface.h>

二. 登录

在AppDelegate.swift中注册app:
QQ在注册App的时候, 和其他的不同, 是要创建一个TencentOAuth对象, 来发起授权申请:

var tencentAuth: TencentOAuth! 
        
self. tencentAuth = TencentOAuth(appId: qqAppID, andDelegate: self)

在方法 func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool 中添加回调:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  let urlKey: String = options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String
   
  if urlKey == "com.tencent.mqq" {
            // QQ 的回调
            return  TencentOAuth.handleOpen(url)
        }
        
        return true
}

然后, 实现其代理方法:

func tencentDidLogin() {
        // 登录成功后要调用一下这个方法, 才能获取到个人信息
        self.tencentAuth.getUserInfo()
    }
    
    func tencentDidNotNetWork() {
        // 网络异常
    }
    
    func tencentDidNotLogin(_ cancelled: Bool) {
        
    }
    
    func getUserInfoResponse(_ response: APIResponse!) {
        // 获取个人信息
        if response.retCode == 0 {
            
            if let res = response.jsonResponse {
                             
                if let uid = self.tencentAuth.getUserOpenID() {
                   // 获取uid
                }
                
                if let name = res["nickname"] {
                    // 获取nickname
                }
                
                if let sex = res["gender"] {
                    // 获取性别
                }
                
                if let img = res["figureurl_qq_2"] {
                    // 获取头像
                }
               
            }
        } else {
           // 获取授权信息异常
        }
    }

最后在需要发起登录的地方添加以下代码来发起登录申请:

let appDel = UIApplication.shared.delegate as! AppDelegate
// 需要获取的用户信息
        let permissions = [kOPEN_PERMISSION_GET_USER_INFO, kOPEN_PERMISSION_GET_SIMPLE_USER_INFO]
        appDel.tencentAuth.authorize(permissions)

到此, 一个完整的QQ登录授权流程就完成了,并成功的获取到了QQ用户的相关信息, 即登录成功.
上面我是在AppDelegate.swift方法内处理的回调, 我们可以完全写在其他的类里面, 只需要将其代理对象设置为需要处理回调的对象即可.

三. 分享

一直在吐槽腾讯的开放平台, 找个文档真心不容易, 绕了一些弯路, 最后还是百度搜到了文档地址, 确实很尴尬. 虽然找到了官方文档说明, 但是不是特别详细, 可以下载其详细文档来参考设置.

PS: 在配置工程的时候需要注意, 如果需要兼容旧版本的手机QQ, 需要额外添加一个 ** URL Scheme ** : QQ + 十六进制的AppID ,不足八位的在首部补0 ; 例如你的AppID为: 123456 , 其十六进制为: 1E240, 则, URL Scheme 为: QQ0001E240


兼容低版本QQ

不过, 现在的QQ版本都比较高了, 至于低于哪个版本需要兼容, 官方文档没有提, 如果你的开发中适配低版本QQ时不能成功分享, 不妨添加试试.

如果是单独集成了分享, 在注册APP的时候依然是使用下面这个方法:

TencentOAuth(appId: "appid", andDelegate: nil)

如果没有登录, 这里代理传nil即可; 如果有登录, 按登录的设置即可;
在其代理类中实现代理( QQApiInterfaceDelegate )方法:

func onReq(_ req: QQBaseReq!) {
        
    }
    
    func onResp(_ resp: QQBaseResp!) {
        
        if resp is SendMessageToQQResp {
            let rs = resp as! SendMessageToQQResp
            if rs.type == 2 {
                // QQ分享返回的回调
                if rs.result == "0" {
                    // 分享成功
                    print("分享成功")
                } else {
                    print("分享失败")
                }
            }
        }
    }
    
    func isOnlineResponse(_ response: [AnyHashable : Any]!) {
        
    }

虽然我们只用在代理方法 ** func onResp(_ resp: QQBaseResp!) ** 中处理分享的回调, 但其他两个方法也是要实现.

PS: 这里需要注意, 如果项目中集成了微信, QQ的代理和微信的代理需要分开处理, 不能使用同一个对象, 否则会编译报错:

 Method 'onReq' with Objective-C selector 'onReq:' conflicts with previous declaration with the same Objective-C selector

然后在 ** func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool ** 方法中添加回调:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        
return QQApiInterface.handleOpen(url, delegate: LDShareUnit.shared)
    }

最后, 就是在需要分享的地方发起分享了, 在这里我遇到一个坑.

分享文本

以分享文本为例. 开始我的代码是这样的:

let textObj = QQApiTextObject()
        textObj.text = "这是分享到QQ的一段文字"
        textObj.title = "这是分享到QQ的标题"
        textObj.description = "一段描述"
        textObj.shareDestType = ShareDestTypeQQ // 分享到QQ 还是TIM, 必须指定
        
        let req = SendMessageToQQReq()
        req.message = textObj
        
        let code = QQApiInterface.send(req)  

        print(code)

这样写, 一直无法吊起QQ客户端, 打印返回的code值, 一直是: ** QQApiSendResultCode(rawValue: -1)**, 发送失败; 查了很多资料, 尝试了各种情况, 都没能解决. 最后搁置了些时间, 一时心血来潮, 换了个初始化的方法, 改成如下这样:

let textObj = QQApiTextObject(text: "这是分享到QQ的一段文字")
        //        textObj.text = "这是分享到QQ的一段文字"
        textObj?.title = "这是分享到QQ的标题"
        textObj?.description = "一段描述"
        textObj?.shareDestType = ShareDestTypeQQ // 分享到QQ 还是TIM, 必须指定
        
        let req = SendMessageToQQReq(content: textObj)
        req?.message = textObj
        //        QQApiInterface.openQQ()
        let code = QQApiInterface.send(req)
        
        print(code)

奇迹竟然发生了, 就这样, 成功的吊起QQ客户端, 并分享出去了.......

上面的title和description不需要设置, 设置了也看不到.
关于 shareDestType 参数, 官方文档指出必须设置, 否则无法正常工作, 我发现即使不设置, 默认也是吊起QQ发起分享的.

这算是一个比较大, 也是比较坑的一个大坑了, 花了很多时间, 做了一些无用功, 这也算是其API的一个不太友好的地方吧.

PS: 这里对 QQApiObject 的一个参数 cflag 做一下说明, 这是设置要分享的内容到什么地方, 空间, 收藏, 聊天, 电脑等

// QQApiObject control flags
enum
{
    kQQAPICtrlFlagQZoneShareOnStart = 0x01,
    kQQAPICtrlFlagQZoneShareForbid = 0x02,
    kQQAPICtrlFlagQQShare = 0x04,
    kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏
    kQQAPICtrlFlagQQShareDataline = 0x10,  //数据线
};
  • kQQAPICtrlFlagQQShareDataline
    只分享文字/图片等到电脑
  • kQQAPICtrlFlagQQShareFavorites
    只分享到文字/图片等到收藏
  • kQQAPICtrlFlagQQShare
    分享到QQ, 可以选择到联系人/ 收藏/ 电脑/ 空间等
  • kQQAPICtrlFlagQZoneShareForbid
    禁止分享到QQ空间
  • kQQAPICtrlFlagQZoneShareOnStart
    只分享到QQ空间

如果想要设置不同的分享目标, 可以设置这个参数.

分享图片
  • 单图
func shareImageToQQ() {
        // 原图 最大5M
        let img = UIImage(named: "1.jpg")
        let data = UIImageJPEGRepresentation(img!, 0.8)
        // 预览图 最大 1M
        let thumb = UIImage(named: "qq")
        let thData = UIImagePNGRepresentation(thumb!)
        
        let imgObj = QQApiImageObject(data: data, previewImageData: thData, title: "分享的一张图片", description: "分享图片的描述")
        
        let req = SendMessageToQQReq(content: imgObj)
        // 分享到QQ
        QQApiInterface.send(req)
// 分享到Qzone
//        QQApiInterface.sendReq(toQZone: req)
    }

如果要分享到QZone, 可以设置imgObj?.cflag = UInt64(kQQAPICtrlFlagQZoneShareOnStart), 也可以使用QQApiInterface.sendReq(toQZone: req)

  • 多图
    多图只能分享到 QQ收藏
func shareImagesToQQ() {
        // 多图不支持分享到QQ, 如果设置, 默认分享第一张
        // k可以分享多图到QQ收藏
        let img = UIImage(named: "1.jpg")
        let data = UIImageJPEGRepresentation(img!, 0.8)
        
        let img1 = UIImage(named: "10633861_160536558132_2.jpg")
        let data1 = UIImageJPEGRepresentation(img1!, 0.8)
        
        let thumb = UIImage(named: "qq")
        let thData = UIImagePNGRepresentation(thumb!)
        
        let imgObj = QQApiImageObject(data: data, previewImageData: thData, title: "分享多个图片", description: "描述", imageDataArray: [data!, data1!])
        // 设置分享目标为QQ收藏
        imgObj?.cflag = UInt64(kQQAPICtrlFlagQQShareFavorites)
        let req = SendMessageToQQReq(content: imgObj)
        
        QQApiInterface.send(req)
    }

PS: 这里在设置分享到QQ收藏的时候, 遇到一个错误提示:

 -canOpenURL: failed for URL: "mqqopensdkdataline://" - error: "This app is not allowed to query for scheme mqqopensdkdataline"

这是因为之前配置的工程白名单的时候没有添加** mqqopensdkdataline** , 在第一部分的 适配iOS 9+ , 添加Scheme白名单 中添加** mqqopensdkdataline**即可;

分享新闻链接

新闻可以分享到QQ, 也可以只分享到QZone

func shareNewsToQQ() {
    
        let url = URL(string: "http://www.jianshu.com/u/2846c3d3a974")
        
        let preURL = URL(string: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496830989997&di=5ca7528be6f496c6500a436c8775a67d&imgtype=0&src=http%3A%2F%2Fwww.pp3.cn%2Fuploads%2F201502%2F2015021111.jpg")
        
        let obj = QQApiNewsObject(url: url!, title: "关注作者流火绯瞳", description: "这是一个coder, 不是一个美女", previewImageURL: preURL!, targetContentType: QQApiURLTargetTypeNews)
        
        let req = SendMessageToQQReq(content: obj)
        // 分享到QQ
//        QQApiInterface.send(req)
        // 分享到QZone
        QQApiInterface.sendReq(toQZone: req)
    }

在创建新闻实例对象 QQApiNewsObject 的时候, 可以使用上面的方法, 也可以使用:

QQApiNewsObject(url: URL!, title: String!, description: String!, previewImageData: Data!, targetContentType: QQApiURLTargetType)

只是参数类型不同, 含义和上面的方法是一致的;

分享音乐

音乐可以分享到QQ和QZone

func shareMusicToQQ() {
        
        let url = URL(string: "http://y.qq.com/i/song.html?songid=432451&source=mobileQQ%23wechat_redirect")
        let preUrl = URL(string: "http://imgcache.qq.com/music/photo/mid_album_300/V/E/000J1pJ50cDCVE.jpg")
        
        let obj = QQApiAudioObject(url: url!, title: "歌曲名:不要说话", description: "专辑名:不想放手歌手名:陈奕迅", previewImageURL: preUrl!, targetContentType: QQApiURLTargetTypeVideo)
        
        let req = SendMessageToQQReq(content: obj)
        
        // 分享到QQ
//        QQApiInterface.send(req)
        // 分享到QZone
        QQApiInterface.sendReq(toQZone: req)
    }

这里在创建 QQApiAudioObject 实例对象的时候, 可以使用上面的方法, 也可以使用下面的方法, 只是参数类型不同, 其含义一致:

let obj = QQApiAudioObject(url: URL!, title: String!, description: String!, previewImageData: Data!, targetContentType: QQApiURLTargetType)
分享视频

视频可以分享到QQ和QZone

func shareVideoToQQ() {

        let url = URL(string: "视频URL地址")
        let preURL = URL(string: "视频预览图片URL地址")
        
        let obj = QQApiVideoObject(url: url!, title: "分享的视频名称", description: "视频内容描述", previewImageURL: preURL!, targetContentType: QQApiURLTargetTypeVideo)
        
        let req = SendMessageToQQReq(content: obj)
        
        // 分享到QQ
//        QQApiInterface.send(req)
        //分享到QZone
        QQApiInterface.sendReq(toQZone: req)
    }

这里在创建QQApiVideoObject实例的时候, 可以使用上面的方法, 也可以使用下面的方法, 只是参数类型不同, 其含义一致:

let obj = QQApiVideoObject(url: URL!, title: String!, description: String!, previewImageData: Data!, targetContentType: QQApiURLTargetType

(完)

以上便是 QQ登录分享的所有内容, 如有不正确的地方, 还请评论指出, 或者私信;

文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork



作者:流火绯瞳
链接:https://www.jianshu.com/p/c8db82d27b11
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2018-05-07 12:48:56 xy707707 阅读数 2639

但是用swift 接入友盟登陆或分享时,在授权(我使用的QQ)后跳回出现该问题,在Xcode控制台窗口出现

PBItemCollectionServicer connection disconnected.

并在AppDelegate文件开头处出现

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

这里写图片描述

Env:

  • Xcode Version 9.3 (9E145)

最后发现是系统回调设置的问题,文档 设置系统回调有一句这样的话(下面是文档中OC 对应的swift code)

func application(_ application: UIApplication, open url: URL,
sourceApplication: String?, annotation: Any) -> Bool {
    print("Open Url: \(url)")
    let result = UMSocialManager.default().handleOpen(url)
    if !result{

    }
    return result
}

注:此方法在swift4.1(Xcode 9.3)已废弃,Objective-C项目不影响。 新浪
平台外的其他平台可在swift项目中使用下面两种回调方法。

看来是此方法在 swift4.1 版本中已经废弃,这样造成没有设置回调,因此会出现上面的错误。坑的是,没有一点有用的报错信息, debug也未能看到什么信息。

哎,害我搜索了好久,浪费了好多时间。 具体来看友盟文档还可以,就是swift部分不是太详细。

解决方案:

将上面的方法改为

func application(_ app: UIApplication, open url: URL, options:    [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
   return UMSocialManager.default().handleOpen(url, options: options)
}
2016-08-29 20:17:49 jiang314 阅读数 4581

前言



直入主题

有关微信支付问题
在这里就不再介绍有关微信支付申请的流程了,小白可以参看微信开放平台微信服务号也可申请微信支付接口。这里是微信官方给的微信支付接入指南(然而并没有太大用处)


1. APP支付

1.业务流程:(这个很重要)


APP支付时序图

这个图需要看懂:为了各种原因,下单、请求支付、结果回调等一般安排公司后台完成
大致流程如下:

  • 【APP】用户使用商户APP选择商品完成下单
  • 【APP】向公司服务器请求生成支付订单
  • 【服务器】公司服务器调用统一下单接口
  • 【微信完成】生成订单返回预支付信息(prepay_id)给公司服务器
  • 【服务器】根据prepay_id生成带签名的支付信息,返回给移动端
  • 【微信APP】微信授权需用户确认
  • 【APP】通过公司服务器回调参数,调用微信SDK发起支付请求
  • 【微信APP】向微信服务器发送请求,返回支付授权
  • 【微信APP】用户确认支付,输入密码,提交微信服务器授权
  • 【微信服务器】验证授权,异步通知公司服务器和移动端APP
  • 【APP】可向公司服务器查询订单信息
    需要查看官方文档,请点击这里
    2.iOS开发xCode配置环境
    有关demo下载,根据本文_作者demo iOS微信官方demo
  • 向微信注册你的应用程序id,具体教程可点击这里
  • 下载"微信SDK",截止今日SDK已经更新到1.7.1已支持ipv6的。
  • 使用xcode新建一个工程,将libWeChatSDK.a,WXApi.h,WXApiObject.h三个文件添加到工程中,如下图:

    导入SDK文件
  • 添加依赖库:
    SystemConfiguration.framework,
    libz.tbd,
    libsqlite3.0.tbd,
    libc++.tbd.
    CoreTelephony.framework(不添加会报这个错误
    "_OBJC_CLASS_$_CTTelephonyNetworkInfo", referenced from:)

    需要添加库
  • 允许http请求,编辑Info.plist,在其中添加
    <key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <true/></dict>

    配置http请求
  • 配置URL scheme(应用跳转返回应用标识)
    还记得你在微信注册应用分配给你的id麽?就是需要这个东西


    查看微信AppID


    填写完成大概就是这样


    配置scheme
  • 这里需要注意一下在iOS9以后,唤起另一个APP时(此时是欢迎微信第三方APP完成支付)需要在info.plist中配置一下
    LSApplicationQueriesSchemesiOS9之后才会需要,iOS9之后提高了APP的安全性,需要给出一个类似白名单的东西,在白名单里面的才能打开APP。不然报错:
    -canOpenURL: failed for URL: "OpenAppTest://mark?id=007" - error: "This app is not allowed to query for scheme OpenAppTest"
    配置结束~应该就是这个样子~


    配置白名单

配置开发环境遇到的各种坑:
1.到此开发环境已经全部结束了,至于有些导入依赖库遇到的.dylib文件都是很老的版本了。xcode7.0之后导入.tbd即可。
2.至于有关在Build Setting的Search Paths中添加我们刚刚导入的SDK文件有关问题都不需要做了,Xcode都已经帮我们处理好了。至少使用xcode7.0之后都已经帮我们搞定了,在这里,不得不说微信这部分文档确实很老了。
......

到此为止,有关微信分享好友、朋友圈、收藏等第三方支付环境配置问题已经结束~接下来正式码砖了~


3.SDK使用

  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;方法中向微信终端注册你的AppID


    注册AppID
  2. 配置AppDelegate中的代码,效果图见后
    (1).导入头文件
    #import "WXApi.h"
    #import "WXApiObject.h"
    (2). 重写AppDelegate中handleOpenURLopenURL方法:(多个应用之间的调用)
    (3). 在需要与微信交互的地方,遵守WXApiDelegate协议,实现协议中的两个方法(处理向微信发送、微信返回结果回调)
    - (void)onReq:(BaseReq *)req- (void)onResp:(BaseResp *)resp;


AppDelegate

附: 需要给微信发消息,则需要调用WXApi的sendReq函数(例如:微信分享好友、朋友圈等时)
- (BOOL)sendReq:(BaseReq *)req
3.生成订单

用户选择商品后,在这里向后台服务器发送下单请求,服务器将生成订单信息等微信所下发的预支付id、签名等信息。然后发起支付调用surePay方法

4.完成支付请求

后台生成prepayid、签名sign后调用微信SDK发起支付

//需要创建这个支付对象
PayReq *req = [[PayReq alloc] init];

//应用id
req.openID = kWXAPP_ID;

// 商家商户号
req.partnerId = kWX_PARTNERID;

// 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你
req.prepayId = @"";//self.orderWithWX.prepayid;

// 根据财付通文档填写的数据和签名
//这个比较特殊,是固定的,只能是即req.package = Sign=WXPay
req.package = @"Sign=WXPay";

// 随机编码,为了防止重复的,在后台生成
req.nonceStr = @"";//self.orderWithWX.noncestr;

// 这个是时间戳,也是在后台生成的,为了验证支付的
NSString * stamp = @"";//self.orderWithWX.timestamp;
req.timeStamp = stamp.intValue;

// 这个签名也是后台做的
req.sign = @"";//self.orderWithWX.sign;

//发送请求到微信,等待微信返回onResp
[WXApi sendReq:req];

5.支付结果回调
还记得在AppDelegate中配置的回调方法麽- (void)onResp:(BaseResp*)resp;
如下图:


回调结果处理

有关demo下载,根据本文_作者demo iOS微信官方demo

2014-10-08 14:19:12 totogo2010 阅读数 41507

要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件。这个文件包含了.DSYM文件。

我一般的做法是,发布成功后,把这个文件.xcarchive直接提交到代码版本库对应的版本分支里,这样就不会搞丢了。

这个文件在哪呢?打开XCode->菜单Window->Organizer,在编译成功的文件上右键,就能打开了。


两种比较麻烦的方法。

第一种方法:

使用dwarfdump命令

dwarfdump --uuid xx.app.dSYM     用来得到app的UUID。
dwarfdump --lookup 0x12b45d -arch armv7 xx.app.dSYM  使错误的日志能看懂,把相应的内存地址对应到正确的地方。
如果一开始dwarfdump命令不能用的话,要先装Command Line Tools,这个在设置里面能下载(cmd+“,”打开设置)。另外还必须在进入.DSYM所在文件夹。

使用dwarfdump需要安装Command Line Tools,XCode里设置下载。而且需要进入.DSYM所在文件夹里进行操作。


第二种方法:

使用xcrun atos命令

atos -o YourApp.app.dSYM/Contents/Resources/DWARF/YourApp 0x00062867


下面重点推荐下这个方法,方便快捷

第三方法:可视化工具

下面这是我的项目里通过友盟统计到的崩溃日志,如果光看这些日志报告的话,是不会知道是哪行代码引起的。

使用方法是把对应版本的.xcarchive文件拖到工具。对比UUID和友盟里日志是否一致,一致就把错误的地址信息拷贝到箭头处。点击分析。

即可得出具体代码崩溃位置。很简单吧。


dSYM 文件分析工具 http://answerhuang.duapp.com/index.php/2014/07/06/dsym_tool/

这是这位博主answer-huang开发了一个工具,专门用来快速定位崩溃日志的代码。感谢这位仁兄的提供这么方便的工具。

工具代码还是开源的:https://github.com/answer-huang/dSYMTools

工具下载地址:http://pan.baidu.com/s/1bnkxPvT

百度网盘的下载地址容易失效,我上传csdn下载里,当然是免积分下载了。

地址:http://download.csdn.net/detail/totogo2010/8012367



没有更多推荐了,返回首页