SPA-基于服务器端验证的操作确认

时间:2020-09-05 23:02:09

标签: rest architecture single-page-application software-design webapi

我正在寻找可重用的解决方案,以解决用户执行的某些操作在完成之前可能需要用户进一步确认的问题。

我正在使用React前端和WebAPI后端开发应用程序。

假设用户正在启动资金转帐,并假设我们在启动转账之前无法在其帐户客户方检查可用资金。当用户(通过HTTP POST)提交请求时,如果用户的帐户中有足够的资金,则请求应正常完成;而如果资金不足,并且用户处于透支额度之内,则仅在以下情况下才提示用户使用透支:用户确认要使用透支,请求应完成。

另一种情况是,假设用户想要删除一个收款人帐户(通过HTTP DELETE)。没有针对收款人帐户的定期付款设置时,删除应该正常完成。如果存在定期付款设置,则应进一步提示用户(检查定期帐户只能在服务器端进行,并且仅在需要时才进行(因此,不能提前这样做并提供给客户端)。 / p>

我确信这在任何应用程序中都是常见的情况,但是在Internet上找不到合理的解决方案。

预先感谢

1 个答案:

答案 0 :(得分:2)

这种情况并不常见,不是很多-您对此提出了怪异的要求。在理想的设计中-您会要求客户打开透支功能,这可能是对api/settings端点的单独API调用。您正在将其与常规请求有效负载结合使用,这会使事情变得稍微复杂一些。

您只需要足够详细的响应合同和一个可以处理这些情况的前端即可。

我在下面嘲笑一个。

这是您在以下转帐案例中所具有的内容。您可以修改其中一些响应合同,使其更具描述性,以便处理更多案件。

  1. 启动从客户端(react-app)到服务器的传输请求。传递详细信息。请注意,您将其标记为DirectTry
  2. DirectTry由于帐户资金问题而失败//但您已确认可以透支。我们在字典中添加了Guid和交易信息(即客户信息),以防万一客户希望验证透支。您可能也应该在这里到期。
  3. 将提示状态返回到react-app。您可以通过从服务器传递到客户端We need you to approve going into overdraft for this transaction的消息/后续状态等来扩展此操作...我们还传输了guid,只是为了确保它实际上是同一设备,同一事务要求启用透支。
  4. 在react-app端,您会看到提示状态,启动一个通知组件,说单击此处批准您的透支。
  5. 您单击“批准”,并且相同的guid通过不同的属性袋传递到服务器端,表明这现在也允许透支。
  6. 交易进行。

public enum State
{
   // everything worked
   Done,

   // error - no retry needed.
   CriticalError,

   // additional prompt
   Prompt,
}

public class ServiceResult
{
   // some state.
   public State State { get; set; }

   ... some other props...
}


/// Part of some api controller
[Route("api/funds")]
[HttpPost]
public async Task<ServiceResult> TransferFunds(FundTransferPayload payload)
{
   // ... do some ops.
   ValidationResult validationResult; = new ValidationResult();
   if (payload.OperationType == OperationType.DirectTry)
   {
       validationResult = new ValidationResult();
   }
   // pass the guid we returned to front-end back to service to make sure
   else if (payload.OperationType == OperationType.PromptProvided)
   {
      validationResult = ValidateOp(
           ValidationDictionary[payload.promptGuid],
           payload.customerId,
           payload.operationType,
           payload.operationId);
   }

   var transferResult = await SomeService.SomeOps(validationResult);
   if (transferResult.Succeeded) {...}
   else if (transferResult.NeedsOverdraft)
   {
      var someGuid = new Guid();
      ValidationDictionary.Add(new Key(someGuid), new Value(payload.customerId, 'overdraft', transferResult.operationId));
      return new ServiceResult() { State=Prompt, ...otherprops... };
   }
   else if (transferResult.Failed) {...}
}

在您的前端这样的东西...


axios.post('/api/funds', {
    operationType: 'DirectTry',
    ...some other props...
  })
  .then(function (response) {
    if (response.data.state === 'Prompt') {
      // save the guid or whatever token you're using - you'll call your API again with that.
      // change the UX with the prompt. Upon prompt, fire the request appropriately.
    }
  });