iOS第三方平臺(tái)集成組件化

背景

項(xiàng)目使用到了一些第三方平臺(tái)的登錄赏参、分享志笼、支付功能,包括了微信把篓、微博纫溃、QQ平臺(tái)登錄分享和支付寶、微信平臺(tái)的支付韧掩,使用的是原生的接入配置集成的紊浩,功能上基本上對(duì)照著SDK的開(kāi)發(fā)文檔就能夠成功的集成了。但是問(wèn)題也后面也漸漸的暴露出來(lái)了疗锐,第三方平臺(tái)的登錄坊谁、分享、支付功能不同平臺(tái)的的SDK實(shí)現(xiàn)方式還是有很大的差別的滑臊,包括了輸入的參數(shù)以及回調(diào)方式都有差別很大口芍,如果只是簡(jiǎn)單的按照文檔集成,那么一定會(huì)遇到代碼調(diào)用結(jié)構(gòu)很亂雇卷,回調(diào)雜亂不統(tǒng)一的問(wèn)題鬓椭,更為嚴(yán)重的是,后面如果添加刪除一個(gè)第三發(fā)平臺(tái)关划,那么修改變得很困難和難以維護(hù)小染,這違反了軟件開(kāi)發(fā)中的開(kāi)閉原則,所以考慮到了把這部分代碼做一個(gè)重構(gòu)贮折。

結(jié)果

項(xiàng)目實(shí)現(xiàn)了添加和刪除第三方平臺(tái)的可擴(kuò)展裤翩,添加或者刪除第三發(fā)平臺(tái)只要增加或者移除對(duì)應(yīng)的類(lèi)和配置即可,不會(huì)涉及到已有的代碼调榄,客戶(hù)端的調(diào)用也不影響踊赠。

先上一個(gè)客戶(hù)端代碼調(diào)用的代碼

[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) {

}];

}];

問(wèn)題分析

首先從客戶(hù)端的角度分析,對(duì)于登錄振峻、分享臼疫、支付功能择份,基本上我們的輸入是固定的:

確定了輸入輸出關(guān)系扣孟,接下來(lái)的事情就是統(tǒng)一輸入輸出,這也是這次代碼重構(gòu)的關(guān)鍵荣赶。

結(jié)構(gòu)設(shè)計(jì)

基于以上的分析凤价,對(duì)不同平臺(tái)的SDK的請(qǐng)求和響應(yīng)設(shè)計(jì)了對(duì)應(yīng)的接口進(jìn)行隔離,這部分的設(shè)計(jì)類(lèi)似于抽象工廠拔创,不同的第三發(fā)平臺(tái)抽象為了管理工廠,管理工廠實(shí)現(xiàn)了一個(gè)共同的接口,不同平臺(tái)的操作(登錄眷蚓、分享阀圾、支付的操作可以認(rèn)為是產(chǎn)品)抽象為了共同的接口調(diào)用(這里和抽象工廠不同立倍,沒(méi)有對(duì)這些操作封裝為對(duì)象然后使用對(duì)象再去操作,主要是為了保持代碼的簡(jiǎn)單侣滩,防止設(shè)計(jì)過(guò)度)

單個(gè)平臺(tái)(以微信平臺(tái)為例)的類(lèi)結(jié)構(gòu)圖: 結(jié)構(gòu)圖

結(jié)構(gòu)說(shuō)明:

接口PTAbsThirdPlatformManager抽象了客戶(hù)端對(duì)第三發(fā)平臺(tái)的配置和請(qǐng)求

接口PTAbsThirdPlatformRequestHandler抽象了第三方平臺(tái)的請(qǐng)求

接口PTAbsThirdPlatformRespManager抽象了第三方平臺(tái)的響應(yīng)通過(guò)PTAbsThirdPlatformRespManagerDelegate把數(shù)據(jù)統(tǒng)一回調(diào)到PTAbsThirdPlatformManager子類(lèi)中

類(lèi)PTWXManager是PTAbsThirdPlatformManager的具體實(shí)現(xiàn)口注,進(jìn)行微信第三方平臺(tái)的登錄、分享和支付處理

類(lèi)PTWXRequestHandler是PTAbsThirdPlatformRequestHandler的實(shí)現(xiàn)君珠,這里和微信的API打交道

類(lèi)PTWXRespManager是PTAbsThirdPlatformRespManager的實(shí)現(xiàn)寝志,在這里處理微信SDK的回調(diào),并通過(guò)PTAbsThirdPlatformRespManagerDelegate把數(shù)據(jù)回調(diào)到PTWXManager

