我正在做与支付服务的集成。我还得登上一艘商船。要登录商家,我需要遵循以下步骤
- 创建支付服务用户,如果创建成功:POST api call
- 创建上一步中创建的用户的业务配置文件:POST api call
- 为用户创建支付配置文件:POST api call
- 注册一个回调url,用于接收webhook的交易状态更改,用于该用户的支付:POST api调用
如果任何步骤失败,我只需要从该步骤重试。我不能从头开始。
我的解决方案:
我正在维护一个状态对象,用于用户的登录。状态对象有4个字段
- userCreated
- businessProfileCreated
- paymentProfileCreated
- webhookRegistered
每一步我设置各自的状态属性为真,并保存它。
Algotithm:
初始化状态对象all
state.userCreated = false;
state.businessProfileCreated = false;
state.paymentProfileCreated = false;
state.webhookRegistered = false;`
if(state.userCreated != true)
create user
if create profile **not** success
save state
return
state.userCreated = true
if(state.businessProfileCreated != true)
create business profile
if businessProfile creation **not** success
save state
return
state.businessProfileCreated = true
如果状态。= true创建支付配置文件如果支付配置文件创建不成功保存状态返回state.paymentProfileCreated
如果状态。webhookRegistered != true):创建webhook配置文件保存状态返回
state.paymentProfileCreated保存状态">
我需要一个干净的方式来做这件事,也处理api失败。是否存在此任务的模式
也许其他人有更好的想法,但我想到的是策略模式的修改版本。(参见https://en.wikipedia.org/wiki/Strategy_pattern)
要实现这一点,你需要一个要执行的函数列表(策略),你需要编写一些代码来遍历列表,调用函数,检查结果,并通过存储失败函数的索引来跟踪错误发生的位置,而不是使用一堆布尔标志。
如果您决定使用这种模式,您的问题是不同的函数可能需要不同的参数,并且使事情更加复杂的是,某些函数可能依赖于先前调用的函数返回的某些结果。要解决这个问题,您必须将这些函数可能需要的所有信息存储到一个单独的对象中,并将该对象传递给每个函数,以便它们可以根据需要从该对象中读取字段并向其写入字段。
这可能是不值得的麻烦,它可能不会让读者更清楚正在发生什么。
考虑保持现有代码的结构,只是改进它,例如:
-
使用一个枚举来告诉你你走了多远,而不是一堆布尔值;
-
移动新函数中的所有步骤,并修改每个错误检查,使其返回失败指示,而不是保存状态然后返回。然后,从调用该函数的地方,检查它是否指示错误,如果是,只在一个地方保存状态。
这是可以使用状态模式的地方。正如wiki所说:
状态模式是一种行为软件设计模式,允许对象在其内部状态改变时改变其行为。此模式接近有限状态机的概念
让我来演示一下如何通过c#实现它。
这是一个将按顺序运行多个API的类:
public class APIMachine
{
IState _userState;
IState _callbackState;
IState _paymentState;
IState _businessState;
public string Run()
{
_userState = InitializeState();
_userState.Do();
return _callbackState.GetResult().ToString();
}
private IState InitializeState()
{
_callbackState = new CallbackState();
_paymentState = new PaymentState(_callbackState);
_businessState = new BusinessState(_paymentState);
return new UserState(_businessState);
}
}
这是所有状态的抽象:
public interface IState
{
void Do();
bool HasSuccess { get; set; }
int RetryCount { get; }
object GetResult();
}
这是UserState
的一个具体实现:
public class UserState : IState
{
IState _state;
public UserState(IState state) => _state = state;
public int RetryCount => 3;
public bool HasSuccess { get ; set ; }
public void Do()
{
int count = 0;
while (count <= RetryCount)
{
// Make post request here to create user
HasSuccess = true;
if (HasSuccess)
{
_state.Do();
break;
}
count++;
}
}
public object GetResult()
{
throw new NotImplementedException();
}
}
:
public class BusinessState : IState
{
IState _state;
public BusinessState(IState state) => _state = state;
public int RetryCount => 3;
public bool HasSuccess { get; set; }
public void Do()
{
int count = 0;
while (count <= RetryCount)
{
// Make post request here to create business profile
HasSuccess = true; // if post request is okay
if (HasSuccess)
{
_state.Do();
break;
}
count++;
}
}
public object GetResult()
{
throw new NotImplementedException();
}
}
:
public class PaymentState : IState
{
IState _state;
public PaymentState(IState state) => _state = state;
public int RetryCount => 3;
public bool HasSuccess { get; set; }
public void Do()
{
int count = 0;
while (count <= RetryCount)
{
// Make post request here to create payment profile
HasSuccess = true; // if post request is okay
if (HasSuccess)
{
_state.Do();
break;
}
count++;
}
}
public object GetResult()
{
throw new NotImplementedException();
}
}
:
public class CallbackState : IState
{
public int RetryCount => 3;
public bool HasSuccess { get; set; }
public void Do()
{
int count = 0;
while (count <= RetryCount)
{
// Make post request here to create payment profile
HasSuccess = true; // if post request is okay
if (HasSuccess)
{
break;
}
count++;
}
}
public object GetResult()
{
return "foobar.com";
}
}
上面的代码可以这样运行:
APIMachine apiMachine = new();
string callbackUri = apiMachine.Run();
输出:foobar.com