├── .gitignore ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md ├── YHThirdManager.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── YHThirdManager.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── WorkspaceSettings.xcsettings └── YHThirdManager ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── Resource ├── 1.png └── big_image.jpeg ├── Sources ├── Alipay │ ├── YHAlipayManager.h │ └── YHAlipayManager.m ├── Core │ ├── YHThirdDefine.h │ ├── YHThirdHttpRequest.h │ └── YHThirdHttpRequest.m ├── QQ │ ├── YHQQManager.h │ ├── YHQQManager.m │ ├── YHQQUserInfo.h │ └── YHQQUserInfo.m ├── Sina │ ├── YHSinaManager.h │ ├── YHSinaManager.m │ ├── YHSinaUserInfo.h │ └── YHSinaUserInfo.m ├── WeiXin Pay │ ├── YHWXManager+Pay.h │ └── YHWXManager+Pay.m └── WeiXin │ ├── YHWXAuthResult.h │ ├── YHWXAuthResult.m │ ├── YHWXManager.h │ ├── YHWXManager.m │ ├── YHWXUserInfo.h │ └── YHWXUserInfo.m ├── ThirdParty ├── QQ │ └── TencentOpenAPI.framework │ │ ├── Headers │ │ ├── QQApiInterface.h │ │ ├── QQApiInterfaceObject.h │ │ ├── TencentOAuth.h │ │ └── sdkdef.h │ │ └── TencentOpenAPI └── WeiXin │ ├── WXApi.h │ ├── WXApiObject.h │ ├── WechatAuthSDK.h │ └── libWeChatSDK.a ├── ViewController.h ├── ViewController.m └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | # Mac OS X Finder and whatnot 6 | .DS_Store 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xcuserstate 26 | *.xccheckout 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | #CocoaPods 35 | Pods/ 36 | 37 | YHThirdManager/SDK.h 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 liujun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '9.0' 3 | target 'YHThirdManager' do 4 | use_frameworks! 5 | 6 | pod 'Weibo_SDK', :git => 'https://github.com/sinaweibosdk/weibo_ios_sdk.git' 7 | pod 'AlipaySDK-iOS' 8 | pod 'MBProgressHUD' 9 | 10 | pod 'AFNetworking' 11 | 12 | end 13 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (4.0.0): 3 | - AFNetworking/NSURLSession (= 4.0.0) 4 | - AFNetworking/Reachability (= 4.0.0) 5 | - AFNetworking/Security (= 4.0.0) 6 | - AFNetworking/Serialization (= 4.0.0) 7 | - AFNetworking/UIKit (= 4.0.0) 8 | - AFNetworking/NSURLSession (4.0.0): 9 | - AFNetworking/Reachability 10 | - AFNetworking/Security 11 | - AFNetworking/Serialization 12 | - AFNetworking/Reachability (4.0.0) 13 | - AFNetworking/Security (4.0.0) 14 | - AFNetworking/Serialization (4.0.0) 15 | - AFNetworking/UIKit (4.0.0): 16 | - AFNetworking/NSURLSession 17 | - AlipaySDK-iOS (15.6.8) 18 | - MBProgressHUD (1.2.0) 19 | - Weibo_SDK (3.2.7) 20 | 21 | DEPENDENCIES: 22 | - AFNetworking 23 | - AlipaySDK-iOS 24 | - MBProgressHUD 25 | - Weibo_SDK (from `https://github.com/sinaweibosdk/weibo_ios_sdk.git`) 26 | 27 | SPEC REPOS: 28 | trunk: 29 | - AFNetworking 30 | - AlipaySDK-iOS 31 | - MBProgressHUD 32 | 33 | EXTERNAL SOURCES: 34 | Weibo_SDK: 35 | :git: https://github.com/sinaweibosdk/weibo_ios_sdk.git 36 | 37 | CHECKOUT OPTIONS: 38 | Weibo_SDK: 39 | :commit: 90a5cf8d5dfb03ccf62b1c8e1a17fea766dc806b 40 | :git: https://github.com/sinaweibosdk/weibo_ios_sdk.git 41 | 42 | SPEC CHECKSUMS: 43 | AFNetworking: d9fdf484a3c723ec3c558a41cc5754c7e845ee77 44 | AlipaySDK-iOS: 703a55774a37f412410ab04af96c011b91ec58cb 45 | MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 46 | Weibo_SDK: 5a4d08f7e1fedbb635435e4585c8c0439c7da089 47 | 48 | PODFILE CHECKSUM: 26f16d163bf4b8f9fcd11832700308d515655d5a 49 | 50 | COCOAPODS: 1.9.1 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 一个好用的社交化组件,目前支持微信(包含支付功能和不包含支付功能)、新浪微博、QQ、支付宝(暂时只支持支付,不支持授权,因为我也没做过授权🤣) 2 | 3 | # 🔥即将增加FaceBook,谷歌、苹果登录 4 | 5 |
6 | 7 | # SDK的核心封装已完成,Demo未完成 8 | # 目前遇到个问题,`universalLink`本人暂时无法配置,因此微信和QQ的相关功能暂时无法进行测试,之后会完善 9 | 10 |
11 | 12 | # 请根据自己项目的实际情况,导入对应的模块(重要的事情说3遍) 13 | # 请根据自己项目的实际情况,导入对应的模块(重要的事情说3遍) 14 | # 请根据自己项目的实际情况,导入对应的模块(重要的事情说3遍) 15 |
16 |
17 |
18 | 该开源库编写的初衷:替代友盟等三方库。因为友盟等三方库虽然使用起来比较方便,但是个人觉得太臃肿了。 19 |
20 |
21 |
22 | 23 | # 该组件暂时不支持pod,请使用手动的方式集成进自己的项目中。 24 |
25 |
26 | 27 | # 下载下来之后,请`pod install`,之后运行会提示缺少`SDK.h`文件,请自己新建一个同名文件。该文件是保存的APPID,key等各种常量的 28 | ``` 29 | #define WECHAT_APP_ID @"" 30 | #define WECHAT_APP_SECRET @"" 31 | #define QQ_APP_ID @"" 32 | #define SINA_APP_KEY @"" 33 | #define SINA_Redirect_URL @"" 34 | ``` 35 |
36 |
37 | 38 | ### 1、必须导入的三方库 39 | 40 | ``` 41 | pod 'MBProgressHUD' 42 | pod 'AFNetworking' # 请导入最新版本的AFNetworking 43 | ``` 44 | 45 | ### 2、`Podfile`文件里加上`use_frameworks!` 46 | ### 3、源文件里面`Core`文件夹是必须导入的 47 | ### 4、关于微信:如果你的应用包含支付功能,请导入`WeiXin Pay`文件夹,否则不要导入。另外请自行前往微信官方下载包含支付功能的SDK,否则请下载不包含支付功能的SDK 48 | 49 | # 总结 50 | #### 1、友盟等三方分享SDK虽然使用起来比较方便,但是有很多限制。比如一个App如果运营到后期,肯定不止分享和登录这么简单的功能。比如要集成微信支付,这个时候使用友盟自带的微信SDK是完不成的,即使使用完整版,因为APP无法调用友盟自带的微信SDK里面的API。再比如也许会增加获取我的微博列表,同样无法使用友盟自带的微博SDK完成。这个时候,即必须要再次导入微信或者微博SDK才能完成。换句话说,友盟等三方分享SDK,仅仅只是为分享和登录服务的,无法完成其他功能。在项目前期使用友盟确实比较方便,但是项目后期,继续使用友盟个人觉得不是很合适。 51 | #### 2、在使用友盟完整版的情况下,要使用微信支付、获取微博列表等这些功能,也无法完成,除非自己再次导入SDK。 52 | #### 3、在第一次打开三方应用时,iOS系统会给用户一个选项,即"是否允许打开xxx"的这个一个弹出框,这个弹出框属于系统级别,开发者无法获取到用户到底是点击了"确定"还是"取消"。如果界面上有一个按钮,点击这个按钮时,会有个loading圈显示,如果这个时候用户点击了"取消",那么loading圈仍然在继续显示,无法取消,本人已经看到很多APP都有这个问题;另外,即使用户点击了"确定"按钮,跳转到了三方应用了,这个时候,如果用户点击屏幕左上角返回APP,loading圈仍然在加载,因为开发者仍然获取不到用户点击屏幕左上角这个事件。`YHThirdManager`完美的解决了这些问题 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /YHThirdManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /YHThirdManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /YHThirdManager.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /YHThirdManager.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /YHThirdManager.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | PreviewsEnabled 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /YHThirdManager/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /YHThirdManager/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "YHQQManager.h" 11 | #import "YHWXManager.h" 12 | #import "YHSinaManager.h" 13 | #import "SDK.h" 14 | 15 | @interface AppDelegate () 16 | 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | 22 | /** 23 | 24 | kWechatNoPay:是否使用无支付功能模块的宏定义 25 | 26 | */ 27 | 28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 29 | 30 | [[YHQQManager sharedInstance] initWithAppID:QQ_APP_ID universalLink:@"https:///apple-app-site-association"]; 31 | [[YHWXManager sharedInstance] initWithAppID:WECHAT_APP_ID appSecret:WECHAT_APP_SECRET universalLink:@""]; 32 | [[YHSinaManager sharedInstance] initWithAppID:SINA_APP_KEY redirectURI:SINA_Redirect_URL]; 33 | 34 | return YES; 35 | } 36 | 37 | // 9.0之后 38 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options{ 39 | [[YHWXManager sharedInstance] handleOpenURL:url]; 40 | [[YHQQManager sharedInstance] handleOpenURL:url]; 41 | [[YHSinaManager sharedInstance] handleOpenURL:url]; 42 | return YES; 43 | } 44 | 45 | // 9.0之前 46 | - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ 47 | [[YHWXManager sharedInstance] handleOpenURL:url]; 48 | [[YHQQManager sharedInstance] handleOpenURL:url]; 49 | [[YHSinaManager sharedInstance] handleOpenURL:url]; 50 | return YES; 51 | } 52 | 53 | // 测试发现,在模拟器上,未安装微博,使用网页打开微博,点击取消,程序崩溃,加上下面这个方法后,程序正常运行 54 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ 55 | [[YHWXManager sharedInstance] handleOpenURL:url]; 56 | [[YHQQManager sharedInstance] handleOpenURL:url]; 57 | [[YHSinaManager sharedInstance] handleOpenURL:url]; 58 | return YES; 59 | } 60 | 61 | - (void)applicationWillResignActive:(UIApplication *)application { 62 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 63 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 64 | } 65 | 66 | 67 | - (void)applicationDidEnterBackground:(UIApplication *)application { 68 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 69 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 70 | } 71 | 72 | 73 | - (void)applicationWillEnterForeground:(UIApplication *)application { 74 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 75 | } 76 | 77 | 78 | - (void)applicationDidBecomeActive:(UIApplication *)application { 79 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 80 | } 81 | 82 | 83 | - (void)applicationWillTerminate:(UIApplication *)application { 84 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 85 | } 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /YHThirdManager/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /YHThirdManager/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /YHThirdManager/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /YHThirdManager/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /YHThirdManager/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleURLTypes 20 | 21 | 22 | CFBundleTypeRole 23 | Editor 24 | CFBundleURLSchemes 25 | 26 | wxd009b4125786d152 27 | 28 | 29 | 30 | CFBundleTypeRole 31 | Editor 32 | CFBundleURLSchemes 33 | 34 | tencent1106091425 35 | 36 | 37 | 38 | CFBundleTypeRole 39 | Editor 40 | CFBundleURLSchemes 41 | 42 | wb1354693372 43 | 44 | 45 | 46 | CFBundleTypeRole 47 | Editor 48 | CFBundleURLSchemes 49 | 50 | qaq 51 | 52 | 53 | 54 | CFBundleTypeRole 55 | Editor 56 | CFBundleURLSchemes 57 | 58 | tbopen23824132 59 | 60 | 61 | 62 | CFBundleVersion 63 | 1 64 | LSApplicationQueriesSchemes 65 | 66 | qaq 67 | wechat 68 | weixin 69 | sinaweibohd 70 | sinaweibo 71 | sinaweibosso 72 | weibosdk 73 | weibosdk2.5 74 | mqqapi 75 | mqq 76 | mqqOpensdkSSoLogin 77 | mqqconnect 78 | mqqopensdkdataline 79 | mqqopensdkgrouptribeshare 80 | mqqopensdkfriend 81 | mqqopensdkapi 82 | mqqopensdkapiV2 83 | mqqopensdkapiV3 84 | mqqopensdkapiV4 85 | mqzoneopensdk 86 | wtloginmqq 87 | wtloginmqq2 88 | mqqwpa 89 | mqzone 90 | mqzonev2 91 | mqzoneshare 92 | wtloginqzone 93 | mqzonewx 94 | mqzoneopensdkapiV2 95 | mqzoneopensdkapi19 96 | mqzoneopensdkapi 97 | mqqbrowser 98 | mttbrowser 99 | tim 100 | timapi 101 | timopensdkfriend 102 | timwpa 103 | timgamebindinggroup 104 | timapiwallet 105 | timOpensdkSSoLogin 106 | wtlogintim 107 | timopensdkgrouptribeshare 108 | timopensdkapiV4 109 | timgamebindinggroup 110 | timopensdkdataline 111 | wtlogintimV1 112 | timapiV1 113 | alipay 114 | alipayauth 115 | safepay 116 | alipayshare 117 | dingtalk 118 | dingtalk-open 119 | linkedin 120 | linkedin-sdk2 121 | linkedin-sdk 122 | laiwangsso 123 | yixin 124 | yixinopenapi 125 | instagram 126 | whatsapp 127 | line 128 | fbapi 129 | fb-messenger-api 130 | fb-messenger-share-api 131 | fbauth2 132 | fbshareextension 133 | kakaofa63a0b2356e923f3edd6512d531f546 134 | kakaokompassauth 135 | storykompassauth 136 | kakaolink 137 | kakaotalk-4.5.0 138 | kakaostory-2.9.0 139 | pinterestsdk.v1 140 | tumblr 141 | evernote 142 | en 143 | enx 144 | evernotecid 145 | evernotemsg 146 | youdaonote 147 | ynotedictfav 148 | com.youdao.note.todayViewNote 149 | ynotesharesdk 150 | gplus 151 | pocket 152 | readitlater 153 | pocket-oauth-v1 154 | fb131450656879143 155 | en-readitlater-5776 156 | com.ideashower.ReadItLaterPro3 157 | com.ideashower.ReadItLaterPro 158 | com.ideashower.ReadItLaterProAlpha 159 | com.ideashower.ReadItLaterProEnterprise 160 | vk 161 | vk-share 162 | vkauthorize 163 | twitter 164 | twitterauth 165 | taobao 166 | tbopen 167 | tmall 168 | 169 | LSRequiresIPhoneOS 170 | 171 | NSAppTransportSecurity 172 | 173 | NSAllowsArbitraryLoads 174 | 175 | 176 | NSPhotoLibraryAddUsageDescription 177 | 111 178 | NSPhotoLibraryUsageDescription 179 | 222 180 | UILaunchStoryboardName 181 | LaunchScreen 182 | UIMainStoryboardFile 183 | Main 184 | UIRequiredDeviceCapabilities 185 | 186 | armv7 187 | 188 | UISupportedInterfaceOrientations 189 | 190 | UIInterfaceOrientationPortrait 191 | 192 | UISupportedInterfaceOrientations~ipad 193 | 194 | UIInterfaceOrientationPortrait 195 | UIInterfaceOrientationPortraitUpsideDown 196 | UIInterfaceOrientationLandscapeLeft 197 | UIInterfaceOrientationLandscapeRight 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /YHThirdManager/Resource/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liujunliuhong/YHThirdManager/9b0fc0c38ec0cdf67caa7b5e1d6447933a9c18ac/YHThirdManager/Resource/1.png -------------------------------------------------------------------------------- /YHThirdManager/Resource/big_image.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liujunliuhong/YHThirdManager/9b0fc0c38ec0cdf67caa7b5e1d6447933a9c18ac/YHThirdManager/Resource/big_image.jpeg -------------------------------------------------------------------------------- /YHThirdManager/Sources/Alipay/YHAlipayManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHAlipayManager.h 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2020/1/17. 6 | // Copyright © 2020 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** 14 | * 支付宝相关功能封装 15 | * SDK版本:v15.6.8 16 | * 文档:https://docs.open.alipay.com/204/105295/ 17 | */ 18 | @interface YHAlipayManager : NSObject 19 | + (instancetype)sharedInstance; 20 | + (instancetype)new NS_UNAVAILABLE; 21 | - (instancetype)init NS_UNAVAILABLE; 22 | 23 | 24 | /// handleOpenURL 25 | /// @param URL URL 26 | - (void)handleOpenURL:(NSURL *)URL; 27 | 28 | 29 | /// 支付 30 | /// @param order 订单参数,从服务端获取 31 | /// @param scheme scheme 32 | /// @param completionBlock 回调 33 | - (void)payWithOrder:(NSString *)order 34 | scheme:(NSString *)scheme 35 | completionBlock:(void(^_Nullable)(NSDictionary *resultDic))completionBlock; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Alipay/YHAlipayManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHAlipayManager.m 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2020/1/17. 6 | // Copyright © 2020 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHAlipayManager.h" 10 | #import 11 | #import "YHThirdDefine.h" 12 | 13 | #if __has_include() 14 | #import 15 | #endif 16 | 17 | @interface YHAlipayManager() 18 | @property (nonatomic, copy) void(^payCompletionBlock)(NSDictionary *resultDic); 19 | @end 20 | 21 | @implementation YHAlipayManager 22 | 23 | + (instancetype)sharedInstance{ 24 | static YHAlipayManager *mgr = nil; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | mgr = [[self alloc] init]; 28 | }); 29 | return mgr; 30 | } 31 | 32 | - (instancetype)init 33 | { 34 | self = [super init]; 35 | if (self) { 36 | 37 | } 38 | return self; 39 | } 40 | 41 | /// handleOpenURL 42 | /// @param URL URL 43 | - (void)handleOpenURL:(NSURL *)URL{ 44 | YHThird_WeakSelf 45 | if ([URL.host isEqualToString:@"safepay"]) { 46 | #if __has_include() 47 | [[AlipaySDK defaultService] processOrderWithPaymentResult:URL standbyCallback:^(NSDictionary *resultDic) { 48 | YHThirdDebugLog(@"[支付宝] [processOrderWithPaymentResult:standbyCallback:] %@", resultDic); 49 | if (resultDic) { 50 | if (weakSelf.payCompletionBlock) { 51 | weakSelf.payCompletionBlock(resultDic); 52 | } 53 | } 54 | }]; 55 | #endif 56 | } 57 | } 58 | 59 | /// 支付 60 | /// @param order 订单参数,从服务端获取 61 | /// @param scheme scheme 62 | /// @param completionBlock 回调 63 | - (void)payWithOrder:(NSString *)order scheme:(NSString *)scheme completionBlock:(void (^)(NSDictionary * _Nonnull))completionBlock{ 64 | #if __has_include() 65 | [[AlipaySDK defaultService] payOrder:order fromScheme:scheme callback:^(NSDictionary *resultDic) { 66 | YHThirdDebugLog(@"[支付宝] [payOrder:fromScheme:callback:] %@", resultDic); 67 | if (resultDic) { 68 | if (completionBlock) { 69 | completionBlock(resultDic); 70 | } 71 | } 72 | }]; 73 | #endif 74 | } 75 | 76 | 77 | 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Core/YHThirdDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHThirdDefine.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #ifndef YHThirdDefine_h 10 | #define YHThirdDefine_h 11 | 12 | #ifdef DEBUG 13 | #define YHThirdDebugLog(format, ...) printf("[👉] %s\n", [[NSString stringWithFormat:format, ##__VA_ARGS__] UTF8String]) 14 | #else 15 | #define YHThirdDebugLog(format, ...) 16 | #endif 17 | 18 | #define YHThirdError(__msg__) [NSError errorWithDomain:@"com.yinhe.yhthird.error" code:-1 userInfo:@{NSLocalizedDescriptionKey: __msg__}] 19 | 20 | 21 | #define YHThird_WeakSelf __weak typeof(self) weakSelf = self; 22 | 23 | #endif /* YHThirdDefine_h */ 24 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Core/YHThirdHttpRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHThirdHttpRequest.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef NS_ENUM(NSUInteger, YHThirdHttpRequestMethod) { 14 | YHThirdHttpRequestMethodGET, 15 | YHThirdHttpRequestMethodPOST, 16 | }; 17 | 18 | @interface YHThirdHttpRequest : NSObject 19 | 20 | + (instancetype)sharedInstance; 21 | + (instancetype)new NS_UNAVAILABLE; 22 | - (instancetype)init NS_UNAVAILABLE; 23 | 24 | - (NSString *)urlTranscoding:(NSString *)url; 25 | 26 | - (void)requestWithURL:(NSString *)url 27 | method:(YHThirdHttpRequestMethod)method 28 | parameter:(nullable NSDictionary *)parameter 29 | successBlock:(void(^)(id responseObject))successBlock 30 | failureBlock:(void(^)(NSError *error))failureBlock; 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Core/YHThirdHttpRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHThirdHttpRequest.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHThirdHttpRequest.h" 10 | @import AFNetworking; 11 | 12 | #define kTimeOutInterval 60 13 | 14 | @interface YHThirdHttpRequest () 15 | 16 | @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; 17 | 18 | @property (nonatomic, strong) AFJSONRequestSerializer *requestSerializerForJSON; 19 | @property (nonatomic, strong) AFJSONResponseSerializer *responseSerializerForJSON; 20 | 21 | @end 22 | 23 | @implementation YHThirdHttpRequest 24 | 25 | + (instancetype)sharedInstance{ 26 | static YHThirdHttpRequest *request = nil; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | request = [[self alloc] init]; 30 | }); 31 | return request; 32 | } 33 | 34 | - (instancetype)init 35 | { 36 | self = [super init]; 37 | if (self) { 38 | // sessionManager 39 | self.sessionManager = [AFHTTPSessionManager manager]; 40 | // requestSerializerForJSON 41 | AFJSONRequestSerializer *requestSerializerForJSON = [AFJSONRequestSerializer serializerWithWritingOptions:NSJSONReadingAllowFragments | NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers]; 42 | requestSerializerForJSON.timeoutInterval = kTimeOutInterval; 43 | [requestSerializerForJSON setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 44 | // responseSerializerForJSON 45 | AFJSONResponseSerializer *responseSerializerForJSON = [AFJSONResponseSerializer serializer]; 46 | responseSerializerForJSON.acceptableContentTypes = [NSSet setWithObjects: 47 | @"application/json", 48 | @"text/json", 49 | @"text/javascript", 50 | @"text/html", 51 | @"text/css", 52 | @"text/xml", 53 | @"text/plain", 54 | @"application/javascript", 55 | @"image/*", 56 | nil]; 57 | // 58 | self.sessionManager.requestSerializer = requestSerializerForJSON; 59 | self.sessionManager.responseSerializer = responseSerializerForJSON; 60 | } 61 | return self; 62 | } 63 | 64 | - (void)requestWithURL:(NSString *)url 65 | method:(YHThirdHttpRequestMethod)method 66 | parameter:(NSDictionary *)parameter 67 | successBlock:(void (^)(id _Nonnull))successBlock 68 | failureBlock:(void (^)(NSError * _Nonnull))failureBlock{ 69 | NSString *newURL = [self urlTranscoding:url]; 70 | switch (method) { 71 | case YHThirdHttpRequestMethodPOST: 72 | { 73 | [self POST_WithURL:newURL param:parameter successBlock:successBlock errorBlock:failureBlock]; 74 | } 75 | break; 76 | case YHThirdHttpRequestMethodGET: 77 | { 78 | [self GET_WithURL:newURL param:parameter successBlock:successBlock errorBlock:failureBlock]; 79 | } 80 | break; 81 | default: 82 | break; 83 | } 84 | } 85 | 86 | - (NSURLSessionDataTask *)POST_WithURL:(NSString *)url 87 | param:(NSDictionary *)param 88 | successBlock:(void(^)(id responseObject))successBlock 89 | errorBlock:(void(^)(NSError *error))errorBlock{ 90 | NSURLSessionDataTask *task = [self.sessionManager POST:url parameters:param headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 91 | if (successBlock) { 92 | successBlock(responseObject); 93 | } 94 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 95 | if (errorBlock) { 96 | errorBlock(error); 97 | } 98 | }]; 99 | return task; 100 | } 101 | 102 | - (NSURLSessionDataTask *)GET_WithURL:(NSString *)url 103 | param:(NSDictionary *)param 104 | successBlock:(void(^)(id responseObject))successBlock 105 | errorBlock:(void(^)(NSError *error))errorBlock{ 106 | NSURLSessionDataTask *task = [self.sessionManager GET:url parameters:param headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 107 | if (successBlock) { 108 | successBlock(responseObject); 109 | } 110 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 111 | if (errorBlock) { 112 | errorBlock(error); 113 | } 114 | }]; 115 | return task; 116 | } 117 | 118 | - (NSString *)urlTranscoding:(NSString *)url{ 119 | NSString *transcodingString = @""; 120 | if (url.length == 0 || !url) { 121 | return transcodingString; 122 | } 123 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0 124 | NSString * kCharactersGeneralDelimitersToEncode = @":#[]@"; 125 | NSString * kCharactersSubDelimitersToEncode = @"!$&'()*+,;="; 126 | NSMutableCharacterSet *allowedCharacterSet = (NSMutableCharacterSet *)[NSMutableCharacterSet URLQueryAllowedCharacterSet]; 127 | [allowedCharacterSet removeCharactersInString:[kCharactersGeneralDelimitersToEncode stringByAppendingString:kCharactersSubDelimitersToEncode]]; 128 | transcodingString = [url stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; 129 | #else 130 | #pragma clang diagnostic push 131 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 132 | transcodingString = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 133 | #pragma clang diagnostic pop 134 | #endif 135 | return transcodingString; 136 | } 137 | @end 138 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/QQ/YHQQManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHQQManager.h 3 | // QAQSmooth 4 | // 5 | // Created by apple on 2019/3/8. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #if __has_include() && __has_include() 12 | #import 13 | #import 14 | #endif 15 | 16 | #import "YHQQUserInfo.h" 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | // 分享类型 21 | typedef NS_ENUM(NSUInteger, YHQQShareType) { 22 | YHQQShareType_QQ, // 分享到QQ 23 | YHQQShareType_QZone, // 分享到QQ空间 24 | }; 25 | 26 | // 分享到哪儿 27 | typedef NS_ENUM(NSUInteger, YHQQShareDestType) { 28 | YHQQShareDestType_QQ, // 分享到QQ 29 | YHQQShareDestType_TIM, // 分享到TIM 30 | }; 31 | 32 | 33 | /** 34 | * SDK版本:3.3.7 35 | * QQ登录、分享功能的封装(文档:http://wiki.connect.qq.com/) 36 | * 不包含QQ支付功能,QQ支付和分享是不同的SDK 37 | * 吐槽一下QQ的SDK:在sdkdef.h文件里,定义了log等级,但是并没有提供关闭日志的方法,导致每次QQ登录的时候,控制台一堆的log 38 | */ 39 | @class MBProgressHUD; 40 | @interface YHQQManager : NSObject 41 | #if __has_include() && __has_include() 42 | /// 初始化SDK的appID 43 | @property (nonatomic, copy, readonly) NSString *appID; 44 | /// 授权成功后的信息保存在此对象里面,需要什么信息自己去拿 45 | @property (nonatomic, strong, readonly, nullable) TencentOAuth *oauth; 46 | /// QQ登录获取的个人信息 47 | @property (nonatomic, strong, readonly, nullable) YHQQUserInfo *userInfo; 48 | #endif 49 | 50 | + (instancetype)sharedInstance; 51 | + (instancetype)new NS_UNAVAILABLE; 52 | - (instancetype)init NS_UNAVAILABLE; 53 | 54 | #if __has_include() && __has_include() 55 | #pragma mark Init 56 | /// QQ SDK初始化 57 | /// @param appID appID 58 | /// @param universalLink 可以为空,根据目前QQ SDK里面提供的初始化方法,`universalLink`是可选的。测试发现`universalLink`为空或者填写不正确,分享会失败 59 | - (void)initWithAppID:(NSString *)appID 60 | universalLink:(nullable NSString *)universalLink; 61 | 62 | /// handleOpenURL 63 | /// @param URL URL 64 | - (void)handleOpenURL:(NSURL *)URL; 65 | 66 | /// handleUniversalLink 67 | /// @param universalLink universalLink 68 | - (void)handleUniversalLink:(NSURL *)universalLink; 69 | 70 | #pragma mark Auth 71 | /// QQ授权 72 | /// @param showHUD 是否显示hUD 73 | /// @param completionBlock 回调(如果isSuccess为YES,代表授权成功,授权信息保存在oauth对象里面) 74 | - (void)authWithShowHUD:(BOOL)showHUD 75 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 76 | 77 | #pragma mark Get User Info 78 | /// QQ获取用户信息 79 | /// @param accessToken accessToken(可通过oauth获得) 80 | /// @param appID appID(可通过oauth获得) 81 | /// @param openId openId(可通过oauth获得) 82 | /// @param showHUD 是否显示HUD 83 | /// @param completionBlock 登录完成回调(信息保存在userInfo里面) 84 | - (void)getUserInfoWithAccessToken:(NSString *)accessToken 85 | appID:(NSString *)appID 86 | openId:(NSString *)openId 87 | isShowHUD:(BOOL)showHUD 88 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 89 | 90 | #pragma mark Share 91 | /// 网页分享(缩略图为URL) 92 | /// @param URL URL 93 | /// @param title 标题 94 | /// @param description 描述 95 | /// @param thumbImageURL 分享的缩略图片链接 96 | /// @param shareTye 分享类型 97 | /// @param shareDestType 分享到哪儿 98 | /// @param showHUD 是否显示HUD 99 | /// @param completionBlock 分享完成回调(是否分享成功) 100 | - (void)shareWebWithURL:(NSString *)URL 101 | title:(NSString *)title 102 | description:(NSString *)description 103 | thumbImageURL:(nullable NSString *)thumbImageURL 104 | shareType:(YHQQShareType)shareTye 105 | shareDestType:(YHQQShareDestType)shareDestType 106 | showHUD:(BOOL)showHUD 107 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 108 | 109 | /// 网页分享(缩略图为NSData) 110 | /// @param URL URL 111 | /// @param title 标题 112 | /// @param description 描述 113 | /// @param thumbImageData 分享的缩略图片NSData(根据QQ SDK,预览图像最大为1M) 114 | /// @param shareTye 分享类型 115 | /// @param shareDestType 分享到哪儿 116 | /// @param showHUD 是否显示HUD 117 | /// @param completionBlock 分享完成回调(是否分享成功) 118 | - (void)shareWebWithURL:(NSString *)URL 119 | title:(NSString *)title 120 | description:(NSString *)description 121 | thumbImageData:(nullable NSData *)thumbImageData 122 | shareType:(YHQQShareType)shareTye 123 | shareDestType:(YHQQShareDestType)shareDestType 124 | showHUD:(BOOL)showHUD 125 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 126 | 127 | /// 图片分享(根据QQ SDK,只能分享到QQ好友) 128 | /// @param imageData 图片数据(根据QQ SDK,预览图像最大为5M) 129 | /// @param thumbImageData 缩略图片NSData(根据QQ SDK,预览图像最大为1M) 130 | /// @param title 标题 131 | /// @param description 描述 132 | /// @param shareDestType 分享到哪儿 133 | /// @param showHUD 是否显示HUD 134 | /// @param completionBlock 分享完成回调(是否分享成功) 135 | - (void)shareImageWithImageData:(NSData *)imageData 136 | thumbImageData:(nullable NSData *)thumbImageData 137 | title:(nullable NSString *)title 138 | description:(nullable NSString *)description 139 | shareDestType:(YHQQShareDestType)shareDestType 140 | showHUD:(BOOL)showHUD 141 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 142 | #endif 143 | @end 144 | 145 | 146 | 147 | 148 | @interface YHQQManager (Private) 149 | - (void)_addObserve; 150 | - (void)_removeObserve; 151 | - (MBProgressHUD *)getHUD; 152 | - (void)_hideHUD:(MBProgressHUD *)hud; 153 | @end 154 | NS_ASSUME_NONNULL_END 155 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/QQ/YHQQManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHQQManager.m 3 | // QAQSmooth 4 | // 5 | // Created by apple on 2019/3/8. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHQQManager.h" 10 | #import "YHThirdDefine.h" 11 | #import "YHThirdHttpRequest.h" 12 | 13 | #if __has_include() 14 | #import 15 | #elif __has_include("MBProgressHUD.h") 16 | #import "MBProgressHUD.h" 17 | #endif 18 | 19 | #define kGetUserInfoAPI @"https://graph.qq.com/user/get_user_info" 20 | 21 | @interface YHQQManager() 22 | #if __has_include() && __has_include() 23 | 24 | #endif 25 | #if __has_include() && __has_include() 26 | @property (nonatomic, copy) NSString *appID; 27 | @property (nonatomic, strong) TencentOAuth *oauth; 28 | @property (nonatomic, strong) YHQQUserInfo *userInfo; 29 | 30 | @property (nonatomic, strong) MBProgressHUD *authHUD; 31 | @property (nonatomic, strong) MBProgressHUD *getUserInfoHUD; 32 | @property (nonatomic, strong) MBProgressHUD *shareHUD; 33 | 34 | @property (nonatomic, copy) void(^authComplectionBlock)(BOOL isSuccess); 35 | @property (nonatomic, copy) void(^shareComplectionBlock)(BOOL isSuccess); 36 | 37 | @property (nonatomic, assign) BOOL sdkFlag; 38 | #endif 39 | @end 40 | 41 | 42 | @implementation YHQQManager 43 | 44 | + (instancetype)sharedInstance{ 45 | static YHQQManager *manager = nil; 46 | static dispatch_once_t onceToken; 47 | dispatch_once(&onceToken, ^{ 48 | manager = [[self alloc] init]; 49 | }); 50 | return manager; 51 | } 52 | 53 | - (instancetype)init 54 | { 55 | self = [super init]; 56 | if (self) { 57 | 58 | } 59 | return self; 60 | } 61 | #if __has_include() && __has_include() 62 | #pragma mark Init 63 | - (void)initWithAppID:(NSString *)appID universalLink:(NSString *)universalLink{ 64 | if (self.oauth) { 65 | self.oauth = nil; 66 | } 67 | if (!appID) { 68 | YHThirdDebugLog(@"[QQ] [初始化] appID为空"); 69 | return; 70 | } 71 | self.appID = appID; 72 | if (universalLink) { 73 | self.oauth = [[TencentOAuth alloc] initWithAppId:appID andUniversalLink:universalLink andDelegate:self]; 74 | } else { 75 | self.oauth = [[TencentOAuth alloc] initWithAppId:appID andDelegate:self]; 76 | } 77 | } 78 | 79 | - (void)handleOpenURL:(NSURL *)URL{ 80 | [TencentOAuth HandleOpenURL:URL]; 81 | [QQApiInterface handleOpenURL:URL delegate:self]; 82 | } 83 | 84 | - (void)handleUniversalLink:(NSURL *)universalLink{ 85 | [TencentOAuth HandleUniversalLink:universalLink]; 86 | [QQApiInterface handleOpenUniversallink:universalLink delegate:self]; 87 | } 88 | 89 | #pragma mark Auth 90 | - (void)authWithShowHUD:(BOOL)showHUD 91 | completionBlock:(void (^)(BOOL))completionBlock{ 92 | dispatch_async(dispatch_get_main_queue(), ^{ 93 | if (!self.appID) { 94 | YHThirdDebugLog(@"[QQ] [授权] appID为空"); 95 | return; 96 | } 97 | self.sdkFlag = NO; 98 | if (showHUD && [QQApiInterface isQQInstalled]) { // 此处做了个判断:只有安装了QQ,才会显示HUD,否则不显示 99 | [self _removeObserve]; 100 | [self _addObserve]; 101 | self.authHUD = [self getHUD]; 102 | } 103 | self.authComplectionBlock = completionBlock; 104 | 105 | NSArray *permissions = @[kOPEN_PERMISSION_GET_INFO, 106 | kOPEN_PERMISSION_GET_USER_INFO, 107 | kOPEN_PERMISSION_GET_SIMPLE_USER_INFO]; 108 | BOOL result = [self.oauth authorize:permissions]; 109 | if (!result) { 110 | YHThirdDebugLog(@"[QQ] [授权] 授权失败"); 111 | if (completionBlock) { 112 | completionBlock(NO); 113 | } 114 | self.authComplectionBlock = nil; 115 | [self _hideHUD:self.authHUD]; 116 | [self _removeObserve]; 117 | } 118 | }); 119 | } 120 | 121 | #pragma mark Get User Info 122 | - (void)getUserInfoWithAccessToken:(NSString *)accessToken 123 | appID:(NSString *)appID 124 | openId:(NSString *)openId 125 | isShowHUD:(BOOL)showHUD 126 | completionBlock:(void (^)(BOOL))completionBlock{ 127 | YHThird_WeakSelf 128 | dispatch_async(dispatch_get_main_queue(), ^{ 129 | NSDictionary *param = @{@"access_token": accessToken ? accessToken : @"", 130 | @"oauth_consumer_key": appID ? appID : @"", 131 | @"openid": openId ? openId : @""}; 132 | YHThirdDebugLog(@"[QQ] [获取个人信息参数] %@", param); 133 | weakSelf.sdkFlag = YES; 134 | if (showHUD) { 135 | weakSelf.getUserInfoHUD = [weakSelf getHUD]; 136 | } 137 | 138 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kGetUserInfoAPI method:YHThirdHttpRequestMethodGET parameter:param successBlock:^(id _Nonnull responseObject) { 139 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 140 | YHThirdDebugLog(@"[QQ] [获取个人信息失败] [数据格式不正确] %@", responseObject); 141 | weakSelf.userInfo = nil; 142 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 143 | dispatch_async(dispatch_get_main_queue(), ^{ 144 | if (completionBlock) { 145 | completionBlock(NO); 146 | } 147 | }); 148 | return ; 149 | } 150 | 151 | YHThirdDebugLog(@"[QQ] [获取个人信息成功] %@", responseObject); 152 | 153 | NSDictionary *infoDic = (NSDictionary *)responseObject; 154 | 155 | YHQQUserInfo *result = [[YHQQUserInfo alloc] init]; 156 | 157 | result.originInfo = infoDic; 158 | 159 | if ([infoDic.allKeys containsObject:@"nickname"]) { 160 | result.nickName = [NSString stringWithFormat:@"%@", infoDic[@"nickname"]]; 161 | } 162 | if ([infoDic.allKeys containsObject:@"gender"]) { 163 | NSString *sex = [NSString stringWithFormat:@"%@", infoDic[@"gender"]]; 164 | if ([sex isEqualToString:@"男"]) { 165 | result.sex = 1; 166 | } else if ([sex isEqualToString:@"女"]) { 167 | result.sex = 2; 168 | } else { 169 | result.sex = 0; 170 | } 171 | } 172 | if ([infoDic.allKeys containsObject:@"province"]) { 173 | result.province = [NSString stringWithFormat:@"%@", infoDic[@"province"]]; 174 | } 175 | if ([infoDic.allKeys containsObject:@"city"]) { 176 | result.city = [NSString stringWithFormat:@"%@", infoDic[@"city"]]; 177 | } 178 | 179 | // 依次取头像,保证一定有头像返回 180 | if ([infoDic.allKeys containsObject:@"figureurl_qq"]) { 181 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl_qq"]]; 182 | } else if ([infoDic.allKeys containsObject:@"figureurl_qq_2"]) { 183 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl_qq_2"]]; 184 | } else if ([infoDic.allKeys containsObject:@"figureurl_2"]) { 185 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl_2"]]; 186 | } else if ([infoDic.allKeys containsObject:@"figureurl_1"]) { 187 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl_1"]]; 188 | } else if ([infoDic.allKeys containsObject:@"figureurl"]) { 189 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl"]]; 190 | } else if ([infoDic.allKeys containsObject:@"figureurl_qq_1"]) { 191 | result.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"figureurl_qq_1"]]; 192 | } 193 | weakSelf.userInfo = result; 194 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 195 | dispatch_async(dispatch_get_main_queue(), ^{ 196 | if (completionBlock) { 197 | completionBlock(YES); 198 | } 199 | }); 200 | } failureBlock:^(NSError * _Nonnull error) { 201 | YHThirdDebugLog(@"[QQ] [获取个人信息失败] %@", error); 202 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 203 | weakSelf.userInfo = nil; 204 | dispatch_async(dispatch_get_main_queue(), ^{ 205 | if (completionBlock) { 206 | completionBlock(NO); 207 | } 208 | }); 209 | }]; 210 | }); 211 | } 212 | 213 | 214 | #pragma mark Share 215 | - (void)shareWebWithURL:(NSString *)URL 216 | title:(NSString *)title 217 | description:(NSString *)description 218 | thumbImageURL:(NSString *)thumbImageURL 219 | shareType:(YHQQShareType)shareTye 220 | shareDestType:(YHQQShareDestType)shareDestType 221 | showHUD:(BOOL)showHUD 222 | completionBlock:(void (^)(BOOL))completionBlock{ 223 | dispatch_async(dispatch_get_main_queue(), ^{ 224 | if (!self.appID) { 225 | YHThirdDebugLog(@"[QQ] [分享] appID为空"); 226 | return; 227 | } 228 | self.sdkFlag = NO; 229 | if (showHUD && [QQApiInterface isQQInstalled]) { 230 | [self _removeObserve]; 231 | [self _addObserve]; 232 | self.shareHUD = [self getHUD]; 233 | } 234 | self.shareComplectionBlock = completionBlock; 235 | 236 | QQApiNewsObject *object = [QQApiNewsObject objectWithURL:[NSURL URLWithString:URL] title:title description:description previewImageURL:[NSURL URLWithString:thumbImageURL]]; 237 | 238 | ShareDestType destType = ShareDestTypeQQ; 239 | if (shareDestType == YHQQShareDestType_QQ) { 240 | destType = ShareDestTypeQQ; 241 | } else if (shareDestType == YHQQShareDestType_TIM) { 242 | destType = ShareDestTypeTIM; 243 | } 244 | object.shareDestType = destType; 245 | 246 | SendMessageToQQReq *rq = [SendMessageToQQReq reqWithContent:object]; 247 | 248 | QQApiSendResultCode sendResultCode = EQQAPISENDFAILD; 249 | if (shareTye == YHQQShareType_QQ) { 250 | sendResultCode = [QQApiInterface sendReq:rq]; 251 | } else if (shareTye == YHQQShareType_QZone) { 252 | sendResultCode = [QQApiInterface SendReqToQZone:rq]; 253 | } 254 | YHThirdDebugLog(@"[QQ] [分享] [QQApiSendResultCode] %d", (int)sendResultCode); 255 | if (sendResultCode != EQQAPISENDSUCESS) { 256 | if (completionBlock) { 257 | completionBlock(NO); 258 | } 259 | self.shareComplectionBlock = nil; 260 | [self _hideHUD:self.shareHUD]; 261 | [self _removeObserve]; 262 | } 263 | }); 264 | } 265 | 266 | - (void)shareWebWithURL:(NSString *)URL 267 | title:(NSString *)title 268 | description:(NSString *)description 269 | thumbImageData:(NSData *)thumbImageData 270 | shareType:(YHQQShareType)shareTye 271 | shareDestType:(YHQQShareDestType)shareDestType 272 | showHUD:(BOOL)showHUD 273 | completionBlock:(void (^)(BOOL))completionBlock{ 274 | dispatch_async(dispatch_get_main_queue(), ^{ 275 | if (!self.appID) { 276 | YHThirdDebugLog(@"[QQ] [分享] appID为空"); 277 | return; 278 | } 279 | self.sdkFlag = NO; 280 | if (showHUD && [QQApiInterface isQQInstalled]) { 281 | [self _removeObserve]; 282 | [self _addObserve]; 283 | self.shareHUD = [self getHUD]; 284 | } 285 | self.shareComplectionBlock = completionBlock; 286 | 287 | QQApiNewsObject *object = [QQApiNewsObject objectWithURL:[NSURL URLWithString:URL] title:title description:description previewImageData:thumbImageData]; 288 | 289 | ShareDestType destType = ShareDestTypeQQ; 290 | if (shareDestType == YHQQShareDestType_QQ) { 291 | destType = ShareDestTypeQQ; 292 | } else if (shareDestType == YHQQShareDestType_TIM) { 293 | destType = ShareDestTypeTIM; 294 | } 295 | object.shareDestType = destType; 296 | 297 | SendMessageToQQReq *rq = [SendMessageToQQReq reqWithContent:object]; 298 | 299 | QQApiSendResultCode sendResultCode = EQQAPISENDFAILD; 300 | if (shareTye == YHQQShareType_QQ) { 301 | sendResultCode = [QQApiInterface sendReq:rq]; 302 | } else if (shareTye == YHQQShareType_QZone) { 303 | sendResultCode = [QQApiInterface SendReqToQZone:rq]; 304 | } 305 | YHThirdDebugLog(@"[QQ] [分享] [QQApiSendResultCode] %d", (int)sendResultCode); 306 | if (sendResultCode != EQQAPISENDSUCESS) { 307 | if (completionBlock) { 308 | completionBlock(NO); 309 | } 310 | self.shareComplectionBlock = nil; 311 | [self _hideHUD:self.shareHUD]; 312 | [self _removeObserve]; 313 | } 314 | }); 315 | } 316 | 317 | - (void)shareImageWithImageData:(NSData *)imageData 318 | thumbImageData:(NSData *)thumbImageData 319 | title:(NSString *)title 320 | description:(NSString *)description 321 | shareDestType:(YHQQShareDestType)shareDestType 322 | showHUD:(BOOL)showHUD 323 | completionBlock:(void (^)(BOOL))completionBlock{ 324 | dispatch_async(dispatch_get_main_queue(), ^{ 325 | if (!self.appID) { 326 | YHThirdDebugLog(@"[QQ] [分享] appID为空"); 327 | return; 328 | } 329 | self.sdkFlag = NO; 330 | if (showHUD && [QQApiInterface isQQInstalled]) { 331 | [self _removeObserve]; 332 | [self _addObserve]; 333 | self.shareHUD = [self getHUD]; 334 | } 335 | self.shareComplectionBlock = completionBlock; 336 | 337 | QQApiImageObject *imageObject = [QQApiImageObject objectWithData:imageData previewImageData:thumbImageData title:title description:description]; 338 | 339 | ShareDestType destType = ShareDestTypeQQ; 340 | if (shareDestType == YHQQShareDestType_QQ) { 341 | destType = ShareDestTypeQQ; 342 | } else if (shareDestType == YHQQShareDestType_TIM) { 343 | destType = ShareDestTypeTIM; 344 | } 345 | imageObject.shareDestType = destType; 346 | 347 | SendMessageToQQReq *rq = [SendMessageToQQReq reqWithContent:imageObject]; 348 | 349 | QQApiSendResultCode sendResultCode = [QQApiInterface sendReq:rq]; 350 | YHThirdDebugLog(@"[QQ] [分享] [QQApiSendResultCode] %d", (int)sendResultCode); 351 | if (sendResultCode != EQQAPISENDSUCESS) { 352 | if (completionBlock) { 353 | completionBlock(NO); 354 | } 355 | self.shareComplectionBlock = nil; 356 | [self _hideHUD:self.shareHUD]; 357 | [self _removeObserve]; 358 | } 359 | }); 360 | } 361 | 362 | #pragma mark 363 | // 登录成功后的回调. 364 | - (void)tencentDidLogin { 365 | YHThirdDebugLog(@"[QQ] [授权] [TencentLoginDelegate] tencentDidLogin"); 366 | if (self.authComplectionBlock) { 367 | self.authComplectionBlock(YES); 368 | } 369 | self.authComplectionBlock = nil; 370 | [self _hideHUD:self.authHUD]; 371 | [self _removeObserve]; 372 | } 373 | 374 | // 授权失败后的回调. 375 | - (void)tencentDidNotLogin:(BOOL)cancelled { 376 | YHThirdDebugLog(@"[QQ] [授权] [TencentLoginDelegate] tencentDidNotLogin"); 377 | if (self.authComplectionBlock) { 378 | self.authComplectionBlock(NO); 379 | } 380 | self.authComplectionBlock = nil; 381 | [self _hideHUD:self.authHUD]; 382 | [self _removeObserve]; 383 | } 384 | 385 | // 授权时网络有问题的回调. 386 | - (void)tencentDidNotNetWork { 387 | YHThirdDebugLog(@"[QQ] [授权] [TencentLoginDelegate] tencentDidNotNetWork"); 388 | if (self.authComplectionBlock) { 389 | self.authComplectionBlock(NO); 390 | } 391 | self.authComplectionBlock = nil; 392 | [self _hideHUD:self.authHUD]; 393 | [self _removeObserve]; 394 | } 395 | 396 | - (void)didGetUnionID{ 397 | YHThirdDebugLog(@"[QQ] [didGetUnionID] %@", self.oauth.unionid); 398 | } 399 | 400 | #pragma mark 401 | // 处理来至QQ的请求. 402 | - (void)onReq:(QQBaseReq *)req{ 403 | YHThirdDebugLog(@"[QQ] [QQApiInterfaceDelegate] [onReq] %@ [type] %d", req, req.type); 404 | } 405 | 406 | // 处理来至QQ的响应. 407 | - (void)onResp:(QQBaseResp *)resp{ 408 | YHThirdDebugLog(@"[QQ] [QQApiInterfaceDelegate] [onResp] %@", resp); 409 | if ([resp isKindOfClass:[SendMessageToQQResp class]]) { 410 | SendMessageToQQResp *response = (SendMessageToQQResp *)resp; 411 | YHThirdDebugLog(@"[QQ] [分享] [QQApiInterfaceDelegate] [onResp] [SendMessageToQQResp] [result] %@", response.result); 412 | if ([response.result isEqualToString:@"0"]) { 413 | if (self.shareComplectionBlock) { 414 | self.shareComplectionBlock(YES); 415 | } 416 | self.shareComplectionBlock = nil; 417 | [self _hideHUD:self.shareHUD]; 418 | [self _removeObserve]; 419 | } else { 420 | if (self.shareComplectionBlock) { 421 | self.shareComplectionBlock(NO); 422 | } 423 | self.shareComplectionBlock = nil; 424 | [self _hideHUD:self.shareHUD]; 425 | [self _removeObserve]; 426 | } 427 | } 428 | } 429 | 430 | // 处理QQ在线状态的回调. 431 | - (void)isOnlineResponse:(NSDictionary *)response{ 432 | YHThirdDebugLog(@"[QQ] [QQApiInterfaceDelegate] [isOnlineResponse] %@", response); 433 | } 434 | 435 | #pragma mark Notification 436 | - (void)applicationWillEnterForeground:(NSNotification *)noti{ 437 | YHThirdDebugLog(@"applicationWillEnterForeground"); 438 | [self _hideHUD:self.authHUD]; 439 | [self _hideHUD:self.shareHUD]; 440 | } 441 | 442 | - (void)applicationDidEnterBackground:(NSNotification *)noti{ 443 | YHThirdDebugLog(@"applicationDidEnterBackground"); 444 | } 445 | 446 | - (void)applicationDidBecomeActive:(NSNotification *)noti{ 447 | YHThirdDebugLog(@"applicationDidBecomeActive"); 448 | // 经过不断测试发现:当代理tencentDidLogin回调之后,有时仍然会走该通知回调。因此定义了一个flag,当tencentDidLogin回调之后,设置该flag为YES,否则HUD会提前关闭 449 | if (self.sdkFlag) { 450 | return; 451 | } 452 | [self _hideHUD:self.authHUD]; 453 | [self _hideHUD:self.shareHUD]; 454 | } 455 | #endif 456 | @end 457 | 458 | 459 | 460 | @implementation YHQQManager (Private) 461 | // 添加观察者 462 | - (void)_addObserve{ 463 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 464 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; 465 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; 466 | } 467 | 468 | // 移除观察者 469 | - (void)_removeObserve{ 470 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 471 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 472 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; 473 | } 474 | 475 | // 显示HUD 476 | - (MBProgressHUD *)getHUD{ 477 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES];//必须在主线程,源码规定 478 | hud.mode = MBProgressHUDModeIndeterminate; 479 | hud.contentColor = [UIColor whiteColor]; 480 | hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; 481 | hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.7]; 482 | hud.removeFromSuperViewOnHide = YES; 483 | return hud; 484 | } 485 | 486 | // 隐藏HUD 487 | - (void)_hideHUD:(MBProgressHUD *)hud{ 488 | if (!hud) { return; } 489 | dispatch_async(dispatch_get_main_queue(), ^{ 490 | [hud hideAnimated:YES]; 491 | }); 492 | } 493 | @end 494 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/QQ/YHQQUserInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHQQUserInfo.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// QQ登录,获取到的个人信息模型 14 | @interface YHQQUserInfo : NSObject 15 | // 昵称 16 | @property (nonatomic, copy, nullable) NSString *nickName; 17 | // 性别 0:未知 1:男 2:女 18 | @property (nonatomic, assign) int sex; 19 | // 省份 20 | @property (nonatomic, copy, nullable) NSString *province; 21 | // 城市 22 | @property (nonatomic, copy, nullable) NSString *city; 23 | // 头像 24 | @property (nonatomic, copy, nullable) NSString *headImgURL; 25 | // 原始数据(如果以上信息不能满足开发要求,则可以用此属性) 26 | @property (nonatomic, strong, nullable) NSDictionary *originInfo; 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/QQ/YHQQUserInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHQQUserInfo.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHQQUserInfo.h" 10 | 11 | @implementation YHQQUserInfo 12 | - (instancetype)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | self.nickName = @""; 17 | self.sex = 0; 18 | self.province = @""; 19 | self.city = @""; 20 | self.headImgURL = @""; 21 | self.originInfo = nil; 22 | } 23 | return self; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Sina/YHSinaManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHSinaManager.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #if __has_include() 12 | #import 13 | #endif 14 | #import "YHSinaUserInfo.h" 15 | 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | /** 20 | * SDK版本:3.2.5.1 21 | * 新浪登录、分享功能的封装 22 | * SDK下载下载地址:https://github.com/sinaweibosdk/weibo_ios_sdk 23 | * 微博开放平台文档:https://open.weibo.com/wiki/%E9%A6%96%E9%A1%B5 24 | * 跳转到指定微博:sinaweibo://detail/?dispMeIfNeed=1&mblogid= 25 | * 调起微博直接到指定的个人页面:sinaweibo://userinfo?uid=xxxx 26 | */ 27 | @class MBProgressHUD; 28 | @interface YHSinaManager : NSObject 29 | #if __has_include() 30 | /// 初始化SDK的appID 31 | @property (nonatomic, copy, readonly) NSString *appID; 32 | /// 初始化SDK的redirectURI 33 | @property (nonatomic, copy, readonly) NSString *redirectURI; 34 | /// 授权成功后的信息保存在此对象里面,需要什么信息自己去拿 35 | @property (nonatomic, strong, readonly, nullable) WBAuthorizeResponse *authorizeResponse; 36 | /// 微博登录获取的个人信息 37 | @property (nonatomic, strong, readonly, nullable) YHSinaUserInfo *userInfo; 38 | 39 | #endif 40 | 41 | + (instancetype)sharedInstance; 42 | + (instancetype)new NS_UNAVAILABLE; 43 | - (instancetype)init NS_UNAVAILABLE; 44 | 45 | #if __has_include() 46 | #pragma mark Init 47 | /// SDK初始化 48 | /// @param appID appID 49 | /// @param redirectURI redirectURI 50 | - (void)initWithAppID:(NSString *)appID 51 | redirectURI:(NSString *)redirectURI; 52 | 53 | /// handleOpenURL 54 | /// @param URL URL 55 | - (void)handleOpenURL:(NSURL *)URL; 56 | 57 | 58 | #pragma mark Auth 59 | /// 微博授权(授权成功后,信息保存在authorizeResponse里面) 60 | /// @param showHUD 是否显示HUD 61 | /// @param completionBlock 回调 62 | - (void)authWithShowHUD:(BOOL)showHUD 63 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 64 | 65 | #pragma mark Share(分享这儿还需要再次处理下) 66 | /// 微博分享(目前只支持分享单图,多图分享SDK有问题) 67 | /// @param title 标题 68 | /// @param url 链接 69 | /// @param description 描述 70 | /// @param thumbImageData 缩略图(必须配置,url才有效,才能点击;不能太大,不然分享不出去,根据SDK,不能超过32k) 71 | /// @param showHUD 是否显示HUD 72 | /// @param completionBlock 回调 73 | - (void)shareWithTitle:(NSString *)title 74 | url:(NSString *)url 75 | description:(nullable NSString *)description 76 | thumbImageData:(nullable NSData *)thumbImageData 77 | showHUD:(BOOL)showHUD 78 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 79 | #endif 80 | 81 | #pragma mark Get User Info 82 | /// 获取用户信息 83 | /// @param accessToken accessToken 84 | /// @param userID userID 85 | /// @param showHUD 是否显示HUD 86 | /// @param completionBlock 回调 87 | - (void)getUserInfoWithAccessToken:(NSString *)accessToken 88 | userID:(NSString *)userID 89 | showHUD:(BOOL)showHUD 90 | completionBlock:(void(^_Nullable)(void))completionBlock; 91 | 92 | #pragma mark Comment WeiBo 93 | /// 评论指定微博(通过API的方式评论指定微博) 94 | /// @param accessToken accessToken 95 | /// @param ID 微博ID 96 | /// @param comment 评论的内容 97 | /// @param isCommentOriginWhenTransfer 当评论转发微博时,是否评论给原微博 98 | /// @param showHUD 是否显示HUD 99 | /// @param completionBlock 回调 100 | - (void)commentWeiBoWithAccessToken:(NSString *)accessToken 101 | ID:(NSString *)ID 102 | comment:(NSString *)comment 103 | isCommentOriginWhenTransfer:(BOOL)isCommentOriginWhenTransfer 104 | showHUD:(BOOL)showHUD completionBlock:(void(^_Nullable)(NSDictionary *_Nullable responseObject))completionBlock; 105 | 106 | /// 评论指定微博(通过scheme的方式评论指定微博,可以打开微博的评论面板,评论完成后,不能自动返回APP) 107 | /// 微博SDK的方法 commentToWeibo: 方法不能往输入框里面添加默认的内容,仅仅只是拉起微博 108 | /// @param ID 微博ID 109 | /// @param comment 评论的内容 110 | - (void)commentWeiBoWithID:(NSString *)ID 111 | comment:(nullable NSString *)comment; 112 | 113 | #pragma mark Get Wy WebiBo 114 | /// 获取我自己发布的微博 115 | /// @param accessToken accessToken 116 | /// @param userID userID 117 | /// @param perCount 单页返回的条数 118 | /// @param curPage 页数 119 | /// @param showHUD 是否显示HUD 120 | /// @param completionBlock 回调的原始数据 121 | - (void)getMineWeoBoListWithAccessToken:(NSString *)accessToken 122 | userID:(NSString *)userID 123 | perCount:(int)perCount 124 | curPage:(int)curPage 125 | showHUD:(BOOL)showHUD 126 | completionBlock:(void(^_Nullable)(NSDictionary *_Nullable responseObject))completionBlock; 127 | @end 128 | 129 | 130 | @interface YHSinaManager (Private) 131 | - (void)_addObserve; 132 | - (void)_removeObserve; 133 | - (MBProgressHUD *)getHUD; 134 | - (void)_hideHUD:(MBProgressHUD *)hud; 135 | @end 136 | 137 | NS_ASSUME_NONNULL_END 138 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Sina/YHSinaManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHSinaManager.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHSinaManager.h" 10 | 11 | #if __has_include() 12 | #import 13 | #elif __has_include("MBProgressHUD.h") 14 | #import "MBProgressHUD.h" 15 | #endif 16 | 17 | #import "YHThirdDefine.h" 18 | #import "YHThirdHttpRequest.h" 19 | 20 | #define kGetUserInfoAPI @"https://api.weibo.com/2/users/show.json" 21 | #define kCommentWeiBoAPI @"https://api.weibo.com/2/comments/create.json" 22 | #define kMineWeiBoListAPI @"https://api.weibo.com/2/statuses/user_timeline.json" 23 | 24 | 25 | @interface YHSinaManager () 26 | #if __has_include() 27 | 28 | #endif 29 | 30 | #if __has_include() 31 | @property (nonatomic, copy) NSString *appID; 32 | @property (nonatomic, copy) NSString *redirectURI; 33 | @property (nonatomic, strong) WBAuthorizeResponse *authorizeResponse; 34 | @property (nonatomic, strong) YHSinaUserInfo *userInfo; 35 | #endif 36 | 37 | @property (nonatomic, strong) MBProgressHUD *authHUD; 38 | @property (nonatomic, strong) MBProgressHUD *getUserInfoHUD; 39 | @property (nonatomic, strong) MBProgressHUD *shareWebHUD; 40 | @property (nonatomic, strong) MBProgressHUD *commentWeiBoHUD; 41 | @property (nonatomic, strong) MBProgressHUD *mineWeiBoListHUD; 42 | 43 | @property (nonatomic, copy) void(^authCompletionBlock)(BOOL); 44 | @property (nonatomic, copy) void(^shareWebCompletionBlock)(BOOL isSuccess); 45 | 46 | @property (nonatomic, assign) BOOL sdkFlag; 47 | 48 | @end 49 | 50 | @implementation YHSinaManager 51 | 52 | + (instancetype)sharedInstance{ 53 | static YHSinaManager *manager = nil; 54 | static dispatch_once_t onceToken; 55 | dispatch_once(&onceToken, ^{ 56 | manager = [[self alloc] init]; 57 | }); 58 | return manager; 59 | } 60 | 61 | - (instancetype)init 62 | { 63 | self = [super init]; 64 | if (self) { 65 | 66 | } 67 | return self; 68 | } 69 | 70 | #if __has_include() 71 | #pragma mark Init 72 | - (void)initWithAppID:(NSString *)appID 73 | redirectURI:(NSString *)redirectURI{ 74 | if (!appID) { 75 | YHThirdDebugLog(@"[Sina] [初始化] appID为空"); 76 | return; 77 | } 78 | if (!redirectURI) { 79 | YHThirdDebugLog(@"[Sina] [初始化] redirectURI为空"); 80 | return; 81 | } 82 | self.appID = appID; 83 | self.redirectURI = redirectURI; 84 | [WeiboSDK registerApp:appID]; 85 | } 86 | 87 | - (void)handleOpenURL:(NSURL *)URL{ 88 | [WeiboSDK handleOpenURL:URL delegate:self]; 89 | } 90 | 91 | #pragma mark Auth 92 | - (void)authWithShowHUD:(BOOL)showHUD 93 | completionBlock:(void (^)(BOOL))completionBlock{ 94 | dispatch_async(dispatch_get_main_queue(), ^{ 95 | if (!self.appID) { 96 | YHThirdDebugLog(@"[Sina] [授权] appID为空"); 97 | return; 98 | } 99 | if (!self.redirectURI) { 100 | YHThirdDebugLog(@"[Sina] [授权] redirectURI为空"); 101 | return; 102 | } 103 | self.sdkFlag = NO; 104 | if (showHUD && [WeiboSDK isWeiboAppInstalled]) { 105 | [self _removeObserve]; 106 | [self _addObserve]; 107 | self.authHUD = [self getHUD]; 108 | } 109 | self.authCompletionBlock = completionBlock; 110 | 111 | WBAuthorizeRequest *authorizeRequest = [[WBAuthorizeRequest alloc] init]; 112 | authorizeRequest.redirectURI = self.redirectURI; 113 | authorizeRequest.shouldShowWebViewForAuthIfCannotSSO = YES; 114 | authorizeRequest.scope = @"all"; 115 | 116 | BOOL result = [WeiboSDK sendRequest:authorizeRequest]; 117 | if (!result) { 118 | self.authorizeResponse = nil; 119 | dispatch_async(dispatch_get_main_queue(), ^{ 120 | if (completionBlock) { 121 | completionBlock(NO); 122 | } 123 | self.authCompletionBlock = nil; 124 | }); 125 | [self _hideHUD:self.authHUD]; 126 | [self _removeObserve]; 127 | } 128 | }); 129 | } 130 | 131 | #pragma mark Share(分享这儿还需要再次处理下) 132 | - (void)shareWithTitle:(NSString *)title 133 | url:(NSString *)url 134 | description:(NSString *)description 135 | thumbImageData:(NSData *)thumbImageData 136 | showHUD:(BOOL)showHUD 137 | completionBlock:(void (^)(BOOL))completionBlock{ 138 | dispatch_async(dispatch_get_main_queue(), ^{ 139 | if (!self.redirectURI) { 140 | YHThirdDebugLog(@"[Sina] [分享] redirectURI为空"); 141 | return; 142 | } 143 | if (showHUD && [WeiboSDK isWeiboAppInstalled]) { 144 | [self _removeObserve]; 145 | [self _addObserve]; 146 | self.shareWebHUD = [self getHUD]; 147 | } 148 | self.sdkFlag = NO; 149 | self.shareWebCompletionBlock = completionBlock; 150 | 151 | WBWebpageObject *webpageObject = [WBWebpageObject object]; 152 | webpageObject.webpageUrl = url; 153 | webpageObject.title = title; 154 | webpageObject.description = description; 155 | webpageObject.thumbnailData = thumbImageData; 156 | webpageObject.objectID = [NSUUID UUID].UUIDString; 157 | 158 | WBMessageObject *messageObject = [[WBMessageObject alloc] init]; 159 | messageObject.text = description; 160 | messageObject.mediaObject = webpageObject; 161 | 162 | WBAuthorizeRequest *authorizeRequest = [WBAuthorizeRequest request]; 163 | authorizeRequest.scope = @"all"; 164 | authorizeRequest.redirectURI = self.redirectURI; 165 | 166 | WBSendMessageToWeiboRequest *request = [WBSendMessageToWeiboRequest requestWithMessage:messageObject authInfo:authorizeRequest access_token:nil]; 167 | 168 | BOOL result = [WeiboSDK sendRequest:request]; 169 | if (!result) { 170 | if (completionBlock) { 171 | completionBlock(NO); 172 | } 173 | self.shareWebCompletionBlock = nil; 174 | [self _hideHUD:self.shareWebHUD]; 175 | } 176 | }); 177 | } 178 | 179 | #endif 180 | 181 | #pragma mark Get User Info 182 | - (void)getUserInfoWithAccessToken:(NSString *)accessToken 183 | userID:(NSString *)userID 184 | showHUD:(BOOL)showHUD 185 | completionBlock:(void (^)(void))completionBlock{ 186 | YHThird_WeakSelf 187 | dispatch_async(dispatch_get_main_queue(), ^{ 188 | weakSelf.sdkFlag = YES; 189 | if (showHUD) { 190 | weakSelf.getUserInfoHUD = [weakSelf getHUD]; 191 | } 192 | 193 | NSDictionary *param = @{@"access_token": accessToken, 194 | @"uid": userID}; 195 | YHThirdDebugLog(@"[Sina] [获取个人信息参数] %@", param); 196 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kGetUserInfoAPI method:YHThirdHttpRequestMethodGET parameter:param successBlock:^(id _Nonnull responseObject) { 197 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 198 | YHThirdDebugLog(@"[Sina] [获取个人信息失败] [数据格式不正确] %@", responseObject); 199 | weakSelf.userInfo = nil; 200 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 201 | dispatch_async(dispatch_get_main_queue(), ^{ 202 | if (completionBlock) { 203 | completionBlock(); 204 | } 205 | }); 206 | return ; 207 | } 208 | 209 | YHThirdDebugLog(@"[Sina] [获取个人信息成功] %@", responseObject); 210 | 211 | NSDictionary *infoDic = (NSDictionary *)responseObject; 212 | 213 | YHSinaUserInfo *userInfo = [[YHSinaUserInfo alloc] init]; 214 | 215 | userInfo.originInfo = responseObject; 216 | 217 | if ([infoDic.allKeys containsObject:@"screen_name"]) { 218 | userInfo.nickName = [NSString stringWithFormat:@"%@", infoDic[@"screen_name"]]; 219 | } 220 | if ([infoDic.allKeys containsObject:@"gender"]) { 221 | NSString *gender = [NSString stringWithFormat:@"%@", infoDic[@"gender"]]; 222 | if ([gender isEqualToString:@"m"]) { 223 | userInfo.sex = 1; 224 | } else if ([gender isEqualToString:@"f"]) { 225 | userInfo.sex = 2; 226 | } else { 227 | userInfo.sex = 0; 228 | } 229 | } 230 | if ([infoDic.allKeys containsObject:@"province"]) { 231 | userInfo.province = [NSString stringWithFormat:@"%@", infoDic[@"province"]]; 232 | } 233 | if ([infoDic.allKeys containsObject:@"city"]) { 234 | userInfo.city = [NSString stringWithFormat:@"%@", infoDic[@"city"]]; 235 | } 236 | if ([infoDic.allKeys containsObject:@"avatar_large"]) { 237 | userInfo.headImgURL = [NSString stringWithFormat:@"%@", infoDic[@"avatar_large"]]; 238 | } 239 | weakSelf.userInfo = userInfo; 240 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 241 | dispatch_async(dispatch_get_main_queue(), ^{ 242 | if (completionBlock) { 243 | completionBlock(); 244 | } 245 | }); 246 | 247 | } failureBlock:^(NSError * _Nonnull error) { 248 | YHThirdDebugLog(@"[Sina] [获取个人信息失败] %@", error); 249 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 250 | weakSelf.userInfo = nil; 251 | dispatch_async(dispatch_get_main_queue(), ^{ 252 | if (completionBlock) { 253 | completionBlock(); 254 | } 255 | }); 256 | }]; 257 | }); 258 | } 259 | 260 | #pragma mark Comment WeiBo 261 | - (void)commentWeiBoWithAccessToken:(NSString *)accessToken 262 | ID:(NSString *)ID 263 | comment:(NSString *)comment 264 | isCommentOriginWhenTransfer:(BOOL)isCommentOriginWhenTransfer 265 | showHUD:(BOOL)showHUD 266 | completionBlock:(void (^)(NSDictionary * _Nullable))completionBlock{ 267 | YHThird_WeakSelf 268 | dispatch_async(dispatch_get_main_queue(), ^{ 269 | weakSelf.sdkFlag = YES; 270 | if (showHUD) { 271 | weakSelf.commentWeiBoHUD = [weakSelf getHUD]; 272 | } 273 | NSDictionary *param = @{@"access_token" : accessToken ? accessToken : @"", 274 | @"comment" : comment ? comment : @"", 275 | @"id" : ID ? ID : @"", 276 | @"comment_ori" : isCommentOriginWhenTransfer ? @"1" : @"0"}; 277 | YHThirdDebugLog(@"[Sina] [评论指定微博参数] %@", param); 278 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kCommentWeiBoAPI method:YHThirdHttpRequestMethodPOST parameter:param successBlock:^(id _Nonnull responseObject) { 279 | [weakSelf _hideHUD:weakSelf.commentWeiBoHUD]; 280 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 281 | YHThirdDebugLog(@"[Sina] [评论指定微博失败] 数据格式错误 %@", responseObject); 282 | dispatch_async(dispatch_get_main_queue(), ^{ 283 | if (completionBlock) { 284 | completionBlock(nil); 285 | } 286 | }); 287 | return ; 288 | } 289 | dispatch_async(dispatch_get_main_queue(), ^{ 290 | if (completionBlock) { 291 | completionBlock(responseObject); 292 | } 293 | }); 294 | } failureBlock:^(NSError * _Nonnull error) { 295 | YHThirdDebugLog(@"[Sina] [评论指定微博失败] %@", error); 296 | [weakSelf _hideHUD:weakSelf.commentWeiBoHUD]; 297 | dispatch_async(dispatch_get_main_queue(), ^{ 298 | if (completionBlock) { 299 | completionBlock(nil); 300 | } 301 | }); 302 | }]; 303 | }); 304 | } 305 | 306 | 307 | - (void)commentWeiBoWithID:(NSString *)ID 308 | comment:(NSString *)comment{ 309 | NSString *url = @""; 310 | if (!comment || comment.length == 0 || [comment isEqualToString:@""]) { 311 | url = [NSString stringWithFormat:@"sinaweibo://comment?srcid=%@", ID]; 312 | } else { 313 | url = [NSString stringWithFormat:@"sinaweibo://comment?srcid=%@&content=%@", ID, comment]; 314 | } 315 | NSURL *URL = [NSURL URLWithString:[[YHThirdHttpRequest sharedInstance] urlTranscoding:url]]; 316 | dispatch_async(dispatch_get_main_queue(), ^{ 317 | if ([[UIApplication sharedApplication] canOpenURL:URL]) { 318 | if (@available(iOS 10.0, *)) { 319 | [[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil]; 320 | } else { 321 | [[UIApplication sharedApplication] openURL:URL]; 322 | } 323 | } else { 324 | YHThirdDebugLog(@"[Sina] [评论指定微博] [用户没有安装微博客户端]"); 325 | } 326 | }); 327 | } 328 | 329 | #pragma mark Get Wy WebiBo 330 | - (void)getMineWeoBoListWithAccessToken:(NSString *)accessToken 331 | userID:(NSString *)userID 332 | perCount:(int)perCount 333 | curPage:(int)curPage 334 | showHUD:(BOOL)showHUD 335 | completionBlock:(void (^)(NSDictionary * _Nullable))completionBlock{ 336 | YHThird_WeakSelf 337 | dispatch_async(dispatch_get_main_queue(), ^{ 338 | weakSelf.sdkFlag = YES; 339 | if (showHUD) { 340 | weakSelf.mineWeiBoListHUD = [weakSelf getHUD]; 341 | } 342 | 343 | NSDictionary *param = @{@"access_token" : accessToken, 344 | @"uid" : userID, 345 | @"count" : [NSString stringWithFormat:@"%d", perCount], 346 | @"page" : [NSString stringWithFormat:@"%d", curPage]}; 347 | YHThirdDebugLog(@"[Sina] [获取我的微博参数] %@", param); 348 | 349 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kMineWeiBoListAPI method:YHThirdHttpRequestMethodGET parameter:param successBlock:^(id _Nonnull responseObject) { 350 | [weakSelf _hideHUD:weakSelf.mineWeiBoListHUD]; 351 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 352 | YHThirdDebugLog(@"[Sina] [获取我的微博失败] [数据格式不正确] %@", responseObject); 353 | dispatch_async(dispatch_get_main_queue(), ^{ 354 | if (completionBlock) { 355 | completionBlock(nil); 356 | } 357 | }); 358 | return ; 359 | } 360 | YHThirdDebugLog(@"[Sina] [获取我的微博成功] %@", responseObject); 361 | dispatch_async(dispatch_get_main_queue(), ^{ 362 | if (completionBlock) { 363 | completionBlock(responseObject); 364 | } 365 | }); 366 | 367 | } failureBlock:^(NSError * _Nonnull error) { 368 | YHThirdDebugLog(@"[Sina] [获取我的微博失败] %@", error); 369 | [weakSelf _hideHUD:weakSelf.mineWeiBoListHUD]; 370 | dispatch_async(dispatch_get_main_queue(), ^{ 371 | if (completionBlock) { 372 | completionBlock(nil); 373 | } 374 | }); 375 | }]; 376 | }); 377 | } 378 | 379 | 380 | #pragma mark ------------------ Notification ------------------ 381 | - (void)applicationWillEnterForeground:(NSNotification *)noti{ 382 | YHThirdDebugLog(@"[Sina] applicationWillEnterForeground"); 383 | [self _hideHUD:self.authHUD]; 384 | [self _hideHUD:self.shareWebHUD]; 385 | } 386 | 387 | - (void)applicationDidEnterBackground:(NSNotification *)noti{ 388 | YHThirdDebugLog(@"[Sina] applicationDidEnterBackground"); 389 | } 390 | 391 | - (void)applicationDidBecomeActive:(NSNotification *)noti{ 392 | YHThirdDebugLog(@"[Sina] applicationDidBecomeActive"); 393 | if (self.sdkFlag) { 394 | return; 395 | } 396 | [self _hideHUD:self.authHUD]; 397 | [self _hideHUD:self.shareWebHUD]; 398 | } 399 | 400 | #pragma mark 401 | - (void)didReceiveWeiboRequest:(WBBaseRequest *)request{ 402 | YHThirdDebugLog(@"[Sina] [didReceiveWeiboRequest] [request] %@ [userInfo] %@", request, request.userInfo); 403 | } 404 | 405 | - (void)didReceiveWeiboResponse:(WBBaseResponse *)response{ 406 | YHThirdDebugLog(@"[Sina] [didReceiveWeiboResponse] [response] %@ [statusCode] %d", response, (int)response.statusCode); 407 | if ([response isKindOfClass:[WBAuthorizeResponse class]]) { 408 | // 授权 409 | WBAuthorizeResponse *authorizeResponse = (WBAuthorizeResponse *)response; 410 | BOOL isSuccess = authorizeResponse.statusCode == WeiboSDKResponseStatusCodeSuccess; 411 | self.authorizeResponse = isSuccess ? authorizeResponse : nil; 412 | dispatch_async(dispatch_get_main_queue(), ^{ 413 | if (self.authCompletionBlock) { 414 | self.authCompletionBlock(isSuccess); 415 | } 416 | self.authCompletionBlock = nil; 417 | }); 418 | [self _hideHUD:self.authHUD]; 419 | [self _removeObserve]; 420 | } else if ([response isKindOfClass:[WBSendMessageToWeiboResponse class]]) { 421 | // 分享 422 | WBSendMessageToWeiboResponse *sendMessageToWeiboResponse = (WBSendMessageToWeiboResponse *)response; 423 | dispatch_async(dispatch_get_main_queue(), ^{ 424 | if (self.shareWebCompletionBlock) { 425 | self.shareWebCompletionBlock(sendMessageToWeiboResponse.statusCode == WeiboSDKResponseStatusCodeSuccess ? YES : NO); 426 | } 427 | self.shareWebCompletionBlock = nil; 428 | }); 429 | [self _hideHUD:self.shareWebHUD]; 430 | [self _removeObserve]; 431 | } 432 | } 433 | @end 434 | 435 | 436 | @implementation YHSinaManager (Private) 437 | // 添加观察者 438 | - (void)_addObserve{ 439 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 440 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; 441 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; 442 | } 443 | 444 | // 移除观察者 445 | - (void)_removeObserve{ 446 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 447 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 448 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; 449 | } 450 | 451 | // 显示HUD 452 | - (MBProgressHUD *)getHUD{ 453 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES];//必须在主线程,源码规定 454 | hud.mode = MBProgressHUDModeIndeterminate; 455 | hud.contentColor = [UIColor whiteColor]; 456 | hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; 457 | hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.7]; 458 | hud.removeFromSuperViewOnHide = YES; 459 | return hud; 460 | } 461 | 462 | // 隐藏HUD 463 | - (void)_hideHUD:(MBProgressHUD *)hud{ 464 | if (!hud) { return; } 465 | dispatch_async(dispatch_get_main_queue(), ^{ 466 | [hud hideAnimated:YES]; 467 | }); 468 | } 469 | @end 470 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Sina/YHSinaUserInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHSinaUserInfo.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface YHSinaUserInfo : NSObject 14 | // 昵称 15 | @property (nonatomic, copy) NSString *nickName; 16 | // 性别 0:未知 1:男 2:女 17 | @property (nonatomic, assign) int sex; 18 | // 省份 用户所在省级ID 19 | @property (nonatomic, copy) NSString *province; 20 | // 城市 用户所在城市ID 21 | @property (nonatomic, copy) NSString *city; 22 | // 头像 23 | @property (nonatomic, copy) NSString *headImgURL; 24 | // 原始数据(如果以上信息不能满足开发要求,则可以用此属性) 25 | @property (nonatomic, strong, nullable) NSDictionary *originInfo; 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/Sina/YHSinaUserInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHSinaUserInfo.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/11/3. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHSinaUserInfo.h" 10 | 11 | @implementation YHSinaUserInfo 12 | - (instancetype)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | self.nickName = @""; 17 | self.sex = 0; 18 | self.province = @""; 19 | self.city = @""; 20 | self.headImgURL = @""; 21 | self.originInfo = nil; 22 | } 23 | return self; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin Pay/YHWXManager+Pay.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXManager+Pay.h 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/12/30. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "YHWXManager.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | 15 | /// 微信支付模块,如果你的项目中没有使用到微信支付,请不要导入此模块 16 | @interface YHWXManager (Pay) 17 | 18 | /// 微信支付方式一:服务端只需要提供prepayID,其余的secretKey、partnerID、appID在APP里面写死(客户端做签名,不安全) 19 | /// @param partnerID 商户ID 20 | /// @param secretKey 商户秘钥(不是appSecret) 21 | /// @param prepayID 预支付ID 22 | /// @param showHUD 是否显示HUD 23 | /// @param completionBlock 支付完成后在主线程的回调 24 | - (void)pay1WithPartnerID:(NSString *)partnerID 25 | secretKey:(NSString *)secretKey 26 | prepayID:(NSString *)prepayID 27 | showHUD:(BOOL)showHUD 28 | comletionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 29 | 30 | /// 微信支付方式二:支付参数全从服务端获取 31 | /// @param partnerID 商户ID 32 | /// @param prepayID 预支付ID 33 | /// @param sign 签名 34 | /// @param nonceStr 随机字符串 35 | /// @param timeStamp 时间戳 36 | /// @param showHUD 是否显示HUD 37 | /// @param completionBlock 支付完成后在主线程的回调 38 | - (void)pay2WithPartnerID:(NSString *)partnerID 39 | prepayID:(NSString *)prepayID 40 | sign:(NSString *)sign 41 | nonceStr:(NSString *)nonceStr 42 | timeStamp:(NSString *)timeStamp 43 | showHUD:(BOOL)showHUD 44 | comletionBlock:(void (^)(BOOL isSuccess))completionBlock; 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin Pay/YHWXManager+Pay.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXManager+Pay.m 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/12/30. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHWXManager+Pay.h" 10 | #import 11 | #import 12 | #if __has_include() 13 | #import 14 | #elif __has_include("MBProgressHUD.h") 15 | #import "MBProgressHUD.h" 16 | #endif 17 | #import "YHThirdDefine.h" 18 | 19 | @interface YHWXManager() 20 | @property (nonatomic, strong) MBProgressHUD *payHUD; 21 | @property (nonatomic, copy) void(^payCompletionBlock)(BOOL isSuccess); 22 | @end 23 | 24 | 25 | @implementation YHWXManager (Pay) 26 | 27 | - (void)pay1WithPartnerID:(NSString *)partnerID 28 | secretKey:(NSString *)secretKey 29 | prepayID:(NSString *)prepayID 30 | showHUD:(BOOL)showHUD 31 | comletionBlock:(void (^)(BOOL))completionBlock{ 32 | YHThird_WeakSelf 33 | dispatch_async(dispatch_get_main_queue(), ^{ 34 | 35 | [weakSelf handleNotification]; 36 | 37 | if (!weakSelf.appID && weakSelf.appID.length <= 0) { 38 | YHThirdDebugLog(@"[微信] [支付1] appID为空"); 39 | return; 40 | } 41 | if (!partnerID && partnerID.length <= 0) { 42 | YHThirdDebugLog(@"[微信] [支付1] partnerID为空"); 43 | return; 44 | } 45 | if (!secretKey && secretKey.length <= 0) { 46 | YHThirdDebugLog(@"[微信] [支付1] secretKey为空"); 47 | return; 48 | } 49 | if (!prepayID && prepayID.length <= 0) { 50 | YHThirdDebugLog(@"[微信] [支付1] prepayID为空"); 51 | return; 52 | } 53 | 54 | if (showHUD && [WXApi isWXAppInstalled]) { 55 | [weakSelf _removeObserve]; 56 | [weakSelf _addObserve]; 57 | weakSelf.payHUD = [weakSelf getHUD]; 58 | } 59 | weakSelf.sdkFlag = NO; 60 | 61 | weakSelf.payCompletionBlock = completionBlock; 62 | 63 | int timestamp = [[weakSelf _currentTimestamp] intValue]; 64 | NSString *package = @"Sign=WXPay"; 65 | NSString *noncestr = [weakSelf _gen32NonceString]; 66 | 67 | NSDictionary *param = @{@"appid":weakSelf.appID, 68 | @"partnerid":partnerID, 69 | @"prepayid":prepayID, 70 | @"package":package, 71 | @"noncestr":noncestr, 72 | @"timestamp":[NSString stringWithFormat:@"%d",(int)timestamp]}; 73 | 74 | NSString *sign = [weakSelf _genSignWithSecretKey:secretKey param:param]; 75 | 76 | PayReq *request = [[PayReq alloc] init]; 77 | request.partnerId = partnerID; 78 | request.prepayId = prepayID; 79 | request.package = package; 80 | request.nonceStr = noncestr; 81 | request.timeStamp = timestamp; 82 | request.sign = sign; 83 | 84 | [WXApi sendReq:request completion:^(BOOL success) { 85 | 86 | if (!success) { 87 | dispatch_async(dispatch_get_main_queue(), ^{ 88 | if (completionBlock) { 89 | completionBlock(NO); 90 | } 91 | weakSelf.payCompletionBlock = nil; 92 | }); 93 | [weakSelf _removeObserve]; 94 | [weakSelf _hideHUD:weakSelf.payHUD]; 95 | } 96 | }]; 97 | }); 98 | } 99 | 100 | 101 | - (void)pay2WithPartnerID:(NSString *)partnerID 102 | prepayID:(NSString *)prepayID 103 | sign:(NSString *)sign 104 | nonceStr:(NSString *)nonceStr 105 | timeStamp:(NSString *)timeStamp 106 | showHUD:(BOOL)showHUD 107 | comletionBlock:(void (^)(BOOL))completionBlock{ 108 | YHThird_WeakSelf 109 | dispatch_async(dispatch_get_main_queue(), ^{ 110 | 111 | [weakSelf handleNotification]; 112 | 113 | if (!weakSelf.appID && weakSelf.appID.length <= 0) { 114 | YHThirdDebugLog(@"[微信] [支付2] appID为空"); 115 | return; 116 | } 117 | if (!partnerID && partnerID.length <= 0) { 118 | YHThirdDebugLog(@"[微信] [支付2] partnerID为空"); 119 | return; 120 | } 121 | if (!prepayID && prepayID.length <= 0) { 122 | YHThirdDebugLog(@"[微信] [支付2] prepayID为空"); 123 | return; 124 | } 125 | if (!sign && sign.length <= 0) { 126 | YHThirdDebugLog(@"[微信] [支付2] sign为空"); 127 | return; 128 | } 129 | if (!nonceStr && nonceStr.length <= 0) { 130 | YHThirdDebugLog(@"[微信] [支付2] nonceStr为空"); 131 | return; 132 | } 133 | if (!timeStamp && timeStamp.length <= 0) { 134 | YHThirdDebugLog(@"[微信] [支付2] timeStamp为空"); 135 | return; 136 | } 137 | 138 | if (showHUD && [WXApi isWXAppInstalled]) { 139 | [weakSelf _removeObserve]; 140 | [weakSelf _addObserve]; 141 | weakSelf.payHUD = [weakSelf getHUD]; 142 | } 143 | weakSelf.sdkFlag = NO; 144 | 145 | weakSelf.payCompletionBlock = completionBlock; 146 | 147 | PayReq *request = [[PayReq alloc] init]; 148 | request.partnerId = partnerID; 149 | request.prepayId = prepayID; 150 | request.package = @"Sign=WXPay"; 151 | request.nonceStr = nonceStr; 152 | request.timeStamp = [timeStamp intValue]; 153 | request.sign = sign; 154 | 155 | [WXApi sendReq:request completion:^(BOOL success) { 156 | if (!success) { 157 | dispatch_async(dispatch_get_main_queue(), ^{ 158 | if (completionBlock) { 159 | completionBlock(NO); 160 | } 161 | weakSelf.payCompletionBlock = nil; 162 | }); 163 | [weakSelf _removeObserve]; 164 | [weakSelf _hideHUD:weakSelf.payHUD]; 165 | } 166 | }]; 167 | }); 168 | } 169 | 170 | 171 | - (void)handleNotification{ 172 | [[NSNotificationCenter defaultCenter] removeObserver:self name:@"yh_wx_ppp_aaa_yyy_notification" object:nil]; 173 | [[NSNotificationCenter defaultCenter] removeObserver:self name:@"yh_wx_hide_hud_ppp_aaa_yyy_notification" object:nil]; 174 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(payNotification:) name:@"yh_wx_ppp_aaa_yyy_notification" object:nil]; 175 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hidePayHUDNotification) name:@"yh_wx_hide_hud_ppp_aaa_yyy_notification" object:nil]; 176 | } 177 | 178 | 179 | - (void)payNotification:(NSNotification *)noti{ 180 | BaseResp *resp = noti.userInfo[@"resp"]; 181 | if ([resp isKindOfClass:[PayResp class]]) { 182 | // 支付 183 | PayResp *response = (PayResp *)resp; 184 | YHThirdDebugLog(@"[微信] [onResp] [PayResp] [errCode] %d [returnKey] %@", response.errCode, response.returnKey); 185 | if (response.errCode == WXSuccess) { 186 | dispatch_async(dispatch_get_main_queue(), ^{ 187 | if (self.payCompletionBlock) { 188 | self.payCompletionBlock(YES); 189 | } 190 | self.payCompletionBlock = nil; 191 | }); 192 | [self _removeObserve]; 193 | [self _hideHUD:self.payHUD]; 194 | } else if (response.errCode == WXErrCodeCommon || 195 | response.errCode == WXErrCodeUserCancel || 196 | response.errCode == WXErrCodeSentFail || 197 | response.errCode == WXErrCodeAuthDeny || 198 | response.errCode == WXErrCodeUnsupport) { 199 | dispatch_async(dispatch_get_main_queue(), ^{ 200 | if (self.payCompletionBlock) { 201 | self.payCompletionBlock(NO); 202 | } 203 | self.payCompletionBlock = nil; 204 | }); 205 | [self _removeObserve]; 206 | [self _hideHUD:self.payHUD]; 207 | } 208 | } 209 | } 210 | 211 | - (void)hidePayHUDNotification{ 212 | [self _hideHUD:self.payHUD]; 213 | } 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | - (MBProgressHUD *)payHUD{ 235 | return [self getHUD]; 236 | } 237 | 238 | - (void)setPayHUD:(MBProgressHUD *)payHUD{ 239 | self.payHUD = payHUD; 240 | } 241 | 242 | - (void (^)(BOOL))payCompletionBlock{ 243 | return objc_getAssociatedObject(self, @selector(payCompletionBlock)); 244 | } 245 | 246 | - (void)setPayCompletionBlock:(void (^)(BOOL))payCompletionBlock{ 247 | objc_setAssociatedObject(self, @selector(payCompletionBlock), payCompletionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); 248 | } 249 | 250 | 251 | // 生成32位随机字符串 252 | - (NSString *)_gen32NonceString { 253 | NSArray *sampleArray = @[@"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", 254 | @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", 255 | @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", 256 | @"U", @"V", @"W", @"X", @"Y", @"Z"]; 257 | NSMutableString *randomString = [NSMutableString string]; 258 | for (NSInteger i = 0; i < 32; ++i) { 259 | [randomString appendString:sampleArray[random() % 32]]; 260 | } 261 | return randomString; 262 | } 263 | 264 | // 生成签名 secretKey:商户平台设置的密钥key(不是appSecret) 265 | - (NSString *)_genSignWithSecretKey:(NSString *)secretKey param:(NSDictionary *)param{ 266 | NSMutableString *stringA = [NSMutableString string]; 267 | // 按字典key升序排序 268 | NSArray *sortKeys = [[param allKeys] sortedArrayUsingSelector:@selector(compare:)]; 269 | // 拼接格式 “key0=value0&key1=value1&key2=value2” 270 | for (NSString *key in sortKeys) { 271 | [stringA appendString:[NSString stringWithFormat:@"%@=%@&", key, param[key]]]; 272 | } 273 | // 拼接商户签名,,,,kShopSign 要和微信平台上填写的密钥一样,(密钥就是签名) 274 | [stringA appendString:[NSString stringWithFormat:@"key=%@", secretKey]]; 275 | // MD5加密 276 | NSString *stringB = [self _MD5:stringA]; 277 | // 返回大写字母 278 | return stringB.uppercaseString; 279 | } 280 | 281 | // MD5 282 | - (NSString *)_MD5:(NSString *)string{ 283 | if (!string) { 284 | return @""; 285 | } 286 | const char *value = [string UTF8String]; 287 | unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH]; 288 | CC_MD5(value, (CC_LONG)strlen(value), outputBuffer); 289 | NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH]; 290 | for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){ 291 | [outputString appendFormat:@"%02x", outputBuffer[count]]; 292 | } 293 | return outputString; 294 | } 295 | 296 | // 获取当前时间戳 297 | - (NSString *)_currentTimestamp{ 298 | NSTimeInterval interval = [[NSDate date] timeIntervalSince1970]; 299 | return [NSString stringWithFormat:@"%ld", (long)interval]; 300 | } 301 | 302 | @end 303 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXAuthResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXAuthResult.h 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/11/8. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface YHWXAuthResult : NSObject 14 | @property (nonatomic, copy) NSString *code; 15 | @property (nonatomic, copy) NSString *openID; 16 | @property (nonatomic, copy) NSString *accessToken; 17 | @property (nonatomic, copy) NSString *expiresIn; 18 | @property (nonatomic, copy) NSString *refreshToken; 19 | @property (nonatomic, copy) NSString *scope; 20 | // 原始数据(如果以上信息不能满足开发要求,则可以用此属性) 21 | @property (nonatomic, strong, nullable) NSDictionary *originAuthInfo; 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXAuthResult.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXAuthResult.m 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/11/8. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHWXAuthResult.h" 10 | 11 | @implementation YHWXAuthResult 12 | - (instancetype)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | self.openID = @""; 17 | self.accessToken = @""; 18 | self.refreshToken = @""; 19 | self.scope = @""; 20 | self.expiresIn = @""; 21 | self.originAuthInfo = nil; 22 | } 23 | return self; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXManager.h 3 | // QAQSmooth 4 | // 5 | // Created by apple on 2019/3/7. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #if __has_include() 12 | #import 13 | #elif __has_include("WXApi.h") 14 | #import "WXApi.h" 15 | #endif 16 | #import "YHWXAuthResult.h" 17 | #import "YHWXUserInfo.h" 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | * 分享类型 23 | */ 24 | typedef NS_ENUM(NSUInteger, YHWXShareType) { 25 | YHWXShareType_Session, // 分享至聊天界面 26 | YHWXShareType_Timeline, // 分享至朋友圈 27 | }; 28 | 29 | 30 | 31 | /** 32 | * SDK版本:1.8.6.1 33 | * 微信授权、登录、分享封装(该模块不包含支付功能) 34 | * 文档1:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317853&lang=zh_CN 35 | */ 36 | @class MBProgressHUD; 37 | @interface YHWXManager : NSObject 38 | /// 初始化SDK的appID 39 | @property (nonatomic, copy, nullable, readonly) NSString *appID; 40 | /// 初始化SDK的appSecret 41 | @property (nonatomic, copy, nullable, readonly) NSString *appSecret; 42 | /// 授权获取的code 43 | @property (nonatomic, copy, nullable, readonly) NSString *code; 44 | /// 授权信息 45 | @property (nonatomic, strong, nullable, readonly) YHWXAuthResult *authResult; 46 | /// 用户信息 47 | @property (nonatomic, strong, nullable, readonly) YHWXUserInfo *userInfo; 48 | 49 | 50 | + (instancetype)sharedInstance; 51 | + (instancetype)new NS_UNAVAILABLE; 52 | - (instancetype)init NS_UNAVAILABLE; 53 | 54 | 55 | #pragma mark Init 56 | /// SDK初始化 57 | /// @param appID appID 58 | /// @param appSecret appSecret(当只需要获取code时,appSecret可以为空) 59 | /// @param universalLink Universal Link(根据最新微信SDK,需要`Universal Link`参数) 60 | - (void)initWithAppID:(NSString *)appID 61 | appSecret:(nullable NSString *)appSecret 62 | universalLink:(NSString *)universalLink; 63 | 64 | /// 处理微信通过URL启动App时传递的数据 65 | /// @param URL URL 66 | - (void)handleOpenURL:(NSURL *)URL; 67 | 68 | /// 处理微信通过`Universal Link`启动App时传递的数据 69 | /// @param userActivity 微信启动第三方应用时系统API传递过来的userActivity 70 | - (void)handleOpenUniversalLink:(NSUserActivity *)userActivity; 71 | 72 | 73 | #pragma mark Auth 74 | /// 获取code(获取code调用的是SDK里面的方法) 75 | /// @param showHUD 是否显示HUD 76 | /// @param completionBlock 回调(是否获取成功,code保存在属性`code`里面) 77 | - (void)authForGetCodeWithShowHUD:(BOOL)showHUD 78 | completionBlock:(void(^_Nullable)(BOOL isGetCodeSuccess))completionBlock; 79 | 80 | /// 通过code获取AccessToken(获取AccessToken其实是个普通的网络请求) 81 | /// @param appID appID 82 | /// @param appSecret appSecret 83 | /// @param code code 84 | /// @param completionBlock 回调(是否获取成功,授权信息保存在`authResult`里面) 85 | - (void)authForGetAccessTokenWithAppID:(NSString *)appID 86 | appSecret:(NSString *)appSecret 87 | code:(NSString *)code 88 | showHUD:(BOOL)showHUD 89 | completionBlock:(void(^_Nullable)(BOOL isGetAccessTokenSuccess))completionBlock; 90 | 91 | 92 | #pragma mark Get User Info 93 | /// 获取用户信息(本质上是一个普通的网络请求) 94 | /// @param openID 授权成功后获取到的openID 95 | /// @param accessToken 授权成功后获取到的accessToken 96 | /// @param showHUD 是否显示HUD 97 | /// @param completionBlock 回调(如果获取成功,那么用户信息保存在`userInfo`里面) 98 | - (void)getUserInfoWithOpenID:(NSString *)openID 99 | accessToken:(NSString *)accessToken 100 | showHUD:(BOOL)showHUD 101 | completionBlock:(void(^_Nullable)(BOOL isGetUserInfoSuccess))completionBlock; 102 | 103 | #pragma mark Share 104 | /** 105 | 微信分享网页 106 | 注意: 107 | 新版本微信SDK分享的时候,即使点击微信分享页面的取消按钮时,也是回调的分享成功。具体请看:https://mp.weixin.qq.com/s?__biz=MjM5NDAwMTA2MA==&mid=2695730124&idx=1&sn=666a448b047d657350de7684798f48d3&chksm=83d74a07b4a0c311569a748f4d11a5ebcce3ba8f6bd5a4b3183a4fea0b3442634a1c71d3cdd0&scene=21#wechat_redirect 108 | 109 | @param URL 链接 110 | @param title 标题 111 | @param description 描述 112 | @param thumbImage 缩略图 113 | @param shareType 分享类型(目前只能分享到朋友圈和聊天界面) 114 | @param showHUD 是否显示HUD 115 | @param completionBlock 分享完成后在主线程的回调 116 | */ 117 | - (void)shareWebWithURL:(NSString *)URL 118 | title:(nullable NSString *)title 119 | description:(nullable NSString *)description 120 | thumbImage:(nullable UIImage *)thumbImage 121 | shareType:(YHWXShareType)shareType 122 | showHUD:(BOOL)showHUD 123 | completionBlock:(void(^_Nullable)(BOOL isSuccess))completionBlock; 124 | @end 125 | 126 | 127 | 128 | @interface YHWXManager (Private) 129 | @property (nonatomic, assign) BOOL sdkFlag; 130 | - (MBProgressHUD *)getHUD; 131 | - (void)_hideHUD:(MBProgressHUD *)hud; 132 | - (void)_removeObserve; 133 | - (void)_addObserve; 134 | @end 135 | 136 | 137 | NS_ASSUME_NONNULL_END 138 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXManager.m 3 | // QAQSmooth 4 | // 5 | // Created by apple on 2019/3/7. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHWXManager.h" 10 | #import 11 | #import 12 | #if __has_include() 13 | #import 14 | #elif __has_include("MBProgressHUD.h") 15 | #import "MBProgressHUD.h" 16 | #endif 17 | #import "YHThirdDefine.h" 18 | #import "YHThirdHttpRequest.h" 19 | 20 | 21 | #define kGetAccessTokenAPI @"https://api.weixin.qq.com/sns/oauth2/access_token" 22 | #define kGetUserInfoAPI @"https://api.weixin.qq.com/sns/userinfo" 23 | 24 | 25 | 26 | @interface YHWXManager() 27 | @property (nonatomic, copy) NSString *appID; 28 | @property (nonatomic, copy) NSString *appSecret; 29 | @property (nonatomic, copy) NSString *code; 30 | @property (nonatomic, strong) YHWXAuthResult *authResult; 31 | @property (nonatomic, strong) YHWXUserInfo *userInfo; 32 | 33 | 34 | @property (nonatomic, strong) MBProgressHUD *requestCodeHUD; 35 | @property (nonatomic, strong) MBProgressHUD *requestAccessTokenHUD; 36 | @property (nonatomic, strong) MBProgressHUD *getUserInfoHUD; 37 | @property (nonatomic, strong) MBProgressHUD *shareWebHUD; 38 | 39 | 40 | @property (nonatomic, copy) void(^getCodeCompletionBlock)(BOOL isSuccess); 41 | @property (nonatomic, copy) void(^shareWebCompletionBlock)(BOOL isSuccess); 42 | @end 43 | 44 | 45 | @implementation YHWXManager 46 | 47 | + (instancetype)sharedInstance{ 48 | static YHWXManager *manager = nil; 49 | static dispatch_once_t onceToken; 50 | dispatch_once(&onceToken, ^{ 51 | manager = [[self alloc] init]; 52 | }); 53 | return manager; 54 | } 55 | 56 | - (instancetype)init 57 | { 58 | self = [super init]; 59 | if (self) { 60 | 61 | } 62 | return self; 63 | } 64 | 65 | - (void)initWithAppID:(NSString *)appID 66 | appSecret:(NSString *)appSecret 67 | universalLink:(NSString *)universalLink{ 68 | if (!appID) { 69 | YHThirdDebugLog(@"[微信] [初始化] appID为空"); 70 | return; 71 | } 72 | self.appID = appID; 73 | self.appSecret = appSecret; 74 | [WXApi registerApp:appID universalLink:universalLink]; 75 | } 76 | 77 | - (void)handleOpenURL:(NSURL *)URL{ 78 | YHThirdDebugLog(@"[微信] [handleOpenURL] [URL] %@", URL); 79 | [WXApi handleOpenURL:URL delegate:self]; 80 | } 81 | 82 | - (void)handleOpenUniversalLink:(NSUserActivity *)userActivity{ 83 | YHThirdDebugLog(@"[微信] [handleOpenUniversalLink] [userActivity] %@", userActivity); 84 | [WXApi handleOpenUniversalLink:userActivity delegate:self]; 85 | } 86 | 87 | 88 | #pragma mark Auth 89 | - (void)authForGetCodeWithShowHUD:(BOOL)showHUD completionBlock:(void (^)(BOOL))completionBlock{ 90 | YHThird_WeakSelf 91 | dispatch_async(dispatch_get_main_queue(), ^{ 92 | if (!self.appID) { 93 | YHThirdDebugLog(@"[微信] [获取code] appID为空"); 94 | return; 95 | } 96 | self.sdkFlag = NO; 97 | 98 | if (showHUD && [WXApi isWXAppInstalled]) { 99 | [self _removeObserve]; 100 | [self _addObserve]; 101 | self.requestCodeHUD = [self getHUD]; 102 | } 103 | 104 | self.getCodeCompletionBlock = completionBlock; 105 | 106 | SendAuthReq *rq = [[SendAuthReq alloc] init]; 107 | rq.scope = @"snsapi_userinfo"; 108 | 109 | [WXApi sendAuthReq:rq viewController:[UIApplication sharedApplication].keyWindow.rootViewController delegate:self completion:^(BOOL success) { 110 | if (!success) { 111 | dispatch_async(dispatch_get_main_queue(), ^{ 112 | if (completionBlock) { 113 | completionBlock(NO); 114 | } 115 | weakSelf.getCodeCompletionBlock = nil; 116 | }); 117 | [weakSelf _hideHUD:weakSelf.requestCodeHUD]; 118 | [weakSelf _removeObserve]; 119 | } 120 | }]; 121 | }); 122 | } 123 | 124 | /// 通过code获取AccessToken(获取AccessToken其实是个普通的网络请求) 125 | /// @param appID appID 126 | /// @param appSecret appSecret 127 | /// @param code code 128 | /// @param completionBlock 回调(是否获取成功,授权信息保存在`authResult`里面) 129 | - (void)authForGetAccessTokenWithAppID:(NSString *)appID 130 | appSecret:(NSString *)appSecret 131 | code:(NSString *)code 132 | showHUD:(BOOL)showHUD 133 | completionBlock:(void (^)(BOOL))completionBlock{ 134 | YHThird_WeakSelf 135 | dispatch_async(dispatch_get_main_queue(), ^{ 136 | weakSelf.sdkFlag = YES; 137 | 138 | if (showHUD) { 139 | weakSelf.requestAccessTokenHUD = [weakSelf getHUD]; 140 | } 141 | 142 | NSDictionary *param = @{@"appid": appID ? appID : @"", 143 | @"secret": appSecret ? appSecret : @"", 144 | @"code": code ? code : @"", 145 | @"grant_type": @"authorization_code"}; 146 | 147 | YHThirdDebugLog(@"[微信] [获取accessToken参数] %@", param); 148 | 149 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kGetAccessTokenAPI method:YHThirdHttpRequestMethodGET parameter:param successBlock:^(id _Nonnull responseObject) { 150 | [weakSelf _hideHUD:weakSelf.requestAccessTokenHUD]; 151 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 152 | YHThirdDebugLog(@"[微信] [获取accessToken失败] [数据格式不正确] %@", responseObject); 153 | weakSelf.authResult = nil; // 置为nil 154 | dispatch_async(dispatch_get_main_queue(), ^{ 155 | if (completionBlock) { 156 | completionBlock(NO); 157 | } 158 | }); 159 | return ; 160 | } 161 | YHThirdDebugLog(@"[微信] [获取accessToken成功] %@", responseObject); 162 | NSDictionary *infoDic = (NSDictionary *)responseObject; 163 | YHWXAuthResult *authResult = [[YHWXAuthResult alloc] init]; 164 | authResult.code = code; 165 | authResult.originAuthInfo = infoDic; 166 | if ([infoDic.allKeys containsObject:@"access_token"]) { 167 | authResult.accessToken = [NSString stringWithFormat:@"%@",infoDic[@"access_token"]]; 168 | } 169 | if ([infoDic.allKeys containsObject:@"expires_in"]) { 170 | authResult.expiresIn = [NSString stringWithFormat:@"%@",infoDic[@"expires_in"]]; 171 | } 172 | if ([infoDic.allKeys containsObject:@"refresh_token"]) { 173 | authResult.refreshToken = [NSString stringWithFormat:@"%@",infoDic[@"refresh_token"]]; 174 | } 175 | if ([infoDic.allKeys containsObject:@"openid"]) { 176 | authResult.openID = [NSString stringWithFormat:@"%@",infoDic[@"openid"]]; 177 | } 178 | if ([infoDic.allKeys containsObject:@"scope"]) { 179 | authResult.scope = [NSString stringWithFormat:@"%@",infoDic[@"scope"]]; 180 | } 181 | weakSelf.authResult = authResult; 182 | dispatch_async(dispatch_get_main_queue(), ^{ 183 | if (completionBlock) { 184 | completionBlock(YES); 185 | } 186 | }); 187 | } failureBlock:^(NSError * _Nonnull error) { 188 | YHThirdDebugLog(@"[微信] [获取accessToken失败] %@", error); 189 | [weakSelf _hideHUD:weakSelf.requestAccessTokenHUD]; 190 | weakSelf.authResult = nil; // 置为nil 191 | dispatch_async(dispatch_get_main_queue(), ^{ 192 | if (completionBlock) { 193 | completionBlock(NO); 194 | } 195 | }); 196 | }]; 197 | }); 198 | } 199 | 200 | 201 | #pragma mark Get User Info 202 | /// 获取用户信息(本质上是一个普通的网络请求) 203 | /// @param openID 授权成功后获取到的openID 204 | /// @param accessToken 授权成功后获取到的accessToken 205 | /// @param showHUD 是否显示HUD 206 | /// @param completionBlock 回调(如果获取成功,那么用户信息保存在`userInfo`里面) 207 | - (void)getUserInfoWithOpenID:(NSString *)openID 208 | accessToken:(NSString *)accessToken 209 | showHUD:(BOOL)showHUD 210 | completionBlock:(void (^)(BOOL))completionBlock{ 211 | YHThird_WeakSelf 212 | dispatch_async(dispatch_get_main_queue(), ^{ 213 | weakSelf.sdkFlag = YES; 214 | 215 | if (showHUD) { 216 | weakSelf.getUserInfoHUD = [weakSelf getHUD]; 217 | } 218 | 219 | NSDictionary *param = @{@"access_token": accessToken ? accessToken : @"", 220 | @"openid": openID ? openID : @""}; 221 | 222 | YHThirdDebugLog(@"[微信] [获取用户信息参数] %@", param); 223 | 224 | [[YHThirdHttpRequest sharedInstance] requestWithURL:kGetUserInfoAPI method:YHThirdHttpRequestMethodGET parameter:param successBlock:^(id _Nonnull responseObject) { 225 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 226 | if (![responseObject isKindOfClass:[NSDictionary class]]) { 227 | YHThirdDebugLog(@"[微信] [获取用户信息失败] [数据格式不正确] %@", responseObject); 228 | weakSelf.userInfo = nil; // 置为nil 229 | dispatch_async(dispatch_get_main_queue(), ^{ 230 | if (completionBlock) { 231 | completionBlock(NO); 232 | } 233 | }); 234 | return ; 235 | } 236 | YHThirdDebugLog(@"[微信] [获取用户信息成功] %@", responseObject); 237 | NSDictionary *infoDic = (NSDictionary *)responseObject; 238 | YHWXUserInfo *userInfo = [[YHWXUserInfo alloc] init]; 239 | userInfo.originInfo = infoDic; 240 | if ([infoDic.allKeys containsObject:@"nickname"]) { 241 | userInfo.nickName = [NSString stringWithFormat:@"%@",infoDic[@"nickname"]]; 242 | } 243 | if ([infoDic.allKeys containsObject:@"sex"]) { 244 | NSString *sex = [NSString stringWithFormat:@"%@",infoDic[@"sex"]]; 245 | NSString *regex = @"[0-9]*"; 246 | NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex]; 247 | BOOL res = [pred evaluateWithObject:sex]; 248 | if (res) { 249 | userInfo.sex = [sex intValue]; 250 | } else { 251 | userInfo.sex = 0; 252 | } 253 | } 254 | if ([infoDic.allKeys containsObject:@"province"]) { 255 | userInfo.province = [NSString stringWithFormat:@"%@",infoDic[@"province"]]; 256 | } 257 | if ([infoDic.allKeys containsObject:@"city"]) { 258 | userInfo.city = [NSString stringWithFormat:@"%@",infoDic[@"city"]]; 259 | } 260 | if ([infoDic.allKeys containsObject:@"country"]) { 261 | userInfo.country = [NSString stringWithFormat:@"%@",infoDic[@"country"]]; 262 | } 263 | if ([infoDic.allKeys containsObject:@"headimgurl"]) { 264 | userInfo.headImgURL = [NSString stringWithFormat:@"%@",infoDic[@"headimgurl"]]; 265 | } 266 | if ([infoDic.allKeys containsObject:@"unionid"]) { 267 | userInfo.unionID = [NSString stringWithFormat:@"%@",infoDic[@"unionid"]]; 268 | } 269 | weakSelf.userInfo = userInfo; 270 | 271 | dispatch_async(dispatch_get_main_queue(), ^{ 272 | if (completionBlock) { 273 | completionBlock(YES); 274 | } 275 | }); 276 | } failureBlock:^(NSError * _Nonnull error) { 277 | YHThirdDebugLog(@"[微信] [获取用户信息失败] %@", error); 278 | [weakSelf _hideHUD:weakSelf.getUserInfoHUD]; 279 | weakSelf.userInfo = nil; // 置为nil 280 | dispatch_async(dispatch_get_main_queue(), ^{ 281 | if (completionBlock) { 282 | completionBlock(NO); 283 | } 284 | }); 285 | }]; 286 | }); 287 | } 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | #pragma mark Share 297 | /* 298 | 注意: 299 | 新版本微信SDK分享的时候,即使点击微信分享页面的取消按钮时,也是回调的分享成功。 300 | 具体请看:https://mp.weixin.qq.com/s?__biz=MjM5NDAwMTA2MA==&mid=2695730124&idx=1&sn=666a448b047d657350de7684798f48d3&chksm=83d74a07b4a0c311569a748f4d11a5ebcce3ba8f6bd5a4b3183a4fea0b3442634a1c71d3cdd0&scene=21#wechat_redirect 301 | */ 302 | /// 微信分享网页 303 | /// @param URL 链接 304 | /// @param title 标题 305 | /// @param description 描述 306 | /// @param thumbImage 缩略图 307 | /// @param shareType 分享类型(目前只能分享到朋友圈和聊天界面) 308 | /// @param showHUD 是否显示HUD 309 | /// @param completionBlock 分享完成后的回调 310 | - (void)shareWebWithURL:(NSString *)URL 311 | title:(NSString *)title 312 | description:(NSString *)description 313 | thumbImage:(UIImage *)thumbImage 314 | shareType:(YHWXShareType)shareType 315 | showHUD:(BOOL)showHUD 316 | completionBlock:(void (^)(BOOL))completionBlock{ 317 | YHThird_WeakSelf 318 | dispatch_async(dispatch_get_main_queue(), ^{ 319 | if (!weakSelf.appID) { 320 | YHThirdDebugLog(@"[微信] [分享] appID为空"); 321 | return; 322 | } 323 | if (showHUD && [WXApi isWXAppInstalled]) { 324 | [weakSelf _removeObserve]; 325 | [weakSelf _addObserve]; 326 | weakSelf.shareWebHUD = [weakSelf getHUD]; 327 | } 328 | weakSelf.sdkFlag = NO; 329 | 330 | weakSelf.shareWebCompletionBlock = completionBlock; 331 | 332 | WXWebpageObject *webpageObject = [WXWebpageObject object]; 333 | webpageObject.webpageUrl = URL; 334 | 335 | WXMediaMessage *message = [WXMediaMessage message]; 336 | message.title = title; 337 | message.description = description; 338 | [message setThumbImage:thumbImage]; 339 | message.mediaObject = webpageObject; 340 | 341 | SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init]; 342 | req.bText = NO; // YES:文本消息 NO:多媒体消息 343 | req.message = message; 344 | 345 | enum WXScene scene = WXSceneSession; 346 | if (shareType == YHWXShareType_Session) { 347 | scene = WXSceneSession; 348 | } else if (shareType == YHWXShareType_Timeline) { 349 | scene = WXSceneTimeline; 350 | } 351 | req.scene = scene; 352 | 353 | [WXApi sendReq:req completion:^(BOOL success) { 354 | if (!success) { 355 | dispatch_async(dispatch_get_main_queue(), ^{ 356 | if (completionBlock) { 357 | completionBlock(NO); 358 | } 359 | weakSelf.shareWebCompletionBlock = nil; 360 | }); 361 | [weakSelf _removeObserve]; 362 | [weakSelf _hideHUD:weakSelf.shareWebHUD]; 363 | } 364 | }]; 365 | }); 366 | } 367 | 368 | #pragma mark ------------------ Notification ------------------ 369 | - (void)applicationWillEnterForeground:(NSNotification *)noti{ 370 | YHThirdDebugLog(@"[微信] applicationWillEnterForeground"); 371 | [self _hideHUD:self.requestCodeHUD]; 372 | [self _hideHUD:self.shareWebHUD]; 373 | [[NSNotificationCenter defaultCenter] postNotificationName:@"yh_wx_hide_hud_ppp_aaa_yyy_notification" object:nil userInfo:nil]; 374 | } 375 | 376 | - (void)applicationDidEnterBackground:(NSNotification *)noti{ 377 | YHThirdDebugLog(@"[微信] applicationDidEnterBackground"); 378 | } 379 | 380 | - (void)applicationDidBecomeActive:(NSNotification *)noti{ 381 | YHThirdDebugLog(@"[微信] applicationDidBecomeActive"); 382 | if (self.sdkFlag) { 383 | return; 384 | } 385 | [self _hideHUD:self.requestCodeHUD]; 386 | [self _hideHUD:self.shareWebHUD]; 387 | [[NSNotificationCenter defaultCenter] postNotificationName:@"yh_wx_hide_hud_ppp_aaa_yyy_notification" object:nil userInfo:nil]; 388 | } 389 | 390 | 391 | #pragma mark ------------------ ------------------ 392 | - (void)onReq:(BaseReq *)req{ 393 | YHThirdDebugLog(@"[微信] [onReq] [req] %@ [type] %d", req, req.type); 394 | } 395 | 396 | 397 | 398 | /* 399 | WXSuccess = 0, // 成功 400 | WXErrCodeCommon = -1, // 普通错误类型 401 | WXErrCodeUserCancel = -2, // 用户点击取消并返回 402 | WXErrCodeSentFail = -3, // 发送失败 403 | WXErrCodeAuthDeny = -4, // 授权失败 404 | WXErrCodeUnsupport = -5, // 微信不支持 405 | */ 406 | - (void)onResp:(BaseResp *)resp{ 407 | if ([resp isKindOfClass:[SendAuthResp class]]) { 408 | // 授权 409 | SendAuthResp *response = (SendAuthResp *)resp; 410 | YHThirdDebugLog(@"[微信] [onResp] [SendAuthResp] [errCode] %d", response.errCode); 411 | YHThirdDebugLog(@"[微信] [onResp] [SendAuthResp] [code] %@", response.code); 412 | YHThirdDebugLog(@"[微信] [onResp] [SendAuthResp] [state] %@", response.state); 413 | YHThirdDebugLog(@"[微信] [onResp] [SendAuthResp] [lang] %@", response.lang); 414 | YHThirdDebugLog(@"[微信] [onResp] [SendAuthResp] [country] %@", response.country); 415 | 416 | if (response.errCode == WXSuccess) { 417 | self.sdkFlag = YES; 418 | [self _removeObserve]; 419 | [self _hideHUD:self.requestCodeHUD]; 420 | 421 | NSString *code = response.code; // code 422 | self.code = code; 423 | 424 | dispatch_async(dispatch_get_main_queue(), ^{ 425 | if (self.getCodeCompletionBlock) { 426 | self.getCodeCompletionBlock(YES); 427 | } 428 | self.getCodeCompletionBlock = nil; 429 | }); 430 | } else if (response.errCode == WXErrCodeCommon || 431 | response.errCode == WXErrCodeUserCancel || 432 | response.errCode == WXErrCodeSentFail || 433 | response.errCode == WXErrCodeAuthDeny || 434 | response.errCode == WXErrCodeUnsupport) { 435 | [self _removeObserve]; 436 | [self _hideHUD:self.requestCodeHUD]; 437 | self.code = nil; 438 | dispatch_async(dispatch_get_main_queue(), ^{ 439 | if (self.getCodeCompletionBlock) { 440 | self.getCodeCompletionBlock(NO); 441 | } 442 | self.getCodeCompletionBlock = nil; 443 | }); 444 | } 445 | } else if ([resp isKindOfClass:[SendMessageToWXResp class]]) { 446 | // 分享 447 | SendMessageToWXResp *response = (SendMessageToWXResp *)resp; 448 | YHThirdDebugLog(@"[微信] [onResp] [SendMessageToWXResp] [errCode] %d", response.errCode); 449 | if (response.errCode == WXSuccess) { 450 | dispatch_async(dispatch_get_main_queue(), ^{ 451 | if (self.shareWebCompletionBlock) { 452 | self.shareWebCompletionBlock(YES); 453 | } 454 | self.shareWebCompletionBlock = nil; 455 | }); 456 | [self _removeObserve]; 457 | [self _hideHUD:self.shareWebHUD]; 458 | } else if (response.errCode == WXErrCodeCommon || 459 | response.errCode == WXErrCodeUserCancel || 460 | response.errCode == WXErrCodeSentFail || 461 | response.errCode == WXErrCodeAuthDeny || 462 | response.errCode == WXErrCodeUnsupport) { 463 | dispatch_async(dispatch_get_main_queue(), ^{ 464 | if (self.shareWebCompletionBlock) { 465 | self.shareWebCompletionBlock(NO); 466 | } 467 | self.shareWebCompletionBlock = nil; 468 | }); 469 | [self _removeObserve]; 470 | [self _hideHUD:self.shareWebHUD]; 471 | } 472 | } else { 473 | [[NSNotificationCenter defaultCenter] postNotificationName:@"yh_wx_ppp_aaa_yyy_notification" object:nil userInfo:@{@"resp": resp}]; 474 | } 475 | } 476 | @end 477 | 478 | 479 | 480 | @implementation YHWXManager (Private) 481 | - (BOOL)sdkFlag{ 482 | return [objc_getAssociatedObject(self, @selector(sdkFlag)) boolValue]; 483 | } 484 | - (void)setSdkFlag:(BOOL)sdkFlag{ 485 | objc_setAssociatedObject(self, @selector(sdkFlag), @(sdkFlag), OBJC_ASSOCIATION_ASSIGN); 486 | } 487 | // 显示HUD 488 | - (MBProgressHUD *)getHUD{ 489 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES];//必须在主线程,源码规定 490 | hud.mode = MBProgressHUDModeIndeterminate; 491 | hud.contentColor = [UIColor whiteColor]; 492 | hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor; 493 | hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.7]; 494 | hud.removeFromSuperViewOnHide = YES; 495 | return hud; 496 | } 497 | 498 | 499 | // 隐藏HUD 500 | - (void)_hideHUD:(MBProgressHUD *)hud{ 501 | __weak typeof(hud) weakHUD = hud; 502 | if (hud) { 503 | dispatch_async(dispatch_get_main_queue(), ^{ 504 | __strong typeof(weakHUD) strongHUD = weakHUD; 505 | [strongHUD hideAnimated:YES]; 506 | strongHUD = nil; 507 | }); 508 | } 509 | } 510 | // 添加观察者 511 | - (void)_addObserve{ 512 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 513 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; 514 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; 515 | } 516 | 517 | // 移除观察者 518 | - (void)_removeObserve{ 519 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 520 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 521 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; 522 | } 523 | @end 524 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXUserInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXUserInfo.h 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/12/30. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface YHWXUserInfo : NSObject 14 | // 普通用户昵称 15 | @property (nonatomic, copy) NSString *nickName; 16 | // 普通用户性别 0:未知 1:男性 2:女性 17 | @property (nonatomic, assign) int sex; 18 | // 普通用户个人资料填写的省份 19 | @property (nonatomic, copy) NSString *province; 20 | // 普通用户个人资料填写的城市 21 | @property (nonatomic, copy) NSString *city; 22 | // 国家,如中国为CN 23 | @property (nonatomic, copy) NSString *country; 24 | // 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空 25 | @property (nonatomic, copy) NSString *headImgURL; 26 | // 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。 27 | @property (nonatomic, copy) NSString *unionID; 28 | // 原始数据(如果以上信息不能满足开发要求,则可以用此属性) 29 | @property (nonatomic, strong, nullable) NSDictionary *originInfo; 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /YHThirdManager/Sources/WeiXin/YHWXUserInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // YHWXUserInfo.m 3 | // YHThirdManager 4 | // 5 | // Created by apple on 2019/12/30. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "YHWXUserInfo.h" 10 | 11 | @implementation YHWXUserInfo 12 | - (instancetype)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | 17 | self.nickName = @""; 18 | self.sex = 0; 19 | self.province = @""; 20 | self.city = @""; 21 | self.country = @""; 22 | self.headImgURL = @""; 23 | self.unionID = @""; 24 | self.originInfo = nil; 25 | } 26 | return self; 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/Headers/QQApiInterface.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file QQApiInterface.h 3 | /// \brief QQApi接口简化封装 4 | /// 5 | /// Created by Tencent on 12-5-15. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import "QQApiInterfaceObject.h" 11 | 12 | typedef void (^sendResultBlock)(NSDictionary *result); 13 | 14 | /** 15 | \brief 处理来至QQ的请求及响应的回调协议 16 | */ 17 | @protocol QQApiInterfaceDelegate 18 | 19 | /** 20 | 处理来至QQ的请求 21 | */ 22 | - (void)onReq:(QQBaseReq *)req; 23 | 24 | /** 25 | 处理来至QQ的响应 26 | */ 27 | - (void)onResp:(QQBaseResp *)resp; 28 | 29 | /** 30 | 处理QQ在线状态的回调 31 | */ 32 | - (void)isOnlineResponse:(NSDictionary *)response; 33 | 34 | @end 35 | 36 | /** 37 | \brief 对QQApi的简单封装类 38 | */ 39 | @interface QQApiInterface : NSObject 40 | 41 | /** 42 | 处理由手Q唤起的普通跳转请求 43 | \param url 待处理的url跳转请求 44 | \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 45 | \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 46 | */ 47 | + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; 48 | 49 | /** 50 | 处理由手Q唤起的universallink跳转请求 51 | \param universallink 待处理的universallink跳转请求 52 | \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 53 | \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 54 | */ 55 | + (BOOL)handleOpenUniversallink:(NSURL*)universallink delegate:(id)delegate; 56 | 57 | /** 58 | 向手Q发起分享请求 59 | \param req 分享内容的请求 60 | \return 请求发送结果码 61 | */ 62 | + (QQApiSendResultCode)sendReq:(QQBaseReq *)req; 63 | 64 | 65 | /** 66 | 向手Q QZone结合版发起分享请求 67 | \note H5分享只支持单张网络图片的传递 68 | \param req 分享内容的请求 69 | \return 请求发送结果码 70 | */ 71 | + (QQApiSendResultCode)SendReqToQZone:(QQBaseReq *)req; 72 | 73 | /** 74 | 向手Q发起设置QQ头像 75 | \param req 分享内容的请求 76 | \return 请求发送结果码 77 | */ 78 | + (QQApiSendResultCode)sendMessageToQQAvatarWithReq:(QQBaseReq*)req; 79 | 80 | /** 81 | 向手Q发起组图分享到表情收藏 82 | \param req 分享内容的请求 83 | \return 请求发送结果码 84 | */ 85 | + (QQApiSendResultCode)sendMessageToFaceCollectionWithReq:(QQBaseReq*)req; 86 | 87 | /** 88 | 检测是否已安装QQ 89 | \return 如果QQ已安装则返回YES,否则返回NO 90 | 91 | \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 92 | 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 93 | 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 94 | */ 95 | + (BOOL)isQQInstalled; 96 | 97 | /** 98 | 检测是否已安装TIM 99 | \return 如果TIM已安装则返回YES,否则返回NO 100 | 101 | \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 102 | 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 103 | 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 104 | */ 105 | + (BOOL)isTIMInstalled; 106 | 107 | /** 108 | 检测QQ是否支持API调用 109 | \return 如果当前安装QQ版本支持API调用则返回YES,否则返回NO 110 | */ 111 | + (BOOL)isQQSupportApi; 112 | 113 | /** 114 | 检测TIM是否支持API调用 115 | \return 如果当前安装TIM版本支持API调用则返回YES,否则返回NO 116 | */ 117 | + (BOOL)isTIMSupportApi __attribute__((deprecated("已过期, 建议删除调用,调用地方用YES替代。"))); 118 | 119 | /** 120 | 检测是否支持分享 121 | \return 如果当前已安装QQ且QQ版本支持API调用 或者 当前已安装TIM且TIM版本支持API调用则返回YES,否则返回NO 122 | */ 123 | + (BOOL)isSupportShareToQQ; 124 | 125 | /** 126 | 检测是否支持分享到QQ结合版QZone 127 | \return 如果当前已安装QQ且QQ版本支持API调用则返回YES,否则返回NO 128 | */ 129 | + (BOOL)isSupportPushToQZone; 130 | 131 | /** 132 | 启动QQ 133 | \return 成功返回YES,否则返回NO 134 | */ 135 | + (BOOL)openQQ; 136 | 137 | /** 138 | 启动TIM 139 | \return 成功返回YES,否则返回NO 140 | */ 141 | + (BOOL)openTIM; 142 | 143 | /** 144 | 获取QQ下载地址 145 | 146 | 如果App通过QQApiInterface#isQQInstalledQQApiInterface#isQQSupportApi检测发现QQ没安装或当前版本QQ不支持API调用,可引导用户通过打开此链接下载最新版QQ。 147 | \return iPhoneQQ下载地址 148 | */ 149 | + (NSString *)getQQInstallUrl; 150 | 151 | /** 152 | 获取TIM下载地址 153 | 154 | 如果App通过QQApiInterface#isTIMInstalled检测发现TIM没安装或当前版本TIM不支持API调用,可引导用户通过打开此链接下载最新版TIM。 155 | \return iPhoneTIM下载地址 156 | */ 157 | + (NSString *)getTIMInstallUrl; 158 | @end 159 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file QQApiInterfaceObject.h 3 | /// \brief QQApiInterface所依赖的请求及应答消息对象封装帮助类 4 | /// 5 | /// Created by Tencent on 12-5-15. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #ifndef QQApiInterface_QQAPIOBJECT_h 10 | #define QQApiInterface_QQAPIOBJECT_h 11 | 12 | #import 13 | 14 | typedef NS_ENUM(NSInteger,QQApiSendResultCode) { 15 | EQQAPISENDSUCESS = 0, 16 | EQQAPIQQNOTINSTALLED = 1, //QQ未安装 17 | EQQAPIQQNOTSUPPORTAPI = 2, // QQ api不支持 18 | EQQAPIMESSAGETYPEINVALID = 3, 19 | EQQAPIMESSAGECONTENTNULL = 4, 20 | EQQAPIMESSAGECONTENTINVALID = 5, 21 | EQQAPIAPPNOTREGISTED = 6, 22 | EQQAPIAPPSHAREASYNC = 7, 23 | EQQAPIQQNOTSUPPORTAPI_WITH_ERRORSHOW = 8, //QQ api不支持 && SDK显示error提示(已废弃) 24 | EQQAPIMESSAGEARKCONTENTNULL = 9, //ark内容为空 25 | EQQAPIMESSAGE_MINI_CONTENTNULL = 10, //小程序参数为空 26 | EQQAPISENDFAILD = -1, //发送失败 27 | EQQAPISHAREDESTUNKNOWN = -2, //未指定分享到QQ或TIM 28 | EQQAPITIMSENDFAILD = -3, //发送失败 29 | EQQAPITIMNOTINSTALLED = 11, //TIM未安装 30 | EQQAPITIMNOTSUPPORTAPI = 12, // TIM api不支持 31 | EQQAPI_INCOMING_PARAM_ERROR = 13, // 外部传参错误 32 | EQQAPI_THIRD_APP_GROUP_ERROR_APP_NOT_AUTHORIZIED = 14, // APP未获得授权 33 | EQQAPI_THIRD_APP_GROUP_ERROR_CGI_FAILED = 15, // CGI请求失败 34 | EQQAPI_THIRD_APP_GROUP_ERROR_HAS_BINDED = 16, // 该组织已经绑定群聊 35 | EQQAPI_THIRD_APP_GROUP_ERROR_NOT_BINDED = 17, // 该组织尚未绑定群聊 36 | EQQAPIQZONENOTSUPPORTTEXT = 10000, //qzone分享不支持text类型分享 37 | EQQAPIQZONENOTSUPPORTIMAGE = 10001, //qzone分享不支持image类型分享 38 | EQQAPIVERSIONNEEDUPDATE = 10002, //当前QQ版本太低,需要更新至新版本才可以支持 39 | ETIMAPIVERSIONNEEDUPDATE = 10004, //当前TIM版本太低,需要更新至新版本才可以支持 40 | }; 41 | 42 | #pragma mark - QQApiObject(分享对象类型) 43 | 44 | // QQApiObject control flags 45 | typedef NS_ENUM(NSUInteger,kQQAPICtrlFlag) { 46 | kQQAPICtrlFlagQZoneShareOnStart = 0x01, 47 | kQQAPICtrlFlagQZoneShareForbid = 0x02, 48 | kQQAPICtrlFlagQQShare = 0x04, 49 | kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏 50 | kQQAPICtrlFlagQQShareDataline = 0x10, //数据线 51 | kQQAPICtrlFlagQQShareEnableArk = 0x20, //支持ARK 52 | kQQAPICtrlFlagQQShareEnableMiniProgram = 0x40, //支持小程序 53 | }; 54 | 55 | // 分享到QQ或TIM 56 | typedef NS_ENUM(NSUInteger, ShareDestType) { 57 | ShareDestTypeQQ = 0, 58 | ShareDestTypeTIM, 59 | }; 60 | 61 | //小程序的类型 62 | typedef NS_ENUM(NSUInteger, MiniProgramType) { 63 | MiniProgramType_Develop=0, // 开发版 64 | MiniProgramType_Test=1, // 测试版 65 | MiniProgramType_Online=3, // 正式版,默认 66 | MiniProgramType_Preview=4, // 预览版 67 | }; 68 | 69 | // QQApiObject 70 | /** \brief 所有在QQ及插件间发送的数据对象的根类。 71 | */ 72 | __attribute__((visibility("default"))) @interface QQApiObject : NSObject 73 | @property(nonatomic, retain) NSString* title; ///< 标题,最长128个字符 74 | @property(nonatomic, retain) NSString* description; ///<简要描述,最长512个字符 75 | @property(nonatomic, retain) NSString* universalLink; ///(>=3.3.7)支持第三方传入在互联开放平台注册的universallink 76 | @property(nonatomic, assign) uint64_t cflag; 77 | /* 78 | * 分享到QQ/TIM 79 | * SDK根据是否安装对应客户端进行判断,判断顺序:QQ > TIM 80 | * 默认分享到QQ,如果QQ未安装检测TIM是否安装 81 | */ 82 | @property (nonatomic, assign) ShareDestType shareDestType; 83 | @end 84 | 85 | // ArkObject 86 | /** \brief 支持Ark的根类。 87 | */ 88 | __attribute__((visibility("default"))) @interface ArkObject : NSObject 89 | @property(nonatomic,retain) NSString* arkData; ///< 显示Ark所需的数据,json串,长度暂不限制 90 | @property(nonatomic,assign) QQApiObject* qqApiObject; ///<原有老版本的QQApiObject 91 | 92 | - (id)initWithData:(NSString *)arkData qqApiObject:(QQApiObject*)qqApiObject; 93 | + (id)objectWithData:(NSString *)arkData qqApiObject:(QQApiObject*)qqApiObject; 94 | @end 95 | 96 | #pragma mark QQ小程序 97 | //分享小程序消息 - QQ 8.0.8 98 | __attribute__((visibility("default"))) @interface QQApiMiniProgramObject : NSObject 99 | @property(nonatomic,retain) QQApiObject* qqApiObject; //原有老版本的QQApiObject 100 | @property(nonatomic,retain) NSString* miniAppID; //必填,小程序的AppId(注:必须在QQ互联平台中,将该小程序与分享的App绑定) 101 | @property(nonatomic,retain) NSString* miniPath; //必填,小程序的展示路径 102 | @property(nonatomic,retain) NSString* webpageUrl; //必填,兼容低版本的网页链接 103 | @property(nonatomic,assign) MiniProgramType miniprogramType; //非必填,小程序的类型,默认正式版(3),可选测试版(1)、预览版(4) 104 | @end 105 | 106 | //唤起小程序 - QQ 8.1.8 107 | __attribute__((visibility("default"))) @interface QQApiLaunchMiniProgramObject : QQApiObject 108 | @property(nonatomic,retain) NSString* miniAppID; //必填,小程序的AppId(注:必须在QQ互联平台中,将该小程序与分享的App绑定) 109 | @property(nonatomic,retain) NSString* miniPath; //必填,小程序的展示路径 110 | @property(nonatomic,assign) MiniProgramType miniprogramType; //非必填,小程序的类型,默认正式版(3),可选测试版(1)、开发版(0) 111 | @end 112 | // QQApiResultObject 113 | /** \brief 用于请求回应的数据类型。 114 |

