转载

iOS第三方平台集成组件化

背景  

项目使用到了一些第三方平台的登录、分享、支付功能,包括了微信、微博、QQ平台登录分享和支付宝、微信平台的支付,使用的是原生的接入配置集成的,功能上基本上对照着SDK的开发文档就能够成功的集成了。但是问题也后面也渐渐的暴露出来了,第三方平台的登录、分享、支付功能不同平台的的SDK实现方式还是有很大的差别的,包括了输入的参数以及回调方式都有差别很大,如果只是简单的按照文档集成,那么一定会遇到代码调用结构很乱,回调杂乱不统一的问题,更为严重的是,后面如果添加删除一个第三发平台,那么修改变得很困难和难以维护,这违反了软件开发中的开闭原则,所以考虑到了把这部分代码做一个重构。

结果

项目实现了添加和删除第三方平台的可扩展,添加或者删除第三发平台只要增加或者移除对应的类和配置即可,不会涉及到已有的代码,客户端的调用也不影响。

项目已经上传了Git->>>我是代码库

先上一个客户端代码调用的代码

   [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) {
            
        }];
    }];

问题分析

首先从客户端的角度分析,对于登录、分享、支付功能,基本上我们的输入是固定的:

iOS第三方平台集成组件化

确定了输入输出关系,接下来的事情就是统一输入输出,这也是这次代码重构的关键。

结构设计

基于以上的分析,对不同平台的SDK的请求和响应设计了对应的接口进行隔离,这部分的设计类似于抽象工厂,不同的第三发平台抽象为了管理工厂,管理工厂实现了一个共同的接口,不同平台的操作(登录、分享、支付的操作可以认为是产品)抽象为了共同的接口调用(这里和抽象工厂不同,没有对这些操作封装为对象然后使用对象再去操作,主要是为了保持代码的简单,防止设计过度)

单个平台(以微信平台为例)的类结构图: 结构图

iOS第三方平台集成组件化

结构说明:

  • 接口PTAbsThirdPlatformManager抽象了客户端对第三发平台的配置和请求

  • 接口PTAbsThirdPlatformRequestHandler抽象了第三方平台的请求

  • 接口PTAbsThirdPlatformRespManager抽象了第三方平台的响应通过PTAbsThirdPlatformRespManagerDelegate把数据统一回调到PTAbsThirdPlatformManager子类中

  • 类PTWXManager是PTAbsThirdPlatformManager的具体实现,进行微信第三方平台的登录、分享和支付处理

  • 类PTWXRequestHandler是PTAbsThirdPlatformRequestHandler的实现,这里和微信的API打交道

  • 类PTWXRespManager是PTAbsThirdPlatformRespManager的实现,在这里处理微信SDK的回调,并通过PTAbsThirdPlatformRespManagerDelegate把数据回调到PTWXManager

  • 这样添加其他平台,只要对应的添加 【PT平台Manager】、【PT平台RequestHandler】、【PT平台RespManager】这三个类就好了

不同平台的结构好了,接下来需要有一个地方统一管理不同平台,进行统一的配置管理、请求管理:

iOS第三方平台集成组件化iOS第三方平台集成组件化

PTThirdPlatformConfigManager也是PTAbsThirdPlatformManager实现,里面配置了不同的平台对应的管理器,客户端只要传递不同平台的类型以及需要对应的操作,就可以调用对应平台的功能了。现在客户端可以直接和PTThirdPlatformConfigManager打交道了,而不用去和具体的比如PTWXManager、PTWeiboManager等管理器打交道了。

如果客户添加了新的平台,需要再PTThirdPlatformConfigManager进行配置就行了,然后客户端调用的逻辑保持不变。

代码实现

抽象接口部分

客户端第三方平台功能调用的抽象接口,这些接口是第三发平台需要使用到了接口的并集,有的平台需要用到全部,有的只需要部分即可,比如微信到了登录、分享、支付;支付宝用到了只有支付不同的平台根据功能的不同,实现对应的方法即可。

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

@class PTOrderModel;

@protocol PTAbsThirdPlatformManager

@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
#import
#import "PTThirdPlatformDefine.h"

@class PTOrderModel;

@protocol PTAbsThirdPlatformRequestHandler

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

// 代理,子类需要设置getter/setter
@property (nonatomic, weak) iddelegate;

@end

接口实现类部分

首先定义了PTBaseThirdPlatformManager类用于处理不同平台的公共部分,比如说回调block的设置,接收到PTAbsThirdPlatformRespManagerDelegate的回调然后进行客户端的block回调。此外还有分享图片的统一处理,图片统一处理好了之后交给子类进行处理,这里使用到了是模板模式。

//
//  PTBaseThirdPlatformManager.h
//  YTThirdPlatformManager
//
//  Created by aron on 2017/10/26.
//  Copyright © 2017年 aron. All rights reserved.
//

#import
#import "PTAbsThirdPlatformManager.h"

@interface PTBaseThirdPlatformManager : 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 *);


/**
 第三方分享,子类重写这个方法,由父类的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


@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 {
    // 空实现,子类实现该方法
}

/**
 第三方支付
 5
 @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 
#import "PTThirdPlatformConfigConst.h"

@interface PTWXManager () 
@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 
#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 {
    //调起微信支付
    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]) {
        idmanager = [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]) {
        idmanager = [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)];
    idmanager = [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)];
    idmanager = [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)];
    idmanager = [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);
    idmanager = 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

刚刚学设计模式,有疏漏的地方请各位看官不吝赐教

正文到此结束
Loading...