支付过程中的设计模式-状态模式(一)

目的

本文记录在工作中,使用到的一些设计模式。便于后续开发参考。

本文主要介绍支付过程中,使用到的状态模式。

支付流程

一般支付过程,包括

1. 生成待支付订单

2. 开始支付

3. 等待支付结果(一般都是异步通知的方式)

4. 处理结果

5. 支付成功/支付失败

支付状态

因此,在上述支付过程中,支付状态可以分为:

  • 初始状态

     该状态下,主要完成本地服务器订单创建,并向支付平台发起预支付请求。并由APP(小程序等客户端)发起实际支付操作。

若上述操作成功,则将状态转换成待支付状态。反之,则为支付失败状态。

  • 待支付状态

   该状态下, 本地服务器并不知道APP客户端支付的实际情况,在等待支付结果的异步通知。

在收到异步通知的时候,将待支付状态转换为支付中状态,表示本地服务器要开始处理支付请求了。

  • 支付中状态

    该状态下,表示本地服务器正在处理支付请求。 若用户支付成功,则将状态转换为支付成功状态。若用户支付失败,则将状态转换为支付失败状态。

  • 支付成功状态

    该状态下,表示整个支付过程结束,并支付成功了。

  • 支付失败状态

   改状态下,表示整个支付过程结束,并支付失败了。

整体状态转换过程如下:

初始状态
|___数据库插入待支付记录,向支付平台发送支付请求
|
待支付状态
|___支付结果通知到达,线程尝试获取处理权限(成功,则进入下一个状态;反之,任然停留在当前状态)
|
支付中状态
|___处理支付结果,根据结果进行状态转移(支付成功,则跳转到PaySucState; 支付失败,则跳转到PayFailState)
|
支付成功/支付失败状态

实现方式

AbstractPayState 状态父类
    定义了所有状态的共有模板。
    公共方法包括
    1. doActive --> 进行状态迁移请求(若成功,则返回true;失败,则返回false)
    2. submit --> 在状态迁移请求成功时, 正式提交该请求,实现真正的状态迁移。
    3. cancel --> 在状态迁移请求失败时, 取消改请求, 取消本地状态迁移。
    (PS: 上述过程中,类似mysql的事务, 先开启事务, 若事务中内容都成功处理,则提交;反之,则取消。)
InitState 初始状态
    表示流程开始,但是未发生任何实质交互,包括数据库记录, 微信通信等
UnpaidState 未支付状态
    当前状态下,已经在数据库中插入一条待支付记录,且统一下单接口已发送完成(微信交互成功)。
    但是,支付异步通知还没有发送到edianban服务器(以下简称e服务器)
PayingState 支付中状态
    当前状态下, 支付结果发送到e服务器, 且某一个线程已经获取了当前支付结果的处理权限(该
    状态用户多线程处理同一个订单请求时,只有成功变为PayingState状态的线程,拥有处理资格,
    其他线程则失去处理资格,直接跳过处理过程)
PaySucState 支付失败状态
    当前状态下,该支付结果为支付成功
PayFailState 支付失败状态
    当前状态下,该支付结果为支付失败

 

使用该设计模式的好处

1. 便于管理

我在实现例如微信支付的时候,不需要考虑,一个订单处理完一个阶段,下一步会调用哪个函数。

例如:

简单的支付结果处理的函数里面,在收到支付结果的时候,

1.1 都要先根据订单号查询数据库中是否存在该订单号的订单信息,若没有,则不处理。若有这个订单的信息,则继续判断。

1.2 该订单是否已经被处理。(一般异步通知的接口都会发多次,有幂等性问题)

1.3 同时,需要花费时间,进行加锁(若是分布式系统,则需要增加分布式锁来保证数据的一致性),处理并发性问题。

最终,导致开发者需要花费大量时间在非业务的代码中。

但是,使用状态模式的情况下,

开发者只需要关心在特定阶段,要实现哪些业务逻辑即可,而不需要关系并发,订单状态问题。

例如:

在收到支付结果的时候,

1.1 函数只需要调用状态类的doActive方法,即可调用对应的业务代码。

1.2 若当前订单不存在,则通过状态模式获取当前订单的状态为空。

1.3 若当前订单已经被处理, 则状态会直接迁移到支付成功/支付失败的状态(而不会再次调用处理结果的代码,解决幂等性问题)。

1.4 若同一个订单的多个通知同时到达服务器, 则只有一个线程能够取得处理权限(状态模式中的状态之间的转移,也考虑到了多并发的情况)。

2. 符合开闭原则

2.1 在接入多种支付方式的时候,对原有的支付方式无任何影响。只需要新增拓展新的状态类即可。

这样子可以大大减少开发和测试时间,不需要花费大量时间去做回归性测试(测试新增的支付方式会不会对已经存在的支付方式的功能有影响)。

3. 符合接口单一原则

3.1 状态类主要负责支付过程中状态转移,保证支付流程的完整可靠(功能包括状态转移,并发控制,事务控制等)。

3.2 业务代码类只需要实现业务代码, 不需要关心其他的非业务代码。

 

 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值