iOS 微信、支付宝、银联支付组件的进一步设计

这篇具有很好参考价值的文章主要介绍了iOS 微信、支付宝、银联支付组件的进一步设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

前言

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

描述

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

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

设计

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

//抽像一个协议, 协议定义一个获取支付信息的方法,调用接口是异步操作,所以返回的数据使用block返回

@protocol PayDataPrepareProtocol <NSObject>

@required
- (void)getPayData:(void(^)(id result, NSError *error))block;

@end

微信支付伪代码:

@interface WXPayPrepareData : NSObject <PayDataPrepareProtocol>
@property (nonatomic,strong) NSDictionary *requestParams;

@end

@implementation WXPayPrepareData

- (void)getPayData:(void(^)(id result, NSError *error))block {
    //根据请求参数,使用网络层组件调用API,并返回预支付信息
    block(result,nil);
}

@end

银联支付伪代码:

@interface UnionPayPrepareData : NSObject <PayDataPrepareProtocol>
@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<PayDataPrepareProtocol>)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<PayDataPrepareProtocol>)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文件中有该组件的使用详解,如果喜欢,点关注支持一下。

后记

如果本文对你有一点帮助的话,欢迎收藏、点赞,感谢。文中如有不对之处,也欢迎大家在评论区指出,共勉。文章来源地址https://www.toymoban.com/news/detail-496438.html

到了这里,关于iOS 微信、支付宝、银联支付组件的进一步设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity的GPUSkinning进一步介绍

      大家好,我是阿赵。   在几年前,我曾经写过一篇介绍GPUSkinning的文章,这么多年之后,还是看到不停有朋友在翻看这篇旧文章。今天上去GitHub看了一下,GPUSkinning这个开源的插件已经很久没有更新过了,还是停留在2017年的0.2.3版本。GPUSkinning的魅力在于可以在消耗比较

    2024年02月05日
    浏览(48)
  • 【Vue路由(router)进一步详解】

    本篇文章主要针对已经掌握Vue路由(router)基础以及路由嵌套的用户群体,如果你是Vue路由初学者的话,不仿先去看看 【Vue路由(router)的基本使用】这篇文章 接上一篇文章理解Vue路由中常用的知识点 在实际开发过程中,我们可能不单单要实现简单的页面跳转动作,可能在

    2023年04月08日
    浏览(44)
  • Druid未授权漏洞进一步的利用

    Druid是阿里巴巴数据库出品的为监控而生的数据库连接池。并且Druid提供的监控功能包括监控SQL的执行时间、监控Web URI的请求、Session监控等。Druid本身是不存在什么漏洞的,但当开发者配置不当时就可能造成未授权访问。本文除了介绍Druid未授权漏洞之外,还要讲的是一种该漏

    2024年02月11日
    浏览(45)
  • 数据结构--并查集的进一步优化

    压缩路径 − − F i n d 操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 color{red}压缩路径 -- Find操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 压缩路径 − − F in d 操作,先找到根节点,再将查找路径上所有结点都挂到根结点下 每次Find操作,

    2024年02月15日
    浏览(58)
  • 进一步了解WPF UI 实现XAML语法

    Extensible Application Markup Language (XAML) 是一种用于声明性应用程序编程的标记语言。 Windows Presentation Foundation (WPF) 实现 XAML 处理器实现并提供 XAML 语言支持。 WPF 类型的实现为 XAML 表示提供了必要的类型支持,从而确保了顺畅的集成和高效的运行。 在 XAML 标记中创建 WPF 应用程序

    2024年02月02日
    浏览(38)
  • [架构之路-203] - 对系统需求类型的进一步澄清

    目录 业务/商业需求: 用户/客户需求: 功能性需求: 非功能性需求: 系统需求: 约束条件: 软件需求说明书: 软件质量: 是自顶向下的需求,往往来自于中高层管理人员(或监管、政策要求),基于业务运营管理的直接诉求和要求。需要使用商业/工作语言描述业务/商业

    2024年02月07日
    浏览(70)
  • 频数表和列联表,以及进一步处理分析 -- R

    数据框包含了一些分类变量,问? 操作频数表 vcdӉ中的assocstats()函数可以计算二维列联表的phi系数,列联系数,Cramer‘s V系数 总体来说,较大的数值意味着较强的相关性

    2024年01月19日
    浏览(57)
  • GC 深入(小白,对gc有一个进一步的了解)

      一般这年轻代垃圾回收器,老年代垃圾回收器,如上图搭配着使用   1.8呢默认就是最后边那哥俩 有黑白灰三个颜色 最开始的颜色都是白色 刚找到这个对象的时候,把他标记成灰色,然后他的孩子级别的对象都找到时。 把他标记成黑色。他的孩子就是灰色了。 关于可达性

    2024年02月14日
    浏览(48)
  • 学习笔记---更进一步的双向链表专题~~

    目录 1. 双向链表的结构🦊 2. 实现双向链表🐝 2.1 要实现的目标🎯 2.2 创建+初始化🦋 2.2.1 List.h 2.2.2 List.c 2.2.3 test.c 2.2.4 代码测试运行 2.3 尾插+打印+头插🪼 思路分析 2.3.1 List.h 2.3.2 List.c 2.3.3 test.c 2.3.4 代码测试运行 2.4 尾删+头删🐊 2.4.0 思路分析 2.4.1 List.h 2.4.2 List.c 2.4.3 t

    2024年02月07日
    浏览(42)
  • pypdf 将 PDF两个页面拼接成一个页面进一步详解

    pypdf 原库名Pypdf2(已弃用,文档 PyPDF2 RectangleObject类_w3cschool) pypdf 官方文档 The Transformation Class — pypdf 3.17.4 documentation pypdf 将两个PDF页面在x轴,y轴进行平移调整位置之后,直接用merge_page拼接在一起,或者PageObject.create_blank_page 先创建一个空白页面,再将两个页面添加到空白页

    2024年01月24日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包