這樣添加其他平臺(tái)策添,只要對(duì)應(yīng)的添加 【PT平臺(tái)Manager】材部、【PT平臺(tái)RequestHandler】、【PT平臺(tái)RespManager】這三個(gè)類(lèi)就好了

不同平臺(tái)的結(jié)構(gòu)好了唯竹,接下來(lái)需要有一個(gè)地方統(tǒng)一管理不同平臺(tái)乐导,進(jìn)行統(tǒng)一的配置管理、請(qǐng)求管理:

PTThirdPlatformConfigManager也是PTAbsThirdPlatformManager實(shí)現(xiàn)浸颓,里面配置了不同的平臺(tái)對(duì)應(yīng)的管理器兽叮,客戶(hù)端只要傳遞不同平臺(tái)的類(lèi)型以及需要對(duì)應(yīng)的操作,就可以調(diào)用對(duì)應(yīng)平臺(tái)的功能了』福現(xiàn)在客戶(hù)端可以直接和PTThirdPlatformConfigManager打交道了鹦聪,而不用去和具體的比如PTWXManager、PTWeiboManager等管理器打交道了蒂秘。

如果客戶(hù)添加了新的平臺(tái)泽本,需要再PTThirdPlatformConfigManager進(jìn)行配置就行了,然后客戶(hù)端調(diào)用的邏輯保持不變姻僧。

代碼實(shí)現(xiàn)

抽象接口部分

客戶(hù)端第三方平臺(tái)功能調(diào)用的抽象接口规丽,這些接口是第三發(fā)平臺(tái)需要使用到了接口的并集,有的平臺(tái)需要用到全部撇贺,有的只需要部分即可赌莺,比如微信到了登錄、分享松嘶、支付艘狭;支付寶用到了只有支付不同的平臺(tái)根據(jù)功能的不同,實(shí)現(xiàn)對(duì)應(yīng)的方法即可翠订。

//

//? PTAbsThirdPlatformManager.h

//? YTThirdPlatformManager

//

//? Created by aron on 2017/10/26.

//? Copyright ? 2017年 aron. All rights reserved.

//

#import

#import

#import"PTThirdPlatformDefine.h"

#import"PTThirdPlatformObject.h"

#import"UtilMacro.h"

@classPTOrderModel;

@protocol PTAbsThirdPlatformManager

@optional

- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

/**

第三方平臺(tái)處理URL

*/

- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application

openURL:(NSURL *)url

sourceApplication:(NSString *)sourceApplication

annotation:(id)annotation;

/**

第三方登錄

@param thirdPlatformType 第三方平臺(tái)

@param viewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param callback 登錄回調(diào)

*/

- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType

fromViewController:(UIViewController *)viewController

