环球动态:iOS 微信、支付宝、银联支付组件的进一步设计

原文地址:https://zhanglei.blog.csdn.net/article/details/121376500

前言

有段时间没写技术文章了,一是因为工作太忙,再者因为本人文笔实在一般。最近终于闲下来,本着分享的目的将一些组件设计上的心得与大家分享。本篇文章是基于原有一篇关于支付文章的进一步优化设计,所以在阅读本篇文章前还是建议先移步到那篇文章。文章地址: 微信、支付宝、银联、Paypal 支付组件封装


【资料图】

描述

在封装支付接口时,需要面临各支付平台不同SDK集成的问题,有的支付第三方平台只通过sdk组件就可完成支付,像支付宝,但大部分的支付第三方平台需要先去调用服务端API接口获取支付需要的信息,拿到这些支付信息后,再去调用sdk组件完成支付,这类第三方有银联(需要获取tn交易流水号),微信(需要获取prepayData)等。

为了以后的支付功能复用,想要设计一个支付组件,该组件整合并统一了这些第三方支付sdk的接口,以便给客户端快速集成。在设计支付组件的过程中就遇到上面提到的问题。 如何解决某些第三方需要请求一些数据后,再进行支付的问题 ? 试想一下如果将这些请求hardcode到组件中,显然能满足当前的功能,局限性也非常明显,只能适用当前的支付业务。 此时的支付组件会和网络组件藕合,不利于扩展及复用。

设计

如何解藕? 如何能让这些需要请求API的第三方不污染组件? 解藕的思想就是“抽离变化,并封装”。 我们需要把不稳定的部分抽离出来,使其独自变化,不影响稳定的部分。 找到了方向, 如何抽离? 这里我们可以使用面向协议的编程的思想,将请求API的行为进行抽象。伪代码:

//抽像一个协议, 协议定义一个获取支付信息的方法,调用接口是异步操作,所以返回的数据使用block返回@protocol PayDataPrepareProtocol @required- (void)getPayData:(void(^)(id result, NSError *error))block;@end

微信支付伪代码:

