iOS第三方平臺整合元件化
背景
專案使用到了一些第三方平臺的登入、分享、支付功能,包括了微信、微博、QQ平臺登入分享和支付寶、微信平臺的支付,使用的是原生的接入配置整合的,功能上基本上對照著SDK的開發文件就能夠成功的整合了。但是問題也後面也漸漸的暴露出來了,第三方平臺的登入、分享、支付功能不同平臺的的SDK實現方式還是有很大的差別的,包括了輸入的引數以及回撥方式都有差別很大,如果只是簡單的按照文件整合,那麼一定會遇到程式碼呼叫結構很亂,回撥雜亂不統一的問題,更為嚴重的是,後面如果新增刪除一個第三發平臺,那麼修改變得很困難和難以維護,這違反了軟體開發中的開閉原則,所以考慮到了把這部分程式碼做一個重構。
結果
專案實現了新增和刪除第三方平臺的可擴充套件,新增或者刪除第三發平臺只要增加或者移除對應的類和配置即可,不會涉及到已有的程式碼,客戶端的呼叫也不影響。
我是程式碼,歡迎點我??YTThirdPlatformManager
這篇文章的續集 iOS第三方平臺整合元件化續集 介紹了在這個架構的基礎上使用pod庫的特性,更進一步的進行了模組化和解耦的處理,每個第三方平臺的業務程式碼單獨為pod庫的子模組,可以按需的匯入一個或者多個第三方平臺。
先上一個客戶端程式碼呼叫的程式碼
[self addActionWithName:@"QQ Login" callback:^{
[[PTThirdPlatformConfigManager sharedInstance] signInWithType:PTThirdPlatformTypeTencentQQ fromViewController:weakSelf callback:^(ThirdPlatformUserInfo *userInfo, NSError *err) {
}];
}];
[self addActionWithName:@"Wechat Login" callback:^{
[[PTThirdPlatformConfigManager sharedInstance] signInWithType:PTThirdPlatformTypeWechat fromViewController:weakSelf callback:^(ThirdPlatformUserInfo *userInfo, NSError *err) {
}];
}];
問題分析
首先從客戶端的角度分析,對於登入、分享、支付功能,基本上平臺功能呼叫的輸入和輸出是固定的:
輸入 | 輸出 | |
---|---|---|
登入 | 第三發平臺型別 | 第三發平臺的使用者資訊(UID、使用者名稱...) |
分享 | 分享的內容(圖片、標題、文字、超連結) | 第三發平臺型別、分享的結果 |
支付 | 第三發平臺型別、支付資訊(訂單資訊、簽名資訊... | 第三發平臺型別、支付的結果 |
確定了輸入輸出關係,接下來的事情就是統一輸入輸出,這也是這次程式碼架構的關鍵。
架構設計
基於以上的分析,對不同平臺的SDK的請求和響應設計了對應的介面進行隔離,這部分的設計類似於抽象工廠,不同的第三發平臺抽象為了管理工廠,管理工廠實現了一個共同的介面,不同平臺的操作(登入、分享、支付的操作可以認為是產品)抽象為了共同的介面呼叫(這裡和抽象工廠不同,沒有對這些操作封裝為物件然後使用物件再去操作,主要是為了保持程式碼的簡單,防止設計過度)
單個平臺(以微信平臺為例)的類結構圖:
結構說明:
- 介面PTAbsThirdPlatformManager抽象了客戶端對第三發平臺的配置和請求
- 介面PTAbsThirdPlatformRequestHandler抽象了第三方平臺的請求
- 介面PTAbsThirdPlatformRespManager抽象了第三方平臺的響應通過PTAbsThirdPlatformRespManagerDelegate把資料統一回撥到PTAbsThirdPlatformManager子類中
- 類PTWXManager是PTAbsThirdPlatformManager的具體實現,進行微信第三方平臺的登入、分享和支付處理
- 類PTWXRequestHandler是PTAbsThirdPlatformRequestHandler的實現,這裡和微信的API打交道
- 類PTWXRespManager是PTAbsThirdPlatformRespManager的實現,在這裡處理微信SDK的回撥,並通過PTAbsThirdPlatformRespManagerDelegate把資料回撥到PTWXManager
這樣新增其他平臺,只要對應的新增 【PT平臺Manager】、【PT平臺RequestHandler】、【PT平臺RespManager】這三個類就好了
不同平臺的結構好了,接下來需要有一個地方統一管理不同平臺,進行統一的配置管理、請求管理:
PTThirdPlatformConfigManager也是PTAbsThirdPlatformManager實現,裡面配置了不同的平臺對應的管理器,客戶端只要傳遞不同平臺的型別以及需要對應的操作,就可以呼叫對應平臺的功能了。現在客戶端可以直接和PTThirdPlatformConfigManager打交道了,而不用去和具體的比如PTWXManager、PTWeiboManager等管理器打交道了。
如果客戶新增了新的平臺,需要再PTThirdPlatformConfigManager進行配置就行了,然後客戶端呼叫的邏輯保持不變。
程式碼實現
抽象介面部分
客戶端第三方平臺功能呼叫的抽象介面,這些介面是第三發平臺需要使用到了介面的並集,有的平臺需要用到全部,有的只需要部分即可,比如微信到了登入、分享、支付;支付寶用到了只有支付不同的平臺根據功能的不同,實現對應的方法即可。
//
// PTAbsThirdPlatformManager.h
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "PTThirdPlatformDefine.h"
#import "PTThirdPlatformObject.h"
#import "UtilMacro.h"
@class PTOrderModel;
@protocol PTAbsThirdPlatformManager <NSObject>
@optional
- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
/**
第三方平臺處理URL
*/
- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation;
/**
第三方登入
@param thirdPlatformType 第三方平臺
@param viewController 從哪個頁面呼叫的分享
@param callback 登入回撥
*/
- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType
fromViewController:(UIViewController *)viewController
callback:(void (^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback;
/**
第三方分享
@param platform 第三方分享平臺
@param image 分享的圖片
@param imageUrlString 分享的圖片地址
@param title 分享的標題
@param text 分享的文字
@param urlString 分享的URL
@param fromViewController 從哪個頁面呼叫的分享
@param shareResultBlock 分享結果回撥
*/
- (void)shareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock;
/**
第三方支付
@param payMethodType 支付平臺
@param order 支付訂單模型
@param paymentBlock 支付結果回撥
*/
- (void)payWithPlateform:(PTPaymentMethodType)payMethodType
order:(PTOrderModel*)order
paymentBlock:(void (^)(BOOL result))paymentBlock;
@end
具體的第三發平臺呼叫SDK介面的抽象,因為考慮到考慮到程式碼的功能清晰性,所以把SDK介面呼叫的請求和相應部分單獨出來,雖然增加了類和程式碼量,但在程式碼的職責分離上更清晰。
//
// PTAbsThirdPlatformRequestHandler.h
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "PTThirdPlatformDefine.h"
@class PTOrderModel;
@protocol PTAbsThirdPlatformRequestHandler <NSObject>
@optional
// 第三方授權
+ (BOOL)sendAuthInViewController:(UIViewController *)viewController;
// 支付
+ (BOOL)payWithOrder:(PTOrderModel*)order;
// 分享
+ (BOOL)sendMessageWithImage:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
urlString:(NSString*)urlString
title:(NSString*)title
text:(NSString*)text
shareType:(PTShareType)shareType;
@end
第三發平臺響應和回撥部分的介面,這部分主要負責把不同SDK的不同回撥方式和回撥方法統一進行回撥,通過PTAbsThirdPlatformRespManagerDelegate定義的方法回撥到具體的Manager。
//
// PTAbsThirdPlatformRespManager.h
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PTThirdPlatformDefine.h"
#import "PTThirdPlatformObject.h"
#import "UtilMacro.h"
// RespManagerDelegate
@protocol PTAbsThirdPlatformRespManagerDelegate <NSObject>
@optional
- (void)respManagerDidRecvPayResponse:(BOOL)result platform:(PTPaymentMethodType)platform;
- (void)respManagerDidRecvAuthResponse:(ThirdPlatformUserInfo *)response platform:(PTThirdPlatformType)platform;
- (void)respManagerDidRecvMessageResponse:(BOOL)result platform:(PTShareType)platform;
@end
@protocol PTAbsThirdPlatformRespManager <NSObject>
@optional
// 代理,子類需要設定getter/setter
@property (nonatomic, weak) id<PTAbsThirdPlatformRespManagerDelegate> delegate;
@end
介面實現類部分
首先定義了PTBaseThirdPlatformManager類用於處理不同平臺的公共部分,比如說回撥block的設定,接收到PTAbsThirdPlatformRespManagerDelegate的回撥然後進行客戶端的block回撥。此外還有分享圖片的統一處理,圖片統一處理好了之後交給子類進行處理,這裡使用到了是模板模式。
//
// PTBaseThirdPlatformManager.h
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PTAbsThirdPlatformManager.h"
@interface PTBaseThirdPlatformManager : NSObject <PTAbsThirdPlatformManager>
@property (nonatomic, copy) void (^paymentBlock)(BOOL result);
@property (nonatomic, copy) void (^callback)(ThirdPlatformUserInfo* userInfo, NSError* err);
@property (nonatomic, copy) void (^shareResultBlock)(PTShareType, PTShareResult, NSError *);
/**
第三方分享,子類重寫這個方法,由父類的shareToPlateform方法呼叫子類的該方法
@param platform 第三方分享平臺
@param image 分享的圖片
@param imageUrlString 分享的圖片地址
@param title 分享的標題
@param text 分享的文字
@param urlString 分享的URL
@param fromViewController 從哪個頁面呼叫的分享
@param shareResultBlock 分享結果回撥
*/
- (void)doShareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock;
@end
//
// PTBaseThirdPlatformManager.m
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import "PTBaseThirdPlatformManager.h"
#import <SDWebImage/SDWebImageManager.h>
@implementation PTBaseThirdPlatformManager
- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 子類實現
NSAssert(YES, @"哥麼,這裡你忘記實現了");
}
/**
第三方平臺處理URL
*/
- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// 子類實現
NSAssert(YES, @"哥麼,這裡你忘記實現了");
return NO;
}
/**
第三方分享
@param platform 第三方分享平臺
@param image 分享的圖片
@param imageUrlString 分享的圖片地址
@param title 分享的標題
@param text 分享的文字
@param urlString 分享的URL
@param fromViewController 從哪個頁面呼叫的分享
@param shareResultBlock 分享結果回撥
*/
- (void)shareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock {
__block UIImage* sharedImage = nil;
if (image) {
sharedImage = image;
[self doShareToPlateform:platform image:sharedImage imageUrlString:imageUrlString title:title text:text urlString:urlString fromViewController:fromViewController shareResultBlock:shareResultBlock];
} else if (imageUrlString != nil) {
[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:imageUrlString] options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (image) {
sharedImage = image;
} else {
sharedImage = [UIImage imageNamed:@"app_icon"];
}
[self doShareToPlateform:platform image:sharedImage imageUrlString:imageUrlString title:title text:text urlString:urlString fromViewController:fromViewController shareResultBlock:shareResultBlock];
}];
} else {
sharedImage = [UIImage imageNamed:@"signin_logo"];
[self doShareToPlateform:platform image:sharedImage imageUrlString:imageUrlString title:title text:text urlString:urlString fromViewController:fromViewController shareResultBlock:shareResultBlock];
}
}
- (void)doShareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock {
// 空實現,子類實現該方法
}
/**
第三方登入
@param thirdPlatformType 第三方平臺
@param viewController 從哪個頁面呼叫的分享
@param callback 登入回撥
*/
- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType fromViewController:(UIViewController *)viewController callback:(void (^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {
// 空實現,子類實現該方法
}
/**
第三方支付
@param payMethodType 支付平臺
@param order 支付訂單模型
@param paymentBlock 支付結果回撥
*/
- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void (^)(BOOL result))paymentBlock {
// 空實現,子類實現該方法
}
#pragma mark - ......::::::: PTAbsThirdPlatformRespManagerDelegate :::::::......
- (void)respManagerDidRecvAuthResponse:(ThirdPlatformUserInfo *)response platform:(PTThirdPlatformType)platform {
PTOnMainThreadAsync(^{
!_callback ?: _callback(response, nil);
});
}
- (void)respManagerDidRecvMessageResponse:(BOOL)result platform:(PTShareType)platform {
PTOnMainThreadAsync(^{
if (result) {
!self.shareResultBlock ?: self.shareResultBlock(platform, PTShareResultSuccess, nil);
} else {
!self.shareResultBlock ?: self.shareResultBlock(platform, PTShareResultFailed, nil);
}
});
}
- (void)respManagerDidRecvPayResponse:(BOOL)result platform:(PTPaymentMethodType)platform {
PTOnMainThreadAsync(^{
!self.paymentBlock ?: self.paymentBlock(result);
});
}
@end
具體平臺的實現,以微信為例,PTWXManager處理微信平臺的SDK初始化配置;設定微信客戶端的URL回撥的的代理類,即PTWXRespManager的單例物件。然後就是具體的業務功能方法的重寫,包含了登入、分享、支付,具體的功能則是交給PTWXRequestHandler類處理,然後設定PTWXRespManager單例物件的delegate為自身,會在父類PTBaseThirdPlatformManager統一的處理回撥。
//
// PTWXManager.m
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import "PTWXManager.h"
#import "PTWXRespManager.h"
#import "PTWXRequestHandler.h"
#import <WXApi.h>
#import "PTThirdPlatformConfigConst.h"
@interface PTWXManager () <PTAbsThirdPlatformRespManagerDelegate>
@end
@implementation PTWXManager
DEF_SINGLETON
- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 子類實現
//向微信註冊
[WXApi registerApp:kWXAppID];
}
/**
第三方平臺處理URL
*/
- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// 微信
if ([WXApi handleOpenURL:url delegate:[PTWXRespManager sharedInstance]]) {
return YES;
}
return NO;
}
/**
第三方登入
@param thirdPlatformType 第三方平臺
@param fromViewController 從哪個頁面呼叫的分享
@param callback 登入回撥
*/
- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType fromViewController:(UIViewController *)viewController callback:(void (^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {
self.callback = callback;
[PTWXRespManager sharedInstance].delegate = self;
[PTWXRequestHandler sendAuthInViewController:viewController];
}
/**
第三方分享,子類重寫這個方法,由父類的shareToPlateform方法呼叫子類的該方法
@param platform 第三方分享平臺
@param image 分享的圖片
@param imageUrlString 分享的圖片地址
@param title 分享的標題
@param text 分享的文字
@param urlString 分享的URL
@param fromViewController 從哪個頁面呼叫的分享
@param shareResultBlock 分享結果回撥
*/
- (void)doShareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock {
self.shareResultBlock = shareResultBlock;
[self doWechatShareWithImage:image urlString:urlString title:title text:text platform:platform fromViewController:fromViewController];
}
- (void)doWechatShareWithImage:(UIImage*)image
urlString:(NSString*)urlString
title:(NSString*)title
text:(NSString*)text
platform:(PTShareType)platform
fromViewController:(UIViewController*)fromViewController {
[PTWXRespManager sharedInstance].delegate = self;
BOOL shareResult = [PTWXRequestHandler sendMessageWithImage:image imageUrlString:nil urlString:urlString title:title text:text shareType:platform];
if (shareResult == NO) {
!self.shareResultBlock ?: self.shareResultBlock(PTShareTypeWechat, PTShareResultFailed, nil);
}
}
/**
第三方支付
@param payMethodType 支付平臺
@param order 支付訂單模型
@param paymentBlock 支付結果回撥
*/
- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void (^)(BOOL result))paymentBlock {
self.paymentBlock = paymentBlock;
// 使用支付寶支付
[PTWXRespManager sharedInstance].delegate = self;
[PTWXRequestHandler payWithOrder:order];
}
@end
PTWXRequestHandler實現了具體的SDK呼叫以及其他的一些操作
//
// PTWXRequestHandler.m
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import "PTWXRequestHandler.h"
#import <WXApi.h>
#import "PTWXRespManager.h"
#import "PTOrderModel.h"
#import "PTThirdPlatformConfigConst.h"
#import "UIImage+Util.h"
@implementation PTWXRequestHandler
+ (BOOL)sendAuthInViewController:(UIViewController *)viewController {
SendAuthReq* req = [[SendAuthReq alloc] init];
req.scope = kAuthScope;
req.state = kAuthOpenID;
req.openID = kAuthOpenID;
return [WXApi sendAuthReq:req
viewController:viewController
delegate:[PTWXRespManager sharedInstance]];
}
+ (BOOL)payWithOrder:(PTOrderModel *)order {
//調起微信支付
PayReq* req = [[PayReq alloc] init];
req.partnerId = order.partnerid;
req.prepayId = order.prepayid;
req.nonceStr = order.noncestr;
req.timeStamp = order.timestamp;
req.package = order.package;
req.sign = order.sign;
BOOL result = [WXApi sendReq:req];
return result;
}
// 分享
+ (BOOL)sendMessageWithImage:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
urlString:(NSString*)urlString
title:(NSString*)title
text:(NSString*)text
shareType:(PTShareType)shareType {
enum WXScene wxScene = 0;
if (PTShareTypeWechat == shareType) {
wxScene = WXSceneSession;
} else if (PTShareTypeWechatLine == shareType) {
wxScene = WXSceneTimeline;
}
SendMessageToWXReq* req = [[SendMessageToWXReq alloc] init];
req.scene = wxScene;
req.bText = NO;
WXMediaMessage* msg = [[WXMediaMessage alloc] init];
msg.title = title;
msg.description = text;
[msg setThumbImage:[self scaledImageWithOriImage:image]];
if (urlString && urlString.length>0) {
WXWebpageObject* webPageObj = [[WXWebpageObject alloc] init];
webPageObj.webpageUrl = urlString;
msg.mediaObject = webPageObj;
}
req.message = msg;
BOOL result = [WXApi sendReq:req];
return result;
}
+ (UIImage*)scaledImageWithOriImage:(UIImage*)oriImage {
NSInteger maxSharedImageBytes = 32*1000;//32K
NSInteger oriImageBytes = UIImageJPEGRepresentation(oriImage, 1.0).length;
if (oriImageBytes > maxSharedImageBytes) {
CGFloat scaleFactor = maxSharedImageBytes * 1.0f / oriImageBytes * 1.0f;
UIImage* scaledImage = [oriImage scaletoScale:scaleFactor];
if (scaledImage) {
return scaledImage;
}
}
return oriImage;
}
@end
PTWXRespManager處理微信SDK的回撥,並PTAbsThirdPlatformRespManagerDelegate代理把回撥統一的傳遞給PTWXManager
//
// PTWXRespManager.m
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import "PTWXRespManager.h"
#import "WXApi.h"
#import "NSData+NSJSON.h"
#import "PTThirdPlatformConfigConst.h"
#import "NetworkRequestUtil.h"
@implementation PTWXRespManager
DEF_SINGLETON
#pragma mark - WXApiDelegate
- (void)onResp:(BaseResp *)resp {
if ([resp isKindOfClass:[SendMessageToWXResp class]]) {
if (self.delegate
&& [self.delegate respondsToSelector:@selector(respManagerDidRecvMessageResponse:platform:)]) {
if (resp.errCode == WXSuccess) {
[self.delegate respManagerDidRecvMessageResponse:YES platform:PTShareTypeWechat];
} else {
[self.delegate respManagerDidRecvMessageResponse:NO platform:PTShareTypeWechat];
}
}
} else if ([resp isKindOfClass:[SendAuthResp class]]) {
if (resp.errCode == WXSuccess) {
// wx請求accessToken & openId
NSString *urlString = [NSString stringWithFormat:@"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code", kWXAppID, kWXAppSecret, ((SendAuthResp*)resp).code];
[NetworkRequestUtil requestWithURLString:urlString completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary *resultDict = [data nsjsonObject];
[self getUserInfoWithAccessToken:[resultDict objectForKey:@"access_token"] andOpenId:[resultDict objectForKey:@"openid"]];
}];
} else {
if (self.delegate
&& [self.delegate respondsToSelector:@selector(respManagerDidRecvAuthResponse:platform:)]) {
[self.delegate respManagerDidRecvAuthResponse:nil platform:PTThirdPlatformTypeWechat];
}
}
} else if([resp isKindOfClass:[PayResp class]]){
//支付返回結果,實際支付結果需要去微信伺服器端查詢
if (self.delegate
&& [self.delegate respondsToSelector:@selector(respManagerDidRecvPayResponse:platform:)]) {
[self.delegate respManagerDidRecvPayResponse:(resp.errCode == WXSuccess) platform:PaymentMethodTypeWechat];
}
}
}
//wx獲取使用者資訊
- (void)getUserInfoWithAccessToken:(NSString *)accessToken andOpenId:(NSString *)openId{
NSString *urlString =[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/userinfo?access_token=%@&openid=%@", accessToken, openId];
[NetworkRequestUtil requestWithURLString:urlString completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary *resultDict = [data nsjsonObject];
ThirdPlatformUserInfo* userInfo = [ThirdPlatformUserInfo new];
userInfo.userId = [resultDict objectForKey:@"unionid"];
userInfo.username = [resultDict objectForKey:@"nickname"];
userInfo.head = [resultDict objectForKey:@"headimgurl"];
userInfo.tokenString = accessToken;
PTOnMainThreadAsync(^{
if (self.delegate
&& [self.delegate respondsToSelector:@selector(respManagerDidRecvAuthResponse:platform:)]) {
[self.delegate respManagerDidRecvAuthResponse:userInfo platform:PTThirdPlatformTypeWechat];
}
});
}];
}
@end
不同平臺的管理類,這部分是使用者統一處理客戶端的第三發平臺功能呼叫的,因為不同的第三方平臺有相同的介面,為了不和具體的第三方平臺耦合,使用了類名字串進行配置不同的平臺,客戶端只要使用這個類就可以和具體的第三方平臺互動了。
//
// PTThirdPlatformConfigManager.m
// YTThirdPlatformManager
//
// Created by aron on 2017/10/26.
// Copyright © 2017年 aron. All rights reserved.
//
#import "PTThirdPlatformConfigManager.h"
#import "PTAbsThirdPlatformManager.h"
@implementation PTThirdPlatformConfigManager
DEF_SINGLETON
/**
第三方平臺配置
*/
- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
for (NSString* classString in [self thirdPlatformManagerClasses]) {
id<PTAbsThirdPlatformManager> manager = [self managerFromClassString:classString];
if (manager && [manager conformsToProtocol:@protocol(PTAbsThirdPlatformManager)]) {
[manager thirdPlatConfigWithApplication:application didFinishLaunchingWithOptions:launchOptions];
}
}
}
/**
第三方平臺處理URL
*/
- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
for (NSString* classString in [self thirdPlatformManagerClasses]) {
id<PTAbsThirdPlatformManager> manager = [self managerFromClassString:classString];
if (manager && [manager conformsToProtocol:@protocol(PTAbsThirdPlatformManager)]) {
BOOL result = [manager thirdPlatCanOpenUrlWithApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation];
if (result) {
return YES;
}
}
}
return NO;
}
/**
第三方登入
@param thirdPlatformType 第三方平臺
@param fromViewController 從哪個頁面呼叫的分享
@param callback 登入回撥
*/
- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType
fromViewController:(UIViewController *)viewController
callback:(void (^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {
NSString* classString = [[self thirdPlatformSigninManagerConfig] objectForKey:@(thirdPlatformType)];
id<PTAbsThirdPlatformManager> manager = [self managerFromClassString:classString];
[manager signInWithType:thirdPlatformType
fromViewController:viewController
callback:callback];
}
/**
第三方分享
@param platform 第三方分享平臺
@param image 分享的圖片
@param imageUrlString 分享的圖片地址
@param title 分享的標題
@param text 分享的文字
@param urlString 分享的URL
@param fromViewController 從哪個頁面呼叫的分享
@param shareResultBlock 分享結果回撥
*/
- (void)shareToPlateform:(PTShareType)platform
image:(UIImage*)image
imageUrlString:(NSString*)imageUrlString
title:(NSString*)title
text:(NSString*)text
urlString:(NSString*)urlString
fromViewController:(UIViewController*)fromViewController
shareResultBlock:(void (^) (PTShareType platform, PTShareResult shareResult, NSError* error))shareResultBlock {
NSString* classString = [[self thirdPlatformShareManagerConfig] objectForKey:@(platform)];
id<PTAbsThirdPlatformManager> manager = [self managerFromClassString:classString];
[manager shareToPlateform:platform
image:image
imageUrlString:imageUrlString
title:title
text:text
urlString:urlString
fromViewController:fromViewController
shareResultBlock:shareResultBlock];
}
/**
第三方支付
@param payMethodType 支付平臺
@param order 支付訂單模型
@param paymentBlock 支付結果回撥
*/
- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void (^)(BOOL result))paymentBlock {
NSString* classString = [[self thirdPlatformPayManagerConfig] objectForKey:@(payMethodType)];
id<PTAbsThirdPlatformManager> manager = [self managerFromClassString:classString];
[manager payWithPlateform:payMethodType
order:order
paymentBlock:paymentBlock];
}
- (id)managerFromClassString:(NSString*)classString {
if (classString == nil || classString.length == 0) {
return nil;
}
Class clz = NSClassFromString(classString);
SEL sharedInstanceSelector = @selector(sharedInstance);
id<PTAbsThirdPlatformManager> manager = nil;
if(clz && [clz respondsToSelector:sharedInstanceSelector]){
manager = [clz performSelector:sharedInstanceSelector];
}
return manager;
}
- (NSArray*)thirdPlatformManagerClasses {
return @[@"PTAlipayManager",
@"PTTencentManager",
@"PTWeiboManager",
@"PTWXManager",
];
}
- (NSDictionary*)thirdPlatformSigninManagerConfig {
return @{
@(PTThirdPlatformTypeWechat): @"PTWXManager",
@(PTThirdPlatformTypeTencentQQ): @"PTTencentManager",
@(PTThirdPlatformTypeWeibo): @"PTWeiboManager"
};
}
- (NSDictionary*)thirdPlatformPayManagerConfig {
return @{
@(PaymentMethodTypeWechat): @"PTWXManager",
@(PaymentMethodTypeAlipay): @"PTAlipayManager"
};
}
- (NSDictionary*)thirdPlatformShareManagerConfig {
return @{
@(PaymentMethodTypeWechat): @"PTWXManager",
@(PTShareTypeWechatLine): @"PTWXManager",
@(PTShareTypeQQ): @"PTTencentManager",
@(PTShareTypeQQZone): @"PTTencentManager",
@(PTShareTypeWeibo): @"PTWeiboManager",
};
}
@end
One More Thing
剛剛學設計模式,有疏漏的地方請各位看官不吝賜教
相關文章
- Cacti+Nagios監控平臺完美整合iOS
- iOS平臺 | 快速整合華為AGC認證服務iOSGC
- Nagios+Cacti監控平臺完美整合部署iOS
- iOS 元件化 使用cocoapods整合實戰演練iOS元件化
- API整合新一代平臺,iPaaS整合平臺API
- iOS第三發平臺元件化解耦實踐iOS元件化解耦
- ETL資料整合平臺,RestCloud視覺化ETLRESTCloud視覺化
- 第三方平臺接入
- springmvc dubbo整合cms內容釋出平臺ios androidSpringMVCiOSAndroid
- springmvc + mybatis 整合 cms 內容釋出平臺 ios androidSpringMVCMyBatisiOSAndroid
- iOS-元件化iOS元件化
- iOS 元件化方案iOS元件化
- SAP NetWeaver整合化技術平臺解決方案
- RestCloud iPaaS混合整合平臺,資料整合RESTCloud
- 在開放平臺建立第三方平臺應用
- Flutter元件化探索——Pod整合Flutter元件化
- spring mvc dubbo ios android整合cms內容釋出平臺SpringMVCiOSAndroid
- 流程簡化!資料中臺+BI平臺輕鬆實現資料整合
- OPTIMUS — 過程整合與多學科最佳化平臺
- ETL資料整合,RestCloud資料整合平臺RESTCloud
- iOS元件化實踐iOS元件化
- iOS元件化方案(二)iOS元件化
- iOS 元件化方案探索iOS元件化
- iOS平臺如何進行app自動化測試?iOSAPP
- iOS的元件化(模組化)之路iOS元件化
- 第三方支付平臺業務分析
- Web應用的元件化開發(二)——管控平臺Web元件化
- 【轉帖】SAP NetWeaver整合化技術平臺解決方案
- 微信開放平臺 第三方平臺開發踩坑記錄
- 微信開放平臺-第三方平臺-全網釋出邏輯
- iOS元件化之私有庫iOS元件化
- iOS的元件化思路分享iOS元件化
- iOS的元件化開發iOS元件化
- IOS元件化方案總結iOS元件化
- iOS 元件化實踐思考iOS元件化
- 配置第三方平臺URL SchemeScheme
- IOS整合第三方支付、分享、登入功能小結iOS
- Optimus—多學科模擬整合與最佳化設計平臺