欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-22 22:57:04
...

目的

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

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

支付流程

一般支付过程,包括

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 业务代码类只需要实现业务代码, 不需要关心其他的非业务代码。

 

 

 

相关标签: 支付