callback:(void(^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback;

/**

第三方分享

@param platform 第三方分享平臺(tái)

@param image 分享的圖片

@param imageUrlString 分享的圖片地址

@param title 分享的標(biāo)題

@param text 分享的文字

@param urlString 分享的URL

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param shareResultBlock 分享結(jié)果回調(diào)

*/

- (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 支付平臺(tái)

@param order 支付訂單模型

@param paymentBlock 支付結(jié)果回調(diào)

*/

- (void)payWithPlateform:(PTPaymentMethodType)payMethodType

order:(PTOrderModel*)order

paymentBlock:(void(^)(BOOL result))paymentBlock;

@end

具體的第三發(fā)平臺(tái)調(diào)用SDK接口的抽象巢音,因?yàn)榭紤]到考慮到代碼的功能清晰性,所以把SDK接口調(diào)用的請(qǐng)求和相應(yīng)部分單獨(dú)出來(lái)尽超,雖然增加了類(lèi)和代碼量官撼,但在代碼的職責(zé)分離上更清晰。

//

//? PTAbsThirdPlatformRequestHandler.h

//? YTThirdPlatformManager

//

//? Created by aron on 2017/10/26.

//? Copyright ? 2017年 aron. All rights reserved.

//

#import

#import

#import"PTThirdPlatformDefine.h"

@classPTOrderModel;

@protocol PTAbsThirdPlatformRequestHandler

@optional

// 第三方授權(quán)

+ (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

第三發(fā)平臺(tái)響應(yīng)和回調(diào)部分的接口似谁,這部分主要負(fù)責(zé)把不同SDK的不同回調(diào)方式和回調(diào)方法統(tǒng)一進(jìn)行回調(diào)傲绣,通過(guò)PTAbsThirdPlatformRespManagerDelegate定義的方法回調(diào)到具體的Manager掠哥。

//

//? PTAbsThirdPlatformRespManager.h

//? YTThirdPlatformManager

//

//? Created by aron on 2017/10/26.

//? Copyright ? 2017年 aron. All rights reserved.

//

#import

#import"PTThirdPlatformDefine.h"

#import"PTThirdPlatformObject.h"

#import"UtilMacro.h"

// RespManagerDelegate

@protocol PTAbsThirdPlatformRespManagerDelegate

@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

@optional

// 代理,子類(lèi)需要設(shè)置getter/setter

@property (nonatomic, weak) iddelegate;

@end

接口實(shí)現(xiàn)類(lèi)部分

首先定義了PTBaseThirdPlatformManager類(lèi)用于處理不同平臺(tái)的公共部分秃诵,比如說(shuō)回調(diào)block的設(shè)置龙致,接收到PTAbsThirdPlatformRespManagerDelegate的回調(diào)然后進(jìn)行客戶(hù)端的block回調(diào)。此外還有分享圖片的統(tǒng)一處理顷链,圖片統(tǒng)一處理好了之后交給子類(lèi)進(jìn)行處理目代,這里使用到了是模板模式。

//

//? PTBaseThirdPlatformManager.h

//? YTThirdPlatformManager

//

//? Created by aron on 2017/10/26.

//? Copyright ? 2017年 aron. All rights reserved.

//

#import

#import"PTAbsThirdPlatformManager.h"

@interfacePTBaseThirdPlatformManager : NSObject

@property (nonatomic, copy) void(^paymentBlock)(BOOL result);

@property (nonatomic, copy) void(^callback)(ThirdPlatformUserInfo* userInfo, NSError* err);

@property (nonatomic, copy) void(^shareResultBlock)(PTShareType, PTShareResult, NSError *);

/**

第三方分享嗤练,子類(lèi)重寫(xiě)這個(gè)方法榛了,由父類(lèi)的shareToPlateform方法調(diào)用子類(lèi)的該方法

@param platform 第三方分享平臺(tái)

@param image 分享的圖片

@param imageUrlString 分享的圖片地址

@param title 分享的標(biāo)題

@param text 分享的文字

@param urlString 分享的URL

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param shareResultBlock 分享結(jié)果回調(diào)

*/

- (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

@implementation PTBaseThirdPlatformManager

- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// 子類(lèi)實(shí)現(xiàn)

NSAssert(YES, @"哥么,這里你忘記實(shí)現(xiàn)了");

}

/**

第三方平臺(tái)處理URL

*/

- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application

openURL:(NSURL *)url

sourceApplication:(NSString *)sourceApplication

annotation:(id)annotation {

// 子類(lèi)實(shí)現(xiàn)

NSAssert(YES, @"哥么煞抬,這里你忘記實(shí)現(xiàn)了");

returnNO;

}

/**

第三方分享

@param platform 第三方分享平臺(tái)

@param image 分享的圖片

@param imageUrlString 分享的圖片地址

@param title 分享的標(biāo)題

@param text 分享的文字

@param urlString 分享的URL

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param shareResultBlock 分享結(jié)果回調(diào)

*/

- (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];

} elseif(imageUrlString != nil) {

[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:imageUrlString] options:0progress: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 {

// 空實(shí)現(xiàn)霜大,子類(lèi)實(shí)現(xiàn)該方法

}

/**

第三方登錄

@param thirdPlatformType 第三方平臺(tái)

@param viewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param callback 登錄回調(diào)

*/

- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType fromViewController:(UIViewController *)viewController callback:(void(^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {

// 空實(shí)現(xiàn),子類(lèi)實(shí)現(xiàn)該方法

}

/**

第三方支付

5

@param payMethodType 支付平臺(tái)

@param order 支付訂單模型

@param paymentBlock 支付結(jié)果回調(diào)

*/

- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void(^)(BOOL result))paymentBlock {

// 空實(shí)現(xiàn)革答,子類(lèi)實(shí)現(xiàn)該方法

}

#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

具體平臺(tái)的實(shí)現(xiàn)战坤,以微信為例,PTWXManager處理微信平臺(tái)的SDK初始化配置残拐;設(shè)置微信客戶(hù)端的URL回調(diào)的的代理類(lèi)途茫,即PTWXRespManager的單例對(duì)象。然后就是具體的業(yè)務(wù)功能方法的重寫(xiě)溪食,包含了登錄囊卜、分享、支付错沃,具體的功能則是交給PTWXRequestHandler類(lèi)處理栅组,然后設(shè)置PTWXRespManager單例對(duì)象的delegate為自身,會(huì)在父類(lèi)PTBaseThirdPlatformManager統(tǒng)一的處理回調(diào)枢析。

//

//? 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

#import"PTThirdPlatformConfigConst.h"

@interfacePTWXManager ()

@end

@implementation PTWXManager

DEF_SINGLETON

- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// 子類(lèi)實(shí)現(xiàn)

//向微信注冊(cè)

[WXApi registerApp:kWXAppID];

}

/**

第三方平臺(tái)處理URL

*/

- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application

openURL:(NSURL *)url

sourceApplication:(NSString *)sourceApplication

annotation:(id)annotation {

// 微信

if([WXApi handleOpenURL:url delegate:[PTWXRespManager sharedInstance]]) {

returnYES;

}

returnNO;

}

/**

第三方登錄

@param thirdPlatformType 第三方平臺(tái)

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param callback 登錄回調(diào)

*/

- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType fromViewController:(UIViewController *)viewController callback:(void(^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {

self.callback = callback;

[PTWXRespManager sharedInstance].delegate = self;

[PTWXRequestHandler sendAuthInViewController:viewController];

}

/**

第三方分享玉掸,子類(lèi)重寫(xiě)這個(gè)方法,由父類(lèi)的shareToPlateform方法調(diào)用子類(lèi)的該方法

@param platform 第三方分享平臺(tái)

@param image 分享的圖片

@param imageUrlString 分享的圖片地址

@param title 分享的標(biāo)題

@param text 分享的文字

@param urlString 分享的URL

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param shareResultBlock 分享結(jié)果回調(diào)

*/

- (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 支付平臺(tái)

@param order 支付訂單模型

@param paymentBlock 支付結(jié)果回調(diào)

*/

- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void(^)(BOOL result))paymentBlock {

self.paymentBlock = paymentBlock;

// 使用支付寶支付

[PTWXRespManager sharedInstance].delegate = self;

[PTWXRequestHandler payWithOrder:order];

}

@end

PTWXRequestHandler實(shí)現(xiàn)了具體的SDK調(diào)用以及其他的一些操作

//

//? PTWXRequestHandler.m

//? YTThirdPlatformManager

//

//? Created by aron on 2017/10/26.

//? Copyright ? 2017年 aron. All rights reserved.

//

#import"PTWXRequestHandler.h"

#import

#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;

4

return[WXApi sendAuthReq:req

viewController:viewController

delegate:[PTWXRespManager sharedInstance]];

}

+ (BOOL)payWithOrder:(PTOrderModel *)order {

//調(diào)起微信支付

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];

returnresult;

}

// 分享

+ (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;

} elseif(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];

returnresult;

}

+ (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) {

returnscaledImage;

}

}