@interface WXPayPrepareData : NSObject @property (nonatomic,strong) NSDictionary *requestParams;@end@implementation WXPayPrepareData- (void)getPayData:(void(^)(id result, NSError *error))block {    //根据请求参数,使用网络层组件调用API,并返回预支付信息    block(result,nil);}@end

银联支付伪代码:

@interface UnionPayPrepareData : NSObject @property (nonatomic,strong) NSDictionary *requestParams;@end@implementation UnionPayPrepareData- (void)getPayData:(void(^)(id result, NSError *error))block {    //根据请求参数,使用网络层组件调用API,并返回预支付信息    block(result,nil);}@end

如何能将支付类型与预支付实现类之间建立联系呢?我们需要设计一个配置类来管理这种支付类型与预支付实现类的对应关系 。

支付配置的伪代码:

typedef NS_Enum(NSInteger, PayType) {    PayTypeForAlipay,    //支付宝支付    PayTypeForWXPay,    //微信支付    PayTypeForUPPay,    //银联支付} @interface PayConfig: NSObject//单例对象+ (instancetype)config;//添加获取预支付信息对应的策略类, 没有传递实例对象,避免未使用而造成的内存浪费- (void)appendPrepayDataStrategy:(Class)strategyClass withPayType:(PayType)payType;//判断是否存在指定类型对应的实现策略- (BOOL)containsPrepayDataStrategyWithPayType:(PayType)payType;//根据支付的枚举类型,获取预支付信息处理对象- (id)getPrepayDataStrategyWithPayType:(PayType)payType;@end@interface PayConfig ()@property (nonatomic,strong) NSMutableDictionary *strategyMap;@end@implementation PayConfig//单例对象+ (instancetype)config {    static PayConfig *_instance;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        if (!_instance) {           _instance = [[PayConfig alloc] init];         }    });    return _instance;}//添加获取预支付信息对应的策略类, 没有传递实例对象,避免未使用而造成的内存浪费- (void)appendPrepayDataStrategy:(Class)strategyClass withPayType:(PayType)payType {    if (!strategyClass) {        return;    }    //判断是否实现了协议    if (![strategyClass conformsToProtocol:@protocol(PayDataPrepareProtocol)]) {        return;    }        NSString *payTypeKey = [Utils convertPayTypeToString:payType]; //将枚举转成字符串    [self.strategyMap setObject:strategyClass forKey:payTypeKey];}//判断是否存在指定类型对应的实现策略- (BOOL)containsPrepayDataStrategyWithPayType:(PayType)payType {    NSString *payTypeKey = [Utils convertPayTypeToString:payType]; //将枚举转成字符串    return  !self.strategyMap[payTypeKey];}//根据支付的枚举类型,获取预支付信息处理对象- (id)getPrepayDataStrategyWithPayType:(PayType)payType {    if (![self containsPrepayDataStrategyWithPayType:payType]) {        return nil;    }    NSString *payTypeKey = [Utils convertPayTypeToString:payType]; //将枚举转成字符串    Class cls = self.strategyMap[payTypeKey];    return [[cls alloc] init]; //在需要时才返回创建的对象}//懒加载,需要时创建- (NSMutableDictionary *)strategyMap {    if (!_strategyMap) {        _strategyMap = @{}.mutableCopy;    }    return _strategyMap;}@end

通过上面的支付配置(单例)对象,我们将以支付类型为key, 以对应的获取预支付信息的类为value, 使用字典来管理。 将配置类设计成单例,这样就可以在支付组件中访问,并使用其中的配置信息。

支付组件的伪代码:

#import "PayConfig.h"@interface PayManager :NSObject //调用预支付信息API接口,用到的请求参数@property (nonatomic,strong) NSDictionary *requestParams;//支付第三方类型@property (nonatomic,assign) PayType payType;//开始支付- (void)startPay;@end@implementation PayManager //开始支付- (void)startPay {        //1. 根据支付类型,判断支付配置中是否有需要请求服务API的处理类    if ([[PayConfig config] containsPrepayDataStrategyWithPayType:self.payType]) {        id strategy = [[PayConfig config] getPrepayDataStrategyWithPayType:self.payType];                //利用KVC向请求API接口的策略类传递请求参数        [strategy setValue:self.requestParams forKey:@“requestParams”];                //准备好请求数据后,开始调用接口API获取所需要的预支付信息        [strategy getPayData:^(id result, NSError *error ) {            //拿到需要的预支付信息后,再调起第三方支付组件                    }];        }else {        // 调起第三方支付组件    }}@end

总结

通过我们的进一步设计,支付组件已完全不依赖于网络组件来完成对预支付信息的获取,而且扩展性更强了。 如果以后有新的支付第三方加入进来,且需要获取预支付信息的, 我们只需要实现PayDataPrepareProtocol协议, 并将其加入到 PayConfig 中就可以了。 通过少量的修改我们就可以完成扩展,也遵循了“开闭原则( 对扩展开放,对修改关闭)” 。

完整的支付组件代码请前往:RZPayManager在README.md文件中有该组件的使用详解,如果喜欢,点关注支持一下。

后记

如果本文对你有一点帮助的话,欢迎收藏、点赞,感谢。文中如有不对之处,也欢迎大家在评论区指出,共勉。

标签:

x 广告
广东高考成绩6月25日11时30分起手机推送,12时起这些方式可查分 环球热头条

文 羊城晚报全媒体记者孙唯目前,广东省2023年普通高考评卷工作已经完

上汽通用召回78205辆旗下车辆 涉及别克昂科雷、雪佛兰探界者

中国网汽车6月23日讯日前,上汽通用汽车有限公司根据《缺陷汽车产品召

有钱!曝利雅得新月挖曼城大将 愿给年薪7500万镑-每日快播

去年夏天,巴萨和巴黎圣日耳曼都有意签下B席,当时曼城对他的估价在700

当前要闻:中国气象局启动高温四级应急响应

央视网消息:据中国气象局网站消息,6月22日,北京、天津、河北、山东

暴雨黄色预警!福建西北部地区有大暴雨

中央气象台6月23日06时继续发布暴雨黄色预警。预计,6月23日08时至24日

当前速读:央行发布最新支付数据:POS总量3309万台

6月20日,央行发布的2023年第一季度支付业务统计数据显示,我国支付体

天天微头条丨许昌职业技术学院入选2023年河南省职业教育思政示范项目

大河网讯近日,河南省教育厅下发《关于公布2023年河南省职业教育和继续

生活成本飙升 超过100万名英国儿童接受食品救济

在生活成本飙升的重压下,越来越多英国家庭难以负担生活必需品的开支,

缙云教育网成绩查询(缙云教育网) 全球播报

1、办公室联系电话:3140606人事科联系电话:3140612计划财务科(校产

“老虎变猫”是进化还是退化?全新路虎揽胜极光发布 搭载1.5T三缸发动机

“老虎变猫”是进化还是退化?全新路虎揽胜极光发布搭载1 5T三缸发动机

x 广告

Copyright ©  2015-2023 亚洲都市网版权所有  备案号:京ICP备2021034106号-51   联系邮箱:5 516 538 @qq.com