可能错误码及描述如下:

115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 |
errorerrorDescription注释
0nil成功
-1param error参数错误
-2group code is invalid该群不在自己的群列表里面
-3upload photo failed上传图片失败
-4user give up the current operation用户放弃当前操作
-5client internal error客户端内部处理错误
124 | */ 125 | __attribute__((visibility("default"))) @interface QQApiResultObject : QQApiObject 126 | @property(nonatomic,retain) NSString* error; ///<错误 127 | @property(nonatomic,retain) NSString* errorDescription; ///<错误描述 128 | @property(nonatomic,retain) NSString* extendInfo; ///<扩展信息 129 | @end 130 | 131 | // QQApiTextObject 132 | /** \brief 文本对象 133 | */ 134 | @interface QQApiTextObject : QQApiObject 135 | @property(nonatomic,retain)NSString* text; ///<文本内容,必填,最长1536个字符 136 | 137 | -(id)initWithText:(NSString*)text; ///<初始化方法 138 | +(id)objectWithText:(NSString*)text;///<工厂方法,获取一个QQApiTextObject对象. 139 | @end 140 | 141 | // QQApiURLObject 142 | typedef NS_ENUM(NSUInteger, QQApiURLTargetType) { 143 | QQApiURLTargetTypeNotSpecified = 0x00, 144 | QQApiURLTargetTypeAudio = 0x01, 145 | QQApiURLTargetTypeVideo = 0x02, 146 | QQApiURLTargetTypeNews = 0x03 147 | }; 148 | 149 | /** @brief URL对象类型。 150 | 151 | 包括URL地址,URL地址所指向的目标类型及预览图像。 152 | */ 153 | __attribute__((visibility("default"))) @interface QQApiURLObject : QQApiObject 154 | /** 155 | URL地址所指向的目标类型. 156 | @note 参见QQApi.h 中的 QQApiURLTargetType 定义. 157 | */ 158 | @property(nonatomic)QQApiURLTargetType targetContentType; 159 | 160 | @property(nonatomic,retain)NSURL* url; ///QQApiExtendObject对象 204 | @param data 数据内容 205 | @param previewImageData 用于预览的图片 206 | @param title 标题 207 | @param description 此对象,分享的描述 208 | @return 209 | 一个自动释放的QQApiExtendObject实例 210 | */ 211 | + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description; 212 | 213 | /** 214 | helper方法获取一个autorelease的QQApiExtendObject对象 215 | @param data 数据内容 216 | @param previewImageData 用于预览的图片 217 | @param title 标题 218 | @param description 此对象,分享的描述 219 | @param imageDataArray 发送的多张图片队列 220 | @return 221 | 一个自动释放的QQApiExtendObject实例 222 | */ 223 | + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description imageDataArray:(NSArray*)imageDataArray; 224 | 225 | @end 226 | 227 | // QQApiImageObject 228 | /** @brief 图片对象 229 | 用于分享图片内容的对象,是一个指定为图片类型的QQApiExtendObject 230 | */ 231 | @interface QQApiImageObject : QQApiExtendObject 232 | @end 233 | 234 | // QQApiImageForQQAvatarObject 235 | /** @brief 图片对象 236 | 用于设置QQ头像内容的对象,是一个指定为图片类型的QQApiExtendObject 237 | */ 238 | @interface QQApiImageForQQAvatarObject : QQApiExtendObject 239 | @end 240 | /** 241 | * @brief 视频对象 242 | * 用于设置动态头像 243 | * assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier 244 | 从手Q返回的错误码: 245 | //第三方设置动态头像结果 246 | @"ret=0"//设置成功 247 | @"ret=-10&error_des=user cancel"//用户取消设置 248 | @"ret=-11&error_des=pasteboard have no video data"//剪切板没有数据 249 | @"ret=-12&error_des=export data failed"//从剪切板导出数据到本地失败 250 | @"ret=-13&error_des=url param invalid"//sdk传递过来的数据有误 251 | @"ret=-14&error_des=video param invalid"//视频的参数不符合要求(检测第三方视频源方案:1、分辨率跟480*480保持一致;2、视频长度0.5s~8s) 252 | @"ret=-15&error_des=app authorised failed"//应用鉴权失败 253 | @"ret=-16&error_des=upload video failed"//设置头像,上传到后台失败 254 | @"ret=-17&error_des=account diff"//账号不一致 255 | */ 256 | @interface QQApiVideoForQQAvatarObject : QQApiExtendObject 257 | @property(nonatomic, retain) NSString *assetURL; 258 | @end 259 | 260 | // QQApiImageArrayForFaceCollectionObject 261 | /** @brief 图片数组对象 262 | 用于分享图片组到表情收藏,是一个指定为图片类型的QQApiObject 263 | */ 264 | @interface QQApiImageArrayForFaceCollectionObject : QQApiObject 265 | 266 | @property(nonatomic,retain) NSArray* imageDataArray;///图片数组 267 | 268 | /** 269 | 初始化方法 270 | @param imageDataArray 图片数组 271 | */ 272 | - (id)initWithImageArrayData:(NSArray*)imageDataArray; 273 | /** 274 | helper方法获取一个autorelease的QQApiObject对象 275 | @param imageDataArray 发送的多张图片队列 276 | @return 277 | 一个自动释放的QQApiObject实例 278 | */ 279 | + (id)objectWithimageDataArray:(NSArray *)imageDataArray; 280 | 281 | @end 282 | 283 | // QQApiImageArrayForQZoneObject 284 | /** @brief 图片对象 285 | 用于分享图片到空间,走写说说路径,是一个指定为图片类型的,当图片数组为空时,默认走文本写说说QQApiObject 286 | */ 287 | @interface QQApiImageArrayForQZoneObject : QQApiObject 288 | 289 | @property(nonatomic,retain) NSArray* imageDataArray;///图片数组 290 | @property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 291 | 292 | /** 293 | 初始化方法 294 | @param imageDataArray 图片数组 295 | @param title 写说说的内容,可以为空 296 | @param extMap 扩展字段 297 | */ 298 | - (id)initWithImageArrayData:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; 299 | 300 | /** 301 | helper方法获取一个autorelease的QQApiExtendObject对象 302 | @param title 写说说的内容,可以为空 303 | @param imageDataArray 发送的多张图片队列 304 | @param extMap 扩展字段 305 | @return 306 | 一个自动释放的QQApiExtendObject实例 307 | */ 308 | + (id)objectWithimageDataArray:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; 309 | 310 | @end 311 | 312 | // QQApiVideoForQZoneObject 313 | /** @brief 视频对象 314 | 用于分享视频到空间,走写说说路径QQApiObject,assetURL和videoData两个参数必须设置至少一个参数,如果assetURL设置了忽略videoData参数 315 | @param assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier 316 | @param extMap 扩展字段 317 | @param videoData 视频数据,大小不超过50M 318 | */ 319 | @interface QQApiVideoForQZoneObject : QQApiObject 320 | 321 | @property(nonatomic, retain) NSString *assetURL; 322 | @property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 323 | @property(nonatomic,retain) NSData* videoData; 324 | 325 | - (id)initWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; 326 | 327 | + (id)objectWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; 328 | 329 | - (id)initWithVideoData:(NSData*)videoData title:(NSString*)title extMap:(NSDictionary *)extMap; 330 | 331 | + (id)objectWithVideoData:(NSData*)videoData title:(NSString*)title extMap:(NSDictionary *)extMap; 332 | 333 | @end 334 | 335 | // QQApiWebImageObject 336 | /** @brief 图片对象 337 | 用于分享网络图片内容的对象,是一个指定网络图片url的: 该类型只在2.9.0的h5分享中才支持, 338 | 原有的手q分享是不支持该类型的。 339 | */ 340 | @interface QQApiWebImageObject : QQApiObject 341 | 342 | @property(nonatomic, retain) NSURL *previewImageURL; ///<预览图像URL 343 | 344 | /** 345 | 初始化方法 346 | @param previewImageURL 用于预览的图片 347 | @param title 标题 348 | @param description 此对象,分享的描述 349 | */ 350 | - (id)initWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; 351 | 352 | /** 353 | helper方法获取一个autorelease的QQApiWebImageObject对象 354 | @param previewImageURL 用于预览的图片 355 | @param title 标题 356 | @param description 此对象,分享的描述 357 | */ 358 | + (id)objectWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; 359 | 360 | @end 361 | 362 | 363 | //QQApiFileObject 364 | /** @brief 本地文件对象(暂只支持分享到手机QQ数据线功能) 365 | 用于分享文件内容的对象,是一个指定为文件类型的QQApiExtendObject 366 | */ 367 | @interface QQApiFileObject : QQApiExtendObject 368 | { 369 | NSString* _fileName; 370 | } 371 | @property(nonatomic, retain)NSString* fileName; 372 | @end 373 | 374 | // QQApiAudioObject 375 | /** @brief 音频URL对象 376 | 用于分享目标内容为音频的URL的对象 377 | */ 378 | @interface QQApiAudioObject : QQApiURLObject 379 | 380 | @property (nonatomic, retain) NSURL *flashURL; ///<音频URL地址,最长512个字符 381 | 382 | /** 383 | 获取一个autorelease的QQApiAudioObject 384 | @param url 音频内容的目标URL 385 | @param title 分享内容的标题 386 | @param description 分享内容的描述 387 | @param data 分享内容的预览图像 388 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 389 | */ 390 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 391 | 392 | /** 393 | 获取一个autorelease的QQApiAudioObject 394 | @param url 音频内容的目标URL 395 | @param title 分享内容的标题 396 | @param description 分享内容的描述 397 | @param previewURL 分享内容的预览图像URL 398 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 399 | */ 400 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 401 | 402 | @end 403 | 404 | // QQApiVideoObject 405 | /** @brief 视频URL对象 406 | 用于分享目标内容为视频的URL的对象 407 | 408 | QQApiVideoObject类型的分享,目前在Android和PC QQ上接收消息时,展现有待完善,待手机QQ版本以后更新支持 409 | 目前如果要分享视频,推荐使用 QQApiNewsObject 类型 410 | */ 411 | @interface QQApiVideoObject : QQApiURLObject 412 | 413 | @property (nonatomic, retain) NSURL *flashURL; ///<视频URL地址,最长512个字符 414 | 415 | /** 416 | 获取一个autorelease的QQApiVideoObject 417 | @param url 视频内容的目标URL 418 | @param title 分享内容的标题 419 | @param description 分享内容的描述 420 | @param data 分享内容的预览图像 421 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 422 | */ 423 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 424 | 425 | /** 426 | 获取一个autorelease的QQApiVideoObject 427 | @param url 视频内容的目标URL 428 | @param title 分享内容的标题 429 | @param description 分享内容的描述 430 | @param previewURL 分享内容的预览图像URL 431 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 432 | */ 433 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 434 | 435 | @end 436 | 437 | // QQApiNewsObject 438 | /** @brief 新闻URL对象 439 | 用于分享目标内容为新闻的URL的对象 440 | */ 441 | @interface QQApiNewsObject : QQApiURLObject 442 | /** 443 | 获取一个autorelease的QQApiNewsObject 444 | @param url 视频内容的目标URL 445 | @param title 分享内容的标题 446 | @param description 分享内容的描述 447 | @param data 分享内容的预览图像 448 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 449 | */ 450 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 451 | 452 | /** 453 | 获取一个autorelease的QQApiNewsObject 454 | @param url 视频内容的目标URL 455 | @param title 分享内容的标题 456 | @param description 分享内容的描述 457 | @param previewURL 分享内容的预览图像URL 458 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 459 | */ 460 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 461 | 462 | @end 463 | 464 | // QQApiCommonContentObject; 465 | /** @brief 通用模板类型对象 466 | 用于分享一个固定显示模板的图文混排对象 467 | @note 图片列表和文本列表不能同时为空 468 | */ 469 | @interface QQApiCommonContentObject : QQApiObject 470 | /** 471 | 预定义的界面布局类型 472 | */ 473 | @property(nonatomic,assign) unsigned int layoutType; 474 | @property(nonatomic,assign) NSData* previewImageData;///<预览图 475 | @property(nonatomic,retain) NSArray* textArray;///<文本列表 476 | @property(nonatomic,retain) NSArray* pictureDataArray;///<图片列表 477 | +(id)objectWithLayoutType:(int)layoutType textArray:(NSArray*)textArray pictureArray:(NSArray*)pictureArray previewImageData:(NSData*)data; 478 | /** 479 | 将一个NSDictionary对象转化为QQApiCommomContentObject,如果无法转换,则返回空 480 | */ 481 | +(id)objectWithDictionary:(NSDictionary*)dic; 482 | -(NSDictionary*)toDictionary; 483 | @end 484 | 485 | // QQApiExtraServiceObject; 486 | /** 487 | @brief OpenSDK扩展支持的服务,通用接口,后续会扩充能力 488 | @param serviceID [必选] 扩展支持的服务类型ID,参考官方文档说明 489 | @param openID [必选] 授权登录后对该用户的唯一标识 490 | @param toUin [可选] 对方的QQ号码 491 | @param extraInfo [可选] 扩展字段 492 | @note 该接口的使用须先登录 493 | */ 494 | @interface QQApiExtraServiceObject : QQApiObject 495 | @property (nonatomic,retain) NSString* serviceID; 496 | @property (nonatomic,retain) NSString* openID; 497 | @property (nonatomic,retain) NSString* toUin; 498 | @property (nonatomic,retain) NSDictionary* extraInfo; 499 | 500 | - (id)initWithOpenID:(NSString *)openID serviceID:(NSString *)serviceID; 501 | + (id)objecWithOpenID:(NSString *)openID serviceID:(NSString *)serviceID; 502 | @end 503 | 504 | 505 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 506 | // Ad item object definition 507 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 508 | /** @brief 广告数据对象 509 | */ 510 | @interface QQApiAdItem : NSObject 511 | @property(nonatomic,retain) NSString* title; ///<名称 512 | @property(nonatomic,retain) NSString* description;///<描述 513 | @property(nonatomic,retain) NSData* imageData;///<广告图片 514 | @property(nonatomic,retain) NSURL* target;///<广告目标链接 515 | @end 516 | 517 | 518 | #pragma mark - QQApi请求消息类型 519 | 520 | /** 521 | QQApi请求消息类型 522 | */ 523 | typedef NS_ENUM(NSUInteger, QQApiInterfaceReqType) { 524 | EGETMESSAGEFROMQQREQTYPE = 0, ///< 手Q -> 第三方应用,请求第三方应用向手Q发送消息 525 | ESENDMESSAGETOQQREQTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用向手Q分享消息 526 | ESHOWMESSAGEFROMQQREQTYPE = 2, ///< 手Q -> 第三方应用,请求第三方应用展现消息中的数据 527 | ESENDMESSAGEARKTOQQREQTYPE = 3, ///< 第三方应用 -> 手Q,第三方应用向手Q分享Ark消息 528 | ESENDMESSAGE_MINI_TOQQREQTYPE = 4 ///< 第三方应用 -> 手Q,第三方应用向手Q分享小程序消息 529 | }; 530 | 531 | /** 532 | QQApi应答消息类型 533 | */ 534 | typedef NS_ENUM(NSUInteger, QQApiInterfaceRespType) { 535 | ESHOWMESSAGEFROMQQRESPTYPE = 0, ///< 第三方应用 -> 手Q,第三方应用应答消息展现结果 536 | EGETMESSAGEFROMQQRESPTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用回应发往手Q的消息 537 | ESENDMESSAGETOQQRESPTYPE = 2 ///< 手Q -> 第三方应用,手Q应答处理分享消息的结果 538 | }; 539 | 540 | /** 541 | QQApi请求消息基类 542 | */ 543 | @interface QQBaseReq : NSObject 544 | 545 | /** 请求消息类型,参见\ref QQApiInterfaceReqType */ 546 | @property (nonatomic, assign) int type; 547 | 548 | @end 549 | 550 | /** 551 | QQApi应答消息基类 552 | */ 553 | @interface QQBaseResp : NSObject 554 | 555 | /** 请求处理结果 */ 556 | @property (nonatomic, copy) NSString* result; 557 | 558 | /** 具体错误描述信息 */ 559 | @property (nonatomic, copy) NSString* errorDescription; 560 | 561 | /** 应答消息类型,参见\ref QQApiInterfaceRespType */ 562 | @property (nonatomic, assign) int type; 563 | 564 | /** 扩展信息 */ 565 | @property (nonatomic, assign) NSString* extendInfo; 566 | 567 | @end 568 | 569 | /** 570 | GetMessageFromQQReq请求帮助类 571 | */ 572 | @interface GetMessageFromQQReq : QQBaseReq 573 | 574 | /** 575 | 创建一个GetMessageFromQQReq请求实例 576 | */ 577 | + (GetMessageFromQQReq *)req; 578 | 579 | @end 580 | 581 | @interface SendMessageToQQReq : QQBaseReq 582 | 583 | /** 584 | 创建一个SendMessageToQQReq请求实例 585 | \param message 具体分享消息实例 586 | \return 新创建的SendMessageToQQReq请求实例 587 | */ 588 | + (SendMessageToQQReq *)reqWithContent:(QQApiObject *)message; 589 | 590 | /** 591 | 创建一个支持Ark的SendMessageToQQReq请求实例 592 | \param message 具体分享消息实例 593 | \return 新创建的SendMessageToQQReq请求实例 594 | */ 595 | + (SendMessageToQQReq *)reqWithArkContent:(ArkObject *)message; 596 | /** 597 | * 创建一个支持小程序的消息请求实例 598 | * @param miniMessage 小程序实例对象 599 | * @return 消息请求实例 600 | */ 601 | +(SendMessageToQQReq*) reqWithMiniContent:(QQApiMiniProgramObject *)miniMessage; 602 | /** 具体分享消息 */ 603 | @property (nonatomic, retain) QQApiObject *message; 604 | 605 | /** 支持Ark的具体分享消息 */ 606 | @property (nonatomic, retain) ArkObject *arkMessage; 607 | /** 支持小程序的具体分享消息 */ 608 | @property (nonatomic, retain) QQApiMiniProgramObject *miniMessage; 609 | @end 610 | 611 | /** 612 | SendMessageToQQResp应答帮助类 613 | */ 614 | @interface SendMessageToQQResp : QQBaseResp 615 | 616 | /** 617 | 创建一个SendMessageToQQResp应答实例 618 | \param result 请求处理结果 619 | \param errDesp 具体错误描述信息 620 | \param extendInfo 扩展信息 621 | \return 新创建的SendMessageToQQResp应答实例 622 | */ 623 | + (SendMessageToQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp extendInfo:(NSString*)extendInfo; 624 | 625 | @end 626 | 627 | /** 628 | ShowMessageFromQQReq请求帮助类 629 | */ 630 | @interface ShowMessageFromQQReq : QQBaseReq 631 | 632 | /** 633 | 创建一个ShowMessageFromQQReq请求实例 634 | \param message 具体待展现消息实例 635 | \return 新创建的ShowMessageFromQQReq请求实例 636 | */ 637 | + (ShowMessageFromQQReq *)reqWithContent:(QQApiObject *)message; 638 | 639 | /** 具体待展现消息 */ 640 | @property (nonatomic, retain) QQApiObject *message; 641 | 642 | @end 643 | 644 | 645 | #endif 646 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/Headers/TencentOAuth.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file TencentOAuth.h 3 | /// \brief QQ互联开放平台授权登录及相关开放接口实现类 4 | /// 5 | /// Created by Tencent on 12-12-21. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import "sdkdef.h" 11 | 12 | @protocol TencentSessionDelegate; 13 | @protocol TencentLoginDelegate; 14 | @protocol TencentApiInterfaceDelegate; 15 | @protocol TencentWebViewDelegate; 16 | 17 | @class TencentApiReq; 18 | @class TencentApiResp; 19 | 20 | typedef NS_ENUM(NSUInteger, TencentAuthorizeState) { 21 | kTencentNotAuthorizeState, 22 | kTencentSSOAuthorizeState, 23 | kTencentWebviewAuthorzieState, 24 | }; 25 | 26 | typedef NS_ENUM(NSUInteger, TencentAuthMode) { 27 | kAuthModeClientSideToken, 28 | kAuthModeServerSideCode, 29 | }; 30 | 31 | #pragma mark - TencentOAuth(授权登录及相关开放接口调用) 32 | 33 | /** 34 | * \brief TencentOpenAPI授权登录及相关开放接口调用 35 | * 36 | * TencentOAuth实现授权登录逻辑以及相关开放接口的请求调用 37 | */ 38 | @interface TencentOAuth : NSObject 39 | { 40 | NSMutableDictionary* _apiRequests; 41 | NSString* _accessToken; 42 | NSDate* _expirationDate; 43 | id _sessionDelegate; 44 | NSString* _localAppId; 45 | NSString* _openId; 46 | NSString* _redirectURI; 47 | NSArray* _permissions; 48 | } 49 | 50 | /** Access Token凭证,用于后续访问各开放接口 */ 51 | @property(nonatomic, copy) NSString* accessToken; 52 | 53 | /** Access Token的失效期 */ 54 | @property(nonatomic, copy) NSDate* expirationDate; 55 | 56 | /** 已实现的开放接口的回调委托对象 */ 57 | @property(nonatomic, assign) id sessionDelegate; 58 | 59 | /** 第三方应用在开发过程中设置的URLSchema,用于浏览器登录后后跳到第三方应用 */ 60 | @property(nonatomic, copy) NSString* localAppId; 61 | 62 | /** 用户授权登录后对该用户的唯一标识 */ 63 | @property(nonatomic, copy) NSString* openId; 64 | 65 | /** 用户登录成功过后的跳转页面地址 */ 66 | @property(nonatomic, copy) NSString* redirectURI; 67 | 68 | /** 第三方应用在互联开放平台申请的appID */ 69 | @property(nonatomic, retain) NSString* appId; 70 | 71 | /** 第三方应用在互联开放平台注册的UniversalLink */ 72 | @property(nonatomic, retain) NSString* universalLink; 73 | 74 | /** 主要是互娱的游戏设置uin */ 75 | @property(nonatomic, retain) NSString* uin; 76 | 77 | /** 主要是互娱的游戏设置鉴定票据 */ 78 | @property(nonatomic, retain) NSString* skey; 79 | 80 | /** 登陆透传的数据 */ 81 | @property(nonatomic, copy) NSDictionary* passData; 82 | 83 | /** 授权方式(Client Side Token或者Server Side Code) */ 84 | @property(nonatomic, assign) TencentAuthMode authMode; 85 | 86 | /** union id */ 87 | @property(nonatomic, retain) NSString* unionid; 88 | 89 | /** 第三方在授权登录/分享 时选择 QQ,还是TIM 。在授权前一定要指定其中一个类型*/ 90 | @property(nonatomic, assign) TencentAuthShareType authShareType; 91 | 92 | /** 93 | * 获取上次登录得到的token 94 | * 95 | **/ 96 | - (NSString *)getCachedToken; 97 | 98 | /** 99 | * 获取上次登录得到的openid 100 | * 101 | **/ 102 | - (NSString *)getCachedOpenID; 103 | 104 | /** 105 | * 获取上次登录的token过期日期 106 | * 107 | **/ 108 | - (NSDate *)getCachedExpirationDate; 109 | 110 | /** 111 | * 上次登录的token是否过期(本地判断) 112 | **/ 113 | - (BOOL)isCachedTokenValid; 114 | 115 | /** 116 | * 删除上次登录登录的token信息 117 | * 118 | **/ 119 | - (BOOL)deleteCachedToken; 120 | 121 | /** 122 | * 用来获得当前sdk的版本号 123 | * \return 返回sdk版本号 124 | **/ 125 | 126 | + (NSString*)sdkVersion; 127 | 128 | /** 129 | * 用来获得当前sdk的小版本号 130 | * \return 返回sdk小版本号 131 | **/ 132 | 133 | + (NSString*)sdkSubVersion; 134 | 135 | /** 136 | * 用来获得当前sdk的是否精简版 137 | * \return 返回YES表示精简版 138 | **/ 139 | 140 | + (BOOL)isLiteSDK; 141 | 142 | /** 143 | * 主要是用来帮助判断是否有登陆被发起,但是还没有过返回结果 144 | * \return 145 | * kTencentNotAuthorizeState:无授权 146 | * kTencentSSOAuthorizeState:有人发起了sso授权但无返回 147 | * kTencentWebviewAuthorzieState:有人发起了webview授权还未返回 148 | **/ 149 | 150 | + (TencentAuthorizeState *)authorizeState; 151 | 152 | /** 153 | * 用来获得当前手机qq的版本号 154 | * \return 返回手机qq版本号 155 | **/ 156 | + (int)iphoneQQVersion __attribute__((deprecated("已过期, 建议删除调用"))); 157 | 158 | 159 | /** 160 | * 用来获得当前手机TIM的版本号 161 | * \return 返回手机qq版本号 162 | **/ 163 | + (int)iphoneTIMVersion __attribute__((deprecated("已过期, 建议删除调用"))); 164 | 165 | /** 166 | * 初始化TencentOAuth对象 167 | * \param appId 第三方应用在互联开放平台申请的唯一标识 168 | * \param delegate 第三方应用用于接收请求返回结果的委托对象 169 | * \return 初始化后的授权登录对象 170 | */ 171 | - (id)initWithAppId:(NSString *)appId 172 | andDelegate:(id)delegate; 173 | 174 | /** 175 | * 初始化TencentOAuth对象(>=3.3.7) 176 | * \param appId 第三方应用在互联开放平台申请的唯一标识 177 | * \param universalLink 第三方应用在互联开放平台注册的universallink,和bundleID一一对应 178 | * \param delegate 第三方应用用于接收请求返回结果的委托对象 179 | * \return 初始化后的授权登录对象 180 | */ 181 | - (id)initWithAppId:(NSString *)appId 182 | andUniversalLink:(NSString *)universalLink 183 | andDelegate:(id)delegate; 184 | 185 | /** 186 | * 判断用户手机上是否安装手机QQ 187 | * \return YES:安装 NO:没安装 188 | * 189 | * \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 190 | * 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 191 | * 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 192 | */ 193 | + (BOOL)iphoneQQInstalled; 194 | 195 | /** 196 | * 判断用户手机上是否安装手机TIM 197 | * \return YES:安装 NO:没安装 198 | * 199 | * \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 200 | * 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 201 | * 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 202 | */ 203 | + (BOOL)iphoneTIMInstalled; 204 | 205 | /** 206 | * 判断用户手机上的手机QQ是否支持SSO登录 207 | * \return YES:支持 NO:不支持 208 | */ 209 | + (BOOL)iphoneQQSupportSSOLogin __attribute__((deprecated("QQ版本均支持SSO登录。该接口已过期, 建议删除调用"))); 210 | 211 | /** 212 | * 判断用户手机上的手机TIM是否支持SSO登录 213 | * \return YES:支持 NO:不支持 214 | */ 215 | + (BOOL)iphoneTIMSupportSSOLogin __attribute__((deprecated("TIM版本均支持SSO登录。该接口已过期, 建议删除调用"))); 216 | 217 | /** 218 | * 登录授权 219 | * 220 | * \param permissions 授权信息列 221 | */ 222 | - (BOOL)authorize:(NSArray *)permissions; 223 | 224 | /** 225 | * 登录授权 226 | * \param permissions 授权信息列表 227 | * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 228 | */ 229 | - (BOOL)authorize:(NSArray *)permissions 230 | inSafari:(BOOL)bInSafari; 231 | 232 | /** 233 | * 登录授权 234 | * \param permissions 授权信息列表 235 | * \param localAppId 应用APPID 236 | * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 237 | */ 238 | - (BOOL)authorize:(NSArray *)permissions 239 | localAppId:(NSString *)localAppId 240 | inSafari:(BOOL)bInSafari; 241 | 242 | /** 243 | * 登录授权 244 | * 245 | * \param permissions 授权信息列 246 | */ 247 | - (BOOL)authorizeWithQRlogin:(NSArray *)permissions; 248 | 249 | /** 250 | * 增量授权,因用户没有授予相应接口调用的权限,需要用户确认是否授权 251 | * \param permissions 需增量授权的信息列表 252 | * \return 增量授权调用是否成功 253 | */ 254 | - (BOOL)incrAuthWithPermissions:(NSArray *)permissions; 255 | 256 | /** 257 | * 重新授权,因token废除或失效导致接口调用失败,需用户重新授权 258 | * \param permissions 授权信息列表,同登录授权 259 | * \return 授权调用是否成功 260 | */ 261 | - (BOOL)reauthorizeWithPermissions:(NSArray *)permissions; 262 | 263 | /** 264 | * 获取UnindID,可以根据UnindID的比较来确定OpenID是否属于同一个用户 265 | * \return NO未登录,信息不足;YES条件满足,发送请求成功,请等待回调 266 | */ 267 | - (BOOL)RequestUnionId; 268 | 269 | /** 270 | * (静态方法)处理应用拉起协议 271 | * \param url 处理被其他应用呼起时的逻辑 272 | * \return 处理结果,YES表示成功,NO表示失败 273 | */ 274 | + (BOOL)HandleOpenURL:(NSURL *)url; 275 | 276 | /** 277 | * (静态方法)sdk是否可以处理应用拉起协议 278 | * \param url 处理被其他应用呼起时的逻辑 279 | * \return 处理结果,YES表示可以 NO表示不行 280 | */ 281 | + (BOOL)CanHandleOpenURL:(NSURL *)url; 282 | 283 | /** 284 | * (静态方法)处理应用的UniversalLink拉起协议 285 | * \param url 处理被其他应用呼起时的逻辑 286 | * \return 处理结果,YES表示成功,NO表示失败 287 | */ 288 | + (BOOL)HandleUniversalLink:(NSURL *)url; 289 | 290 | /** 291 | * (静态方法)sdk是否可以处理应用的Universallink拉起协议 292 | * \param url 处理被其他应用呼起时的逻辑(应用的Universallink链接须满足官网注册时的格式要求) 293 | * \return 处理结果,YES表示可以 NO表示不行 294 | * 注:在调用其他Universallink相关处理接口之前,均需进行此项判断 295 | */ 296 | + (BOOL)CanHandleUniversalLink:(NSURL *)url; 297 | 298 | /** 299 | * (静态方法)获取TencentOAuth调用的上一次错误信息 300 | */ 301 | + (NSString *)getLastErrorMsg; 302 | 303 | /** 304 | * 以Server Side Code模式授权登录时,通过此接口获取返回的code值; 305 | * 以Client Side Token模式授权登录时,忽略此接口。 306 | */ 307 | - (NSString *)getServerSideCode; 308 | 309 | /** 310 | * 退出登录(退出登录后,TecentOAuth失效,需要重新初始化) 311 | * \param delegate 第三方应用用于接收请求返回结果的委托对象 312 | */ 313 | - (void)logout:(id)delegate; 314 | 315 | /** 316 | * 判断登录态是否有效 317 | * \return 处理结果,YES表示有效,NO表示无效,请用户重新登录授权 318 | */ 319 | - (BOOL)isSessionValid; 320 | 321 | /** 322 | * 获取用户个人信息 323 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 324 | */ 325 | - (BOOL)getUserInfo; 326 | 327 | /** 328 | * 退出指定API调用 329 | * \param userData 用户调用某条API的时候传入的保留参数 330 | * \return 处理结果,YES表示成功 NO表示失败 331 | */ 332 | - (BOOL)cancel:(id)userData; 333 | 334 | /** 335 | * CGI类任务创建接口 336 | * \param apiURL CGI请求的URL地址 337 | * \param method CGI请求方式:"GET","POST" 338 | * \param params CGI请求参数字典 339 | * \param callback CGI请求结果的回调接口对象 340 | * \return CGI请求任务实例,用于取消任务,返回nil代表任务创建失败 341 | */ 342 | - (TCAPIRequest *)cgiRequestWithURL:(NSURL *)apiURL method:(NSString *)method params:(NSDictionary *)params callback:(id)callback; 343 | 344 | /** 345 | * TencentOpenApi发送任务统一接口 346 | * \param request 请求发送的任务 347 | * \param callback 任务发送后的回调地址 348 | */ 349 | - (BOOL)sendAPIRequest:(TCAPIRequest *)request callback:(id)callback; 350 | 351 | - (NSString *)getUserOpenID; 352 | 353 | @end 354 | 355 | #pragma mark - TencentLoginDelegate(授权登录回调协议) 356 | 357 | /** 358 | * \brief TencentLoginDelegate iOS Open SDK 1.3 API回调协议 359 | * 360 | * 第三方应用实现登录的回调协议 361 | */ 362 | @protocol TencentLoginDelegate 363 | 364 | @required 365 | 366 | /** 367 | * 登录成功后的回调 368 | */ 369 | - (void)tencentDidLogin; 370 | 371 | /** 372 | * 登录失败后的回调 373 | * \param cancelled 代表用户是否主动退出登录 374 | */ 375 | - (void)tencentDidNotLogin:(BOOL)cancelled; 376 | 377 | /** 378 | * 登录时网络有问题的回调 379 | */ 380 | - (void)tencentDidNotNetWork; 381 | 382 | @optional 383 | /** 384 | * 登录时权限信息的获得 385 | */ 386 | - (NSArray *)getAuthorizedPermissions:(NSArray *)permissions withExtraParams:(NSDictionary *)extraParams; 387 | 388 | /** 389 | * unionID获得 390 | */ 391 | - (void)didGetUnionID; 392 | 393 | /** 394 | * 强制网页登录,包括账号密码登录和二维码登录 395 | * return YES时,就算本地有手Q也会打开web界面 396 | */ 397 | - (BOOL)forceWebLogin; 398 | @end 399 | 400 | #pragma mark - TencentSessionDelegate(开放接口回调协议) 401 | 402 | /** 403 | * \brief TencentSessionDelegate iOS Open SDK 1.3 API回调协议 404 | * 405 | * 第三方应用需要实现每条需要调用的API的回调协议 406 | */ 407 | @protocol TencentSessionDelegate 409 | 410 | @optional 411 | 412 | /** 413 | * 退出登录的回调 414 | */ 415 | - (void)tencentDidLogout; 416 | 417 | /** 418 | * 因用户未授予相应权限而需要执行增量授权。在用户调用某个api接口时,如果服务器返回操作未被授权,则触发该回调协议接口,由第三方决定是否跳转到增量授权页面,让用户重新授权。 419 | * \param tencentOAuth 登录授权对象。 420 | * \param permissions 需增量授权的权限列表。 421 | * \return 是否仍然回调返回原始的api请求结果。 422 | * \note 不实现该协议接口则默认为不开启增量授权流程。若需要增量授权请调用\ref TencentOAuth#incrAuthWithPermissions: \n注意:增量授权时用户可能会修改登录的帐号 423 | */ 424 | - (BOOL)tencentNeedPerformIncrAuth:(TencentOAuth *)tencentOAuth withPermissions:(NSArray *)permissions; 425 | 426 | /** 427 | * [该逻辑未实现]因token失效而需要执行重新登录授权。在用户调用某个api接口时,如果服务器返回token失效,则触发该回调协议接口,由第三方决定是否跳转到登录授权页面,让用户重新授权。 428 | * \param tencentOAuth 登录授权对象。 429 | * \return 是否仍然回调返回原始的api请求结果。 430 | * \note 不实现该协议接口则默认为不开启重新登录授权流程。若需要重新登录授权请调用\ref TencentOAuth#reauthorizeWithPermissions: \n注意:重新登录授权时用户可能会修改登录的帐号 431 | */ 432 | - (BOOL)tencentNeedPerformReAuth:(TencentOAuth *)tencentOAuth; 433 | 434 | /** 435 | * 用户通过增量授权流程重新授权登录,token及有效期限等信息已被更新。 436 | * \param tencentOAuth token及有效期限等信息更新后的授权实例对象 437 | * \note 第三方应用需更新已保存的token及有效期限等信息。 438 | */ 439 | - (void)tencentDidUpdate:(TencentOAuth *)tencentOAuth; 440 | 441 | /** 442 | * 用户增量授权过程中因取消或网络问题导致授权失败 443 | * \param reason 授权失败原因,具体失败原因参见sdkdef.h文件中\ref UpdateFailType 444 | */ 445 | - (void)tencentFailedUpdate:(UpdateFailType)reason; 446 | 447 | /** 448 | * 获取用户个人信息回调 449 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 450 | * \remarks 正确返回示例: \snippet example/getUserInfoResponse.exp success 451 | * 错误返回示例: \snippet example/getUserInfoResponse.exp fail 452 | */ 453 | - (void)getUserInfoResponse:(APIResponse*) response; 454 | 455 | /** 456 | * 社交API统一回调接口 457 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 458 | * \param message 响应的消息,目前支持‘SendStory’,‘AppInvitation’,‘AppChallenge’,‘AppGiftRequest’ 459 | */ 460 | - (void)responseDidReceived:(APIResponse*)response forMessage:(NSString *)message; 461 | 462 | /** 463 | * post请求的上传进度 464 | * \param tencentOAuth 返回回调的tencentOAuth对象 465 | * \param bytesWritten 本次回调上传的数据字节数 466 | * \param totalBytesWritten 总共已经上传的字节数 467 | * \param totalBytesExpectedToWrite 总共需要上传的字节数 468 | * \param userData 用户自定义数据 469 | */ 470 | - (void)tencentOAuth:(TencentOAuth *)tencentOAuth didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite userData:(id)userData; 471 | 472 | 473 | /** 474 | * 通知第三方界面需要被关闭 475 | * \param tencentOAuth 返回回调的tencentOAuth对象 476 | * \param viewController 需要关闭的viewController 477 | */ 478 | - (void)tencentOAuth:(TencentOAuth *)tencentOAuth doCloseViewController:(UIViewController *)viewController; 479 | 480 | @end 481 | 482 | #pragma mark - TencentWebViewDelegate(H5登录webview旋转方向回调) 483 | 484 | /** 485 | * \brief TencentWebViewDelegate: H5登录webview旋转方向回调协议 486 | * 487 | * 第三方应用可以根据自己APP的旋转方向限制,通过此协议设置 488 | */ 489 | @protocol TencentWebViewDelegate 490 | @optional 491 | - (BOOL) tencentWebViewShouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; 492 | - (NSUInteger) tencentWebViewSupportedInterfaceOrientationsWithWebkit; 493 | - (BOOL) tencentWebViewShouldAutorotateWithWebkit; 494 | @end 495 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/Headers/sdkdef.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file sdkdef.h 3 | /// \brief SDK中相关常量定义 4 | /// 5 | /// Created by Tencent on 12-12-25. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import 11 | 12 | /** 13 | * \brief 设置sdk的log等级 14 | */ 15 | typedef enum { 16 | TCOLogLevel_Disabled = -1, // 关闭所有log 17 | TCOLogLevel_Error = 0, 18 | TCOLogLevel_Warning, 19 | TCOLogLevel_Info, 20 | TCOLogLevel_Debug, 21 | } TCOLogLevel; 22 | 23 | /** 24 | * \breif 授权/分享 方式 25 | */ 26 | typedef enum TencentAuthShareType { 27 | AuthShareType_QQ, 28 | AuthShareType_TIM, 29 | }TencentAuthShareType; 30 | 31 | /** 32 | * \brief APIResponse.retCode可能的枚举常量 33 | */ 34 | typedef enum 35 | { 36 | URLREQUEST_SUCCEED = 0, /**< 网络请求成功发送至服务器,并且服务器返回数据格式正确 37 | * \note 这里包括所请求业务操作失败的情况,例如没有授权等原因导致 38 | */ 39 | 40 | URLREQUEST_FAILED = 1, /**< 网络异常,或服务器返回的数据格式不正确导致无法解析 */ 41 | } REPONSE_RESULT; 42 | 43 | /** 44 | * \brief 增量授权失败原因 45 | * 46 | * \note 增量授权失败不影响原token的有效性(原token已失效的情况除外) 47 | */ 48 | typedef enum 49 | { 50 | kUpdateFailUnknown = 1, ///< 未知原因 51 | kUpdateFailUserCancel, ///< 用户取消 52 | kUpdateFailNetwork, ///< 网络问题 53 | } UpdateFailType; 54 | 55 | /** 56 | * \brief 封装服务器返回的结果 57 | * 58 | * APIResponse用于封装所有请求的返回结果,包括错误码、错误信息、原始返回数据以及返回数据的json格式字典 59 | */ 60 | @interface APIResponse : NSObject { 61 | int _detailRetCode; 62 | int _retCode; 63 | int _seq; 64 | NSString *_errorMsg; 65 | NSDictionary *_jsonResponse; 66 | NSString *_message; 67 | id _userData; 68 | } 69 | 70 | /** 71 | * 新增的详细错误码\n 72 | * detailRetCode主要用于区分不同的错误情况,参见\ref OpenSDKError 73 | */ 74 | @property (nonatomic, assign) int detailRetCode; 75 | 76 | /** 77 | * 网络请求是否成功送达服务器,以及服务器返回的数据格式是否正确\n 78 | * retCode具体取值可参考\ref REPONSE_RESULT 79 | */ 80 | @property (nonatomic, assign) int retCode; 81 | 82 | /** 83 | * 网络请求对应的递增序列号,方便内部管理 84 | */ 85 | @property (nonatomic, assign) int seq; 86 | 87 | /** 88 | * 错误提示语 89 | */ 90 | @property (nonatomic, retain) NSString *errorMsg; 91 | 92 | /** 93 | * 服务器返回数据的json格式字典\n 94 | * 字典内具体参数的命名和含义请参考\ref api_spec 95 | */ 96 | @property (nonatomic, retain) NSDictionary *jsonResponse; 97 | 98 | /** 99 | * 服务器返回的原始数据字符串 100 | */ 101 | @property (nonatomic, retain) NSString *message; 102 | 103 | /** 104 | * 用户保留数据 105 | */ 106 | @property (nonatomic, retain) id userData; 107 | 108 | @end 109 | 110 | 111 | /** 112 | * 用户自定义的保留字段 113 | */ 114 | FOUNDATION_EXTERN NSString * const PARAM_USER_DATA; 115 | 116 | /** 117 | * \name 应用邀请参数字段定义 118 | */ 119 | ///@{ 120 | 121 | /** 应用邀请展示图片url的key */ 122 | FOUNDATION_EXTERN NSString * const PARAM_APP_ICON; 123 | 124 | /** 应用邀请描述文本的key */ 125 | FOUNDATION_EXTERN NSString * const PARAM_APP_DESC; 126 | 127 | /** 应用邀请好友列表的key */ 128 | FOUNDATION_EXTERN NSString * const PARAM_APP_INVITED_OPENIDS; 129 | 130 | ///@} 131 | 132 | /** 133 | * \name sendStory新分享参数字段定义 134 | */ 135 | ///@{ 136 | 137 | /** 预填入接受人列表的key */ 138 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_RECEIVER; 139 | 140 | /** 分享feeds标题的key */ 141 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_TITLE; 142 | 143 | /** 分享feeds评论内容的key */ 144 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_COMMENT; 145 | 146 | /** 分享feeds摘要的key */ 147 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_SUMMARY; 148 | 149 | /** 分享feeds展示图片url的key */ 150 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_IMAGE; 151 | 152 | /** 分享feeds跳转链接url的key */ 153 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_URL; 154 | 155 | /** 分享feeds点击操作默认行为的key */ 156 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_ACT; 157 | 158 | ///@} 159 | 160 | /** 161 | * \name 设置头像参数字段定义 162 | */ 163 | ///@{ 164 | 165 | /** 头像图片数据的key */ 166 | FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_PIC; 167 | 168 | /** 头像图片文件名的key */ 169 | FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_FILENAME; 170 | 171 | ///@} 172 | 173 | /** 174 | * \name 服务器返回数据的参数字段定义 175 | */ 176 | ///@{ 177 | 178 | /** 服务器返回码的key */ 179 | FOUNDATION_EXTERN NSString * const PARAM_RETCODE; 180 | 181 | /** 服务器返回错误信息的key */ 182 | FOUNDATION_EXTERN NSString * const PARAM_MESSAGE; 183 | 184 | /** 服务器返回额外数据的key */ 185 | FOUNDATION_EXTERN NSString * const PARAM_DATA; 186 | 187 | ///@} 188 | 189 | /** 190 | * \name 错误信息相关常量定义 191 | */ 192 | ///@{ 193 | 194 | /** 详细错误信息字典中额外信息的key */ 195 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyExtraInfo; 196 | 197 | /** 详细错误信息字典中返回码的key */ 198 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyRetCode; 199 | 200 | /** 详细错误信息字典中错误语句的key */ 201 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyMsg; 202 | 203 | /** 不支持的接口 */ 204 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnsupportedAPI; 205 | 206 | /** 操作成功 */ 207 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSuccess; 208 | 209 | /** 未知错误 */ 210 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnknown; 211 | 212 | /** 用户取消 */ 213 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserCancel; 214 | 215 | /** 请重新登录 */ 216 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgReLogin; 217 | 218 | /** 应用没有操作权限 */ 219 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgOperationDeny; 220 | 221 | /** 网络异常或没有网络 */ 222 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgNetwork; 223 | 224 | /** URL格式或协议错误 */ 225 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgURL; 226 | 227 | /** 解析数据出错 */ 228 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgDataParse; 229 | 230 | /** 传入参数有误 */ 231 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgParam; 232 | 233 | /** 连接超时 */ 234 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgTimeout; 235 | 236 | /** 安全问题 */ 237 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSecurity; 238 | 239 | /** 文件读写错误 */ 240 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgIO; 241 | 242 | /** 服务器端错误 */ 243 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgServer; 244 | 245 | /** 页面错误 */ 246 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgWebPage; 247 | 248 | /** 设置头像图片过大 */ 249 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserHeadPicLarge; 250 | 251 | ///@} 252 | 253 | /** 254 | * \brief SDK新增详细错误常量 255 | */ 256 | typedef enum 257 | { 258 | kOpenSDKInvalid = -1, ///< 无效的错误码 259 | kOpenSDKErrorUnsupportedAPI = -2, ///< 不支持的接口 260 | 261 | /** 262 | * \name CommonErrorCode 263 | * 公共错误码 264 | */ 265 | ///@{ 266 | kOpenSDKErrorSuccess = 0, ///< 成功 267 | kOpenSDKErrorUnknown, ///< 未知错误 268 | kOpenSDKErrorUserCancel, ///< 用户取消 269 | kOpenSDKErrorReLogin, ///< token无效或用户未授权相应权限需要重新登录 270 | kOpenSDKErrorOperationDeny, ///< 第三方应用没有该api操作的权限 271 | ///@} 272 | 273 | /** 274 | * \name NetworkRelatedErrorCode 275 | * 网络相关错误码 276 | */ 277 | ///@{ 278 | kOpenSDKErrorNetwork, ///< 网络错误,网络不通或连接不到服务器 279 | kOpenSDKErrorURL, ///< URL格式或协议错误 280 | kOpenSDKErrorDataParse, ///< 数据解析错误,服务器返回的数据解析出错 281 | kOpenSDKErrorParam, ///< 传入参数错误 282 | kOpenSDKErrorConnTimeout, ///< http连接超时 283 | kOpenSDKErrorSecurity, ///< 安全问题 284 | kOpenSDKErrorIO, ///< 下载和文件IO错误 285 | kOpenSDKErrorServer, ///< 服务器端错误 286 | ///@} 287 | 288 | /** 289 | * \name WebViewRelatedError 290 | * webview特有错误 291 | */ 292 | ///@{ 293 | kOpenSDKErrorWebPage, ///< 页面错误 294 | ///@} 295 | 296 | /** 297 | * \name SetUserHeadRelatedErrorCode 298 | * 设置头像自定义错误码段 299 | */ 300 | ///@{ 301 | kOpenSDKErrorUserHeadPicLarge = 0x010000, ///< 图片过大 设置头像自定义错误码 302 | ///@} 303 | } OpenSDKError; 304 | 305 | /** 306 | * \name SDK版本(v1.3)支持的授权列表常量 307 | */ 308 | ///@{ 309 | 310 | /** 发表一条说说到QQ空间(需要申请权限) */ 311 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_TOPIC; 312 | 313 | /** 创建一个QQ空间相册(需要申请权限) */ 314 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ALBUM; 315 | 316 | /** 上传一张照片到QQ空间相册(需要申请权限) */ 317 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_UPLOAD_PIC; 318 | 319 | /** 获取用户QQ空间相册列表(需要申请权限) */ 320 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_LIST_ALBUM; 321 | 322 | /** 验证是否认证空间粉丝 */ 323 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_CHECK_PAGE_FANS; 324 | 325 | /** 获取登录用户自己的详细信息 */ 326 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_INFO; 327 | 328 | /** 获取其他用户的详细信息 */ 329 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_OTHER_INFO; 330 | 331 | /** 获取会员用户基本信息 */ 332 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_INFO; 333 | 334 | /** 获取会员用户详细信息 */ 335 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_RICH_INFO; 336 | 337 | /** 获取用户信息 */ 338 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_USER_INFO; 339 | 340 | /** 移动端获取用户信息 */ 341 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_SIMPLE_USER_INFO; 342 | ///@} 343 | 344 | 345 | /** 346 | * \name CGI接口相关参数类型定义 347 | */ 348 | 349 | /** 必填的字符串类型参数 */ 350 | typedef NSString *TCRequiredStr; 351 | 352 | /** 必填的UIImage类型参数 */ 353 | typedef UIImage *TCRequiredImage; 354 | 355 | /** 必填的整型参数 */ 356 | typedef NSInteger TCRequiredInt; 357 | 358 | /** 必填的数字类型 */ 359 | typedef NSNumber *TCRequiredNumber; 360 | 361 | /** 必填的NSData参数 */ 362 | typedef NSData *TCRequiredData; 363 | 364 | /** 可选的字符串类型参数 */ 365 | typedef NSString *TCOptionalStr; 366 | 367 | /** 可选的UIImage类型参数 */ 368 | typedef UIImage *TCOptionalImage; 369 | 370 | /** 可选的整型参数 */ 371 | typedef NSInteger TCOptionalInt; 372 | 373 | /** 可选的数字类型 */ 374 | typedef NSNumber *TCOptionalNumber; 375 | 376 | /** 可选的不定类型参数 */ 377 | typedef id TCRequiredId; 378 | ///@} 379 | 380 | 381 | /** 382 | * \brief CGI请求的参数字典封装辅助基类 383 | * 384 | * 将相应属性的值以key-value的形式保存到参数字典中 385 | */ 386 | @interface TCAPIRequest : NSMutableDictionary 387 | 388 | /** CGI请求的URL地址 */ 389 | @property (nonatomic, readonly) NSURL *apiURL; 390 | 391 | /** CGI请求方式:"GET","POST" */ 392 | @property (nonatomic, readonly) NSString *method; 393 | 394 | /** 395 | * API参数中的保留字段,可以塞入任意字典支持的类型,再调用完成后会带回给调用方 396 | */ 397 | @property (nonatomic, retain) TCRequiredId paramUserData; 398 | 399 | /** 400 | * APIResponse,API的返回结果 401 | */ 402 | @property (nonatomic, readonly) APIResponse *response; 403 | 404 | /** 取消相应的CGI请求任务 */ 405 | - (void)cancel; 406 | 407 | @end 408 | 409 | @protocol TCAPIRequestDelegate 410 | @optional 411 | - (void)cgiRequest:(TCAPIRequest *)request didResponse:(APIResponse *)response; 412 | 413 | @end 414 | 415 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/TencentOpenAPI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liujunliuhong/YHThirdManager/9b0fc0c38ec0cdf67caa7b5e1d6447933a9c18ac/YHThirdManager/ThirdParty/QQ/TencentOpenAPI.framework/TencentOpenAPI -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/WeiXin/WXApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // WXApi.h 3 | // 所有Api接口 4 | // 5 | // Created by Wechat on 12-2-28. 6 | // Copyright (c) 2012年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WXApiObject.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | #pragma mark - WXApiDelegate 15 | /*! @brief 接收并处理来自微信终端程序的事件消息 16 | * 17 | * 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。 18 | * WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。 19 | */ 20 | @protocol WXApiDelegate 21 | @optional 22 | 23 | /*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果 24 | * 25 | * 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。 26 | * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。 27 | * @param req 具体请求内容,是自动释放的 28 | */ 29 | - (void)onReq:(BaseReq*)req; 30 | 31 | 32 | 33 | /*! @brief 发送一个sendReq后,收到微信的回应 34 | * 35 | * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。 36 | * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。 37 | * @param resp具体的回应内容,是自动释放的 38 | */ 39 | - (void)onResp:(BaseResp*)resp; 40 | 41 | @end 42 | 43 | #pragma mark - WXApiLogDelegate 44 | 45 | @protocol WXApiLogDelegate 46 | 47 | - (void)onLog:(NSString*)log logLevel:(WXLogLevel)level; 48 | 49 | @end 50 | 51 | #pragma mark - WXApi 52 | 53 | /*! @brief 微信Api接口函数类 54 | * 55 | * 该类封装了微信终端SDK的所有接口 56 | */ 57 | @interface WXApi : NSObject 58 | 59 | /*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。 60 | * 61 | * 需要在每次启动第三方应用程序时调用。 62 | * @attention 请保证在主线程中调用此函数 63 | * @param appid 微信开发者ID 64 | * @param universalLink 微信开发者Universal Link 65 | * @return 成功返回YES,失败返回NO。 66 | */ 67 | + (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink; 68 | 69 | 70 | /*! @brief 处理旧版微信通过URL启动App时传递的数据 71 | * 72 | * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。 73 | * @param url 微信启动第三方应用时传递过来的URL 74 | * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 75 | * @return 成功返回YES,失败返回NO。 76 | */ 77 | + (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id)delegate; 78 | 79 | 80 | /*! @brief 处理微信通过Universal Link启动App时传递的数据 81 | * 82 | * 需要在 application:continueUserActivity:restorationHandler:中调用。 83 | * @param userActivity 微信启动第三方应用时系统API传递过来的userActivity 84 | * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 85 | * @return 成功返回YES,失败返回NO。 86 | */ 87 | + (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id)delegate; 88 | 89 | 90 | /*! @brief 检查微信是否已被用户安装 91 | * 92 | * @return 微信已安装返回YES,未安装返回NO。 93 | */ 94 | + (BOOL)isWXAppInstalled; 95 | 96 | 97 | 98 | /*! @brief 判断当前微信的版本是否支持OpenApi 99 | * 100 | * @return 支持返回YES,不支持返回NO。 101 | */ 102 | + (BOOL)isWXAppSupportApi; 103 | 104 | 105 | 106 | /*! @brief 获取微信的itunes安装地址 107 | * 108 | * @return 微信的安装地址字符串。 109 | */ 110 | + (NSString *)getWXAppInstallUrl; 111 | 112 | 113 | 114 | /*! @brief 获取当前微信SDK的版本号 115 | * 116 | * @return 返回当前微信SDK的版本号 117 | */ 118 | + (NSString *)getApiVersion; 119 | 120 | 121 | 122 | /*! @brief 打开微信 123 | * 124 | * @return 成功返回YES,失败返回NO。 125 | */ 126 | + (BOOL)openWXApp; 127 | 128 | 129 | 130 | /*! @brief 发送请求到微信,等待微信返回onResp 131 | * 132 | * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型 133 | * SendAuthReq、SendMessageToWXReq、PayReq等。 134 | * @param req 具体的发送请求。 135 | * @param completion 调用结果回调block 136 | */ 137 | + (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion; 138 | 139 | /*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面 140 | * 141 | * 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有 142 | * GetMessageFromWXResp、ShowMessageFromWXResp等。 143 | * @param resp 具体的应答内容 144 | * @param completion 调用结果回调block 145 | */ 146 | + (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion; 147 | 148 | 149 | /*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp 150 | * 151 | * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。 152 | * @param req 具体的发送请求。 153 | * @param viewController 当前界面对象。 154 | * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 155 | * @param completion 调用结果回调block 156 | */ 157 | + (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id)delegate completion:(void (^ __nullable)(BOOL success))completion; 158 | 159 | 160 | /*! @brief WXApi的成员函数,接受微信的log信息。byBlock 161 | 注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏 162 | 注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock 163 | * 164 | * @param level 打印log的级别 165 | * @param logBlock 打印log的回调block 166 | */ 167 | + (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock; 168 | 169 | /*! @brief WXApi的成员函数,接受微信的log信息。byDelegate 170 | 注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象 171 | 注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象 172 | * @param level 打印log的级别 173 | * @param logDelegate 打印log的回调代理, 174 | */ 175 | + (void)startLogByLevel:(WXLogLevel)level logDelegate:(id)logDelegate; 176 | 177 | /*! @brief 停止打印log,会清理block或者delegate为空,释放block 178 | * @param 179 | */ 180 | + (void)stopLog; 181 | @end 182 | 183 | NS_ASSUME_NONNULL_END 184 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/WeiXin/WechatAuthSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // WechatAuthSDK.h 3 | // WechatAuthSDK 4 | // 5 | // Created by 李凯 on 13-11-29. 6 | // Copyright (c) 2013年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | enum AuthErrCode { 15 | WechatAuth_Err_Ok = 0, //Auth成功 16 | WechatAuth_Err_NormalErr = -1, //普通错误 17 | WechatAuth_Err_NetworkErr = -2, //网络错误 18 | WechatAuth_Err_GetQrcodeFailed = -3, //获取二维码失败 19 | WechatAuth_Err_Cancel = -4, //用户取消授权 20 | WechatAuth_Err_Timeout = -5, //超时 21 | }; 22 | 23 | @protocol WechatAuthAPIDelegate 24 | @optional 25 | 26 | - (void)onAuthGotQrcode:(UIImage *)image; //得到二维码 27 | - (void)onQrcodeScanned; //二维码被扫描 28 | - (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode; //成功登录 29 | 30 | @end 31 | 32 | @interface WechatAuthSDK : NSObject{ 33 | NSString *_sdkVersion; 34 | __weak id _delegate; 35 | } 36 | 37 | @property(nonatomic, weak, nullable) id delegate; 38 | @property(nonatomic, readonly) NSString *sdkVersion; //authSDK版本号 39 | 40 | /*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调 41 | * 42 | * @param appId 微信开发者ID 43 | * @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同 44 | * @param timeStamp 时间戳 45 | * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔 46 | * @param signature 签名 47 | * @param schemeData 会在扫码后拼在scheme后 48 | * @return 成功返回YES,失败返回NO 49 | 注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。 50 | */ 51 | 52 | - (BOOL)Auth:(NSString *)appId 53 | nonceStr:(NSString *)nonceStr 54 | timeStamp:(NSString *)timeStamp 55 | scope:(NSString *)scope 56 | signature:(NSString *)signature 57 | schemeData:(nullable NSString *)schemeData; 58 | 59 | 60 | /*! @brief 暂停登录请求 61 | * 62 | * @return 成功返回YES,失败返回NO。 63 | */ 64 | - (BOOL)StopAuth; 65 | 66 | @end 67 | 68 | NS_ASSUME_NONNULL_END 69 | -------------------------------------------------------------------------------- /YHThirdManager/ThirdParty/WeiXin/libWeChatSDK.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liujunliuhong/YHThirdManager/9b0fc0c38ec0cdf67caa7b5e1d6447933a9c18ac/YHThirdManager/ThirdParty/WeiXin/libWeChatSDK.a -------------------------------------------------------------------------------- /YHThirdManager/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /YHThirdManager/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "YHWXManager.h" 12 | #import "YHQQManager.h" 13 | #import "YHSinaManager.h" 14 | 15 | #import "SDK.h" 16 | 17 | 18 | #define NSLog(format, ...) printf("%s\n", [[NSString stringWithFormat:format, ##__VA_ARGS__] UTF8String]) 19 | 20 | 21 | @interface Model : NSObject 22 | @property (nonatomic, copy) NSString *title; 23 | @property (nonatomic, assign) SEL action; 24 | - (instancetype)initWithTitle:(NSString *)title action:(SEL)action; 25 | @end 26 | @implementation Model 27 | - (instancetype)initWithTitle:(NSString *)title action:(SEL)action 28 | { 29 | self = [super init]; 30 | if (self) { 31 | self.title = title; 32 | self.action = action; 33 | } 34 | return self; 35 | } 36 | @end 37 | 38 | @interface ViewController () 39 | @property (nonatomic, strong) UITableView *tableView; 40 | @property (nonatomic, strong) NSMutableArray *> *dataSource; 41 | @end 42 | 43 | @implementation ViewController 44 | - (UITableView *)tableView{ 45 | if (!_tableView) { 46 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds]; 47 | _tableView.delegate = self; 48 | _tableView.dataSource = self; 49 | _tableView.tableFooterView = [UIView new]; 50 | [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])]; 51 | } 52 | return _tableView; 53 | } 54 | 55 | - (void)viewDidLoad { 56 | [super viewDidLoad]; 57 | self.navigationItem.title = @"YHThirdManager"; 58 | [self.view addSubview:self.tableView]; 59 | if (@available(iOS 11.0, *)) { 60 | self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways; 61 | } else { 62 | self.automaticallyAdjustsScrollViewInsets = YES; 63 | } 64 | self.dataSource = [NSMutableArray array]; 65 | 66 | { 67 | Model *model1 = [[Model alloc] initWithTitle:@"QQ授权" action:@selector(qq_auth)]; 68 | Model *model2 = [[Model alloc] initWithTitle:@"QQ获取用户信息" action:@selector(qq_getUserInfo)]; 69 | Model *model3 = [[Model alloc] initWithTitle:@"QQ网页分享" action:@selector(qq_webShare)]; 70 | Model *model4 = [[Model alloc] initWithTitle:@"QQ图片分享" action:@selector(qq_picShare)]; 71 | NSArray *ary = @[model1, model2, model3, model4]; 72 | [self.dataSource addObject:ary]; 73 | } 74 | 75 | 76 | 77 | } 78 | #pragma mark UITableViewDataSource 79 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 80 | return self.dataSource.count; 81 | } 82 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 83 | return [[self.dataSource objectAtIndex:section] count]; 84 | } 85 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 86 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([UITableViewCell class])]; 87 | cell.textLabel.text = self.dataSource[indexPath.section][indexPath.row].title; 88 | return cell; 89 | } 90 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 91 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 92 | SEL action = self.dataSource[indexPath.section][indexPath.row].action; 93 | if ([self respondsToSelector:action]) { 94 | #pragma clang diagnostic push 95 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 96 | [self performSelector:action]; 97 | #pragma clang diagnostic pop 98 | } 99 | } 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | #pragma mark ------------------ QQ ------------------ 111 | // QQ授权 112 | - (void)qq_auth{ 113 | [[YHQQManager sharedInstance] authWithShowHUD:YES completionBlock:^(BOOL isSuccess) { 114 | if (!isSuccess) { 115 | NSLog(@"😋授权失败"); 116 | return; 117 | } 118 | NSLog(@"😋授权成功"); 119 | }]; 120 | } 121 | 122 | // QQ获取用户信息 123 | - (void)qq_getUserInfo{ 124 | // 1、先授权 125 | // 2、再获取用户信息 126 | [[YHQQManager sharedInstance] authWithShowHUD:YES completionBlock:^(BOOL isSuccess) { 127 | if (!isSuccess) { 128 | NSLog(@"😋授权失败"); 129 | return; 130 | } 131 | NSString *accessToken = [YHQQManager sharedInstance].oauth.accessToken; 132 | NSString *appID = [YHQQManager sharedInstance].oauth.appId; 133 | NSString *openID = [YHQQManager sharedInstance].oauth.openId; 134 | [[YHQQManager sharedInstance] getUserInfoWithAccessToken:accessToken appID:appID openId:openID isShowHUD:YES completionBlock:^(BOOL isSuccess) { 135 | if (!isSuccess) { 136 | NSLog(@"😋获取用户信息失败"); 137 | return; 138 | } 139 | NSLog(@"😋获取用户信息成功"); 140 | }]; 141 | }]; 142 | } 143 | 144 | // QQ网页分享 145 | - (void)qq_webShare{ 146 | [[YHQQManager sharedInstance] shareWebWithURL:@"https://www.baidu.com" title:@"标题" description:@"内容内容内容内容内容内容" thumbImageURL:nil shareType:YHQQShareType_QQ shareDestType:YHQQShareDestType_QQ showHUD:YES completionBlock:^(BOOL isSuccess) { 147 | if (!isSuccess) { 148 | NSLog(@"😋分享失败"); 149 | return; 150 | } 151 | NSLog(@"😋分享成功"); 152 | }]; 153 | } 154 | 155 | // QQ图片分享 156 | - (void)qq_picShare{ 157 | [[YHQQManager sharedInstance] shareImageWithImageData:UIImageJPEGRepresentation([UIImage imageNamed:@"1.png"], 1) thumbImageData:nil title:@"标题" description:@"内容内容内容内容内容内容" shareDestType:YHQQShareDestType_QQ showHUD:YES completionBlock:^(BOOL isSuccess) { 158 | if (!isSuccess) { 159 | NSLog(@"😋分享失败"); 160 | return; 161 | } 162 | NSLog(@"😋分享成功"); 163 | }]; 164 | } 165 | 166 | 167 | #pragma mark ------------------ 新浪微博 ------------------ 168 | // 新浪微博授权 169 | - (void)sina_auth{ 170 | // [[YHSinaManager sharedInstance] authWithShowHUD:YES completionBlock:^(WBAuthorizeResponse * _Nullable authResponse) { 171 | // NSLog(@"😆新浪授权:%@", authResponse.description); 172 | // }]; 173 | } 174 | 175 | // 新浪微博获取用户信息 176 | - (void)sina_getUserInfo{ 177 | // [[YHSinaManager sharedInstance] authWithShowHUD:YES completionBlock:^(WBAuthorizeResponse * _Nullable authResponse) { 178 | // if (!authResponse.accessToken) { 179 | // return ; 180 | // } 181 | // [[YHSinaManager sharedInstance] getUserInfoWithAccessToken:authResponse.accessToken userID:authResponse.userID showHUD:YES completionBlock:^(YHSinaUserInfo * _Nullable result) { 182 | // NSLog(@"😆:新浪获取用户信息:%@", result.description); 183 | // }]; 184 | // }]; 185 | } 186 | 187 | // 新浪微博分享 188 | - (void)sina_share{ 189 | // UIImage *image = [UIImage imageNamed:@"1.png"]; 190 | // NSData *data = UIImagePNGRepresentation(image); 191 | // [[YHSinaManager sharedInstance] shareWithContent:@"啦啦啦" imageData:data showHUD:YES completionBlock:^(BOOL isSuccess) { 192 | // NSLog(@"😆新浪微博分享:isSuccess:%d", isSuccess); 193 | // }]; 194 | } 195 | 196 | // 新浪评论指定微博:通过API方式 197 | - (void)sina_comment1{ 198 | // [[YHSinaManager sharedInstance] authWithShowHUD:YES completionBlock:^(WBAuthorizeResponse * _Nullable authResponse) { 199 | // if (!authResponse.accessToken) { 200 | // return ; 201 | // } 202 | // [[YHSinaManager sharedInstance] commentWeiBo1WithAccessToken:authResponse.accessToken ID:@"4368567048776515" comment:@"hello" isCommentOriginWhenTransfer:NO showHUD:YES completionBlock:^(NSDictionary * _Nullable responseObject) { 203 | // NSLog(@"😆新浪评论指定微博:responseObject:%@", responseObject); 204 | // }]; 205 | // }]; 206 | } 207 | 208 | // 新浪评论指定微博:通过scheme方式 209 | - (void)sina_comment2{ 210 | // [[YHSinaManager sharedInstance] commentWeiBo2WithID:@"4368567048776515" comment:@"啦啦啦啦"]; 211 | } 212 | 213 | // 新浪获取我的微博列表 214 | - (void)sina_getMyWeiBoList{ 215 | // [[YHSinaManager sharedInstance] authWithShowHUD:YES completionBlock:^(WBAuthorizeResponse * _Nullable authResponse) { 216 | // if (!authResponse.accessToken) { 217 | // return ; 218 | // } 219 | // [[YHSinaManager sharedInstance] getMineWeoBoListWithAccessToken:authResponse.accessToken userID:authResponse.userID perCount:20 curPage:1 showHUD:YES completionBlock:^(NSDictionary * _Nullable responseObject) { 220 | // NSLog(@"😆新浪获取我的微博列表:responseObject:%@", responseObject); 221 | // }]; 222 | // }]; 223 | } 224 | 225 | #pragma mark ------------------ 微信(本demo导入的是包含支付功能的SDK) ------------------ 226 | // 微信授权 227 | - (void)weixin_auth{ 228 | //#ifdef kWechatNoPay 229 | // [[YHWXNoPayManager sharedInstance] authWithShowHUD:YES completionBlock:^(YHWXNoPayAuthResult * _Nullable authResult) { 230 | // NSLog(@"微信授权:😆:%@", authResult.description); 231 | // }]; 232 | //#else 233 | // [[YHWXManager sharedInstance] authWithShowHUD:YES completionBlock:^(YHWXAuthResult * _Nullable authResult) { 234 | // NSLog(@"微信授权:😆:%@", authResult.description); 235 | // }]; 236 | //#endif 237 | } 238 | 239 | // 微信获取用户信息 240 | - (void)weixin_getUserInfo{ 241 | //#ifdef kWechatNoPay 242 | // [[YHWXNoPayManager sharedInstance] authWithShowHUD:YES completionBlock:^(YHWXNoPayAuthResult * _Nullable authResult) { 243 | // if (!authResult) { 244 | // return ; 245 | // } 246 | // [[YHWXNoPayManager sharedInstance] getUserInfoWithOpenID:authResult.openID accessToken:authResult.accessToken showHUD:YES completionBlock:^(YHWXNoPayUserInfoResult * _Nullable userInfoResult) { 247 | // NSLog(@"微信获取用户信息:😆:%@", userInfoResult.description); 248 | // }]; 249 | // }]; 250 | //#else 251 | // [[YHWXManager sharedInstance] authWithShowHUD:YES completionBlock:^(YHWXAuthResult * _Nullable authResult) { 252 | // if (!authResult) { 253 | // return ; 254 | // } 255 | // [[YHWXManager sharedInstance] getUserInfoWithOpenID:authResult.openID accessToken:authResult.accessToken showHUD:YES completionBlock:^(YHWXUserInfoResult * _Nullable userInfoResult) { 256 | // NSLog(@"微信获取用户信息:😆:%@", userInfoResult.description); 257 | // }]; 258 | // }]; 259 | //#endif 260 | } 261 | 262 | // 微信网页分享 263 | - (void)weixin_webShare{ 264 | //#ifdef kWechatNoPay 265 | // [[YHWXNoPayManager sharedInstance] shareWebWithURL:@"https://www.baidu.com" title:@"测试标题" description:@"测试内容测试内容测试内容测试内容测试内容测试内容测试内容" thumbImage:[UIImage imageNamed:@"big_image.jpeg"] shareType:YHWXNoPayShareType_Session showHUD:YES completionBlock:^(BOOL isSuccess) { 266 | // NSLog(@"微信网页分享:😆:%d", isSuccess); 267 | // }]; 268 | //#else 269 | // [[YHWXManager sharedInstance] shareWebWithURL:@"https://www.baidu.com" title:@"测试标题" description:@"测试内容测试内容测试内容测试内容测试内容测试内容测试内容" thumbImage:[UIImage imageNamed:@"1.png"] shareType:YHWXShareType_Session showHUD:YES completionBlock:^(BOOL isSuccess) { 270 | // NSLog(@"微信网页分享:😆:%d", isSuccess); 271 | // }]; 272 | //#endif 273 | } 274 | 275 | - (void)weixin_pay1{ 276 | // [[YHWXManager sharedInstance] pay1WithPartnerID:QAQ_WECHAT_PARTNERID secretKey:QAQ_WECHAT_SECRETKEY prepayID:@"wx081644129033974637e0de663796974002" showHUD:YES comletionBlock:^(BOOL isSuccess) { 277 | // NSLog(@"微信支付1:😆:%d", isSuccess); 278 | // }]; 279 | } 280 | 281 | - (void)weixin_pay2{ 282 | // [[YHWXManager sharedInstance] pay2WithPartnerID:QAQ_WECHAT_PARTNERID prepayID:@"wx081644129033974637e0de663796974002" sign:@"" nonceStr:@"" timeStamp:@"" showHUD:YES comletionBlock:^(BOOL isSuccess) { 283 | // NSLog(@"微信支付2:😆:%d", isSuccess); 284 | // }]; 285 | } 286 | 287 | 288 | @end 289 | -------------------------------------------------------------------------------- /YHThirdManager/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // YHThirdManager 4 | // 5 | // Created by 银河 on 2019/3/10. 6 | // Copyright © 2019 yinhe. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------