returnoriImage;

}

@end

PTWXRespManager處理微信SDK的回調(diào)醒叁,并PTAbsThirdPlatformRespManagerDelegate代理把回調(diào)統(tǒng)一的傳遞給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];

}

}

} elseif([resp isKindOfClass:[SendAuthResp class]]) {

if(resp.errCode == WXSuccess) {

// wx請(qǐng)求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];

}

}

} elseif([resp isKindOfClass:[PayResp class]]){

//支付返回結(jié)果司浪,實(shí)際支付結(jié)果需要去微信服務(wù)器端查詢(xún)

if(self.delegate

&& [self.delegate respondsToSelector:@selector(respManagerDidRecvPayResponse:platform:)]) {

[self.delegate respManagerDidRecvPayResponse:(resp.errCode == WXSuccess) platform:PaymentMethodTypeWechat];

}

}

}

//wx獲取用戶(hù)信息

- (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

不同平臺(tái)的管理類(lèi),這部分是用戶(hù)統(tǒng)一處理客戶(hù)端的第三發(fā)平臺(tái)功能調(diào)用的辐益,因?yàn)椴煌牡谌狡脚_(tái)有相同的接口断傲,為了不和具體的第三方平臺(tái)耦合,使用了類(lèi)名字符串進(jìn)行配置不同的平臺(tái)智政,客戶(hù)端只要使用這個(gè)類(lèi)就可以和具體的第三方平臺(tái)交互了。

//

//? 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

/**

第三方平臺(tái)配置

*/

- (void)thirdPlatConfigWithApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

for(NSString* classString in[self thirdPlatformManagerClasses]) {

idmanager = [self managerFromClassString:classString];

if(manager && [manager conformsToProtocol:@protocol(PTAbsThirdPlatformManager)]) {

[manager thirdPlatConfigWithApplication:application didFinishLaunchingWithOptions:launchOptions];

}

}

}

/**

第三方平臺(tái)處理URL

*/

- (BOOL)thirdPlatCanOpenUrlWithApplication:(UIApplication *)application

openURL:(NSURL *)url

sourceApplication:(NSString *)sourceApplication

annotation:(id)annotation {

for(NSString* classString in[self thirdPlatformManagerClasses]) {

idmanager = [self managerFromClassString:classString];

if(manager && [manager conformsToProtocol:@protocol(PTAbsThirdPlatformManager)]) {

BOOL result = [manager thirdPlatCanOpenUrlWithApplication:application openURL:url sourceApplication:sourceApplication annotation:annotation];

if(result) {

returnYES;

}

}

}

returnNO;

}

/**

第三方登錄

@param thirdPlatformType 第三方平臺(tái)

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param callback 登錄回調(diào)

*/

- (void)signInWithType:(PTThirdPlatformType)thirdPlatformType

fromViewController:(UIViewController *)viewController

callback:(void(^)(ThirdPlatformUserInfo* userInfo, NSError* err))callback {

NSString* classString = [[self thirdPlatformSigninManagerConfig] objectForKey:@(thirdPlatformType)];

idmanager = [self managerFromClassString:classString];

[manager signInWithType:thirdPlatformType

fromViewController:viewController

callback:callback];

}

/**

第三方分享

@param platform 第三方分享平臺(tái)

@param image 分享的圖片

@param imageUrlString 分享的圖片地址

@param title 分享的標(biāo)題

@param text 分享的文字

@param urlString 分享的URL

@param fromViewController 從哪個(gè)頁(yè)面調(diào)用的分享

@param shareResultBlock 分享結(jié)果回調(diào)

*/

- (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)];

idmanager = [self managerFromClassString:classString];

[manager shareToPlateform:platform

image:image

imageUrlString:imageUrlString

title:title

text:text

urlString:urlString

fromViewController:fromViewController

shareResultBlock:shareResultBlock];

}

/**

第三方支付

@param payMethodType 支付平臺(tái)

@param order 支付訂單模型

@param paymentBlock 支付結(jié)果回調(diào)

*/

- (void)payWithPlateform:(PTPaymentMethodType)payMethodType order:(PTOrderModel*)order paymentBlock:(void(^)(BOOL result))paymentBlock {

NSString* classString = [[self thirdPlatformPayManagerConfig] objectForKey:@(payMethodType)];

idmanager = [self managerFromClassString:classString];

[manager payWithPlateform:payMethodType

order:order

paymentBlock:paymentBlock];

}

- (id)managerFromClassString:(NSString*)classString {

if(classString == nil || classString.length == 0) {

returnnil;

}

Class clz = NSClassFromString(classString);

SEL sharedInstanceSelector = @selector(sharedInstance);

idmanager = nil;

if(clz && [clz respondsToSelector:sharedInstanceSelector]){

manager = [clz performSelector:sharedInstanceSelector];

}

returnmanager;

}

- (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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末箱蝠,一起剝皮案震驚了整個(gè)濱河市续捂,隨后出現(xiàn)的幾起案子垦垂,更是在濱河造成了極大的恐慌,老刑警劉巖牙瓢,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劫拗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡矾克,警方通過(guò)查閱死者的電腦和手機(jī)页慷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胁附,“玉大人酒繁,你說(shuō)我怎么就攤上這事】仄蓿” “怎么了州袒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)弓候。 經(jīng)常有香客問(wèn)我郎哭,道長(zhǎng),這世上最難降的妖魔是什么菇存? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任夸研,我火速辦了婚禮,結(jié)果婚禮上依鸥,老公的妹妹穿的比我還像新娘陈惰。我一直安慰自己,他們只是感情好毕籽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布抬闯。 她就那樣靜靜地躺著,像睡著了一般关筒。 火紅的嫁衣襯著肌膚如雪溶握。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天蒸播,我揣著相機(jī)與錄音睡榆,去河邊找鬼。 笑死袍榆,一個(gè)胖子當(dāng)著我的面吹牛胀屿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播包雀,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宿崭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了才写?” 一聲冷哼從身側(cè)響起葡兑,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奖蔓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后讹堤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吆鹤,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年洲守,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疑务。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡梗醇,死狀恐怖知允,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情婴削,我是刑警寧澤廊镜,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站唉俗,受9級(jí)特大地震影響嗤朴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜虫溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一雹姊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衡楞,春花似錦吱雏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至迷守,卻和暖如春犬绒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背兑凿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工凯力, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人礼华。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓咐鹤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親圣絮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祈惶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容