您将如何设计包括POST模拟的REST API?

例如我需要设计一个具有两个功能的API:付款验证和付款创建。 我需要两者,因为最终用户应该在真正确认付款创建之前就知道一切正常。 为了创造,我有

POST .../payment

带有输入正文。如果出现问题,它将返回HTTP 400。

验证(或 simulation )执行的过程与创建过程完全相同,只是在持久存储数据之前停止了该过程。对于此验证,最好有类似

的内容

解决方案1 ​​

GET .../is-payment-ok

也带有输入正文。它返回HTTP 200,其中包括布尔答案和一些详细信息。

这里的资源不是付款,而是关于付款有效性的信息,这对我来说似乎是REST兼容的。缺点是API用户可能会感到困惑,因为如果付款无效,则模拟将返回HTTP 200(主体中的布尔值设置为 false ),而创建将返回HTTP 400。

解决方案2

POST .../payment?simulation=true,or
POST .../payment-simulation

此处,HTTP响应代码与创建付款时的代码完全相同。缺点是我们使用POST,而没有实际“发布”任何资源。

你会怎么做?是否有REST规则或这种情况的常用做法?

lsw8142 回答:您将如何设计包括POST模拟的REST API?

虽然不是严格禁止的,但是GET请求通常没有请求正文:HTTP GET with request body,因此我不会使用解决方案1 ​​

在我们的API(也包括付款API)中,我们使用具有相同URL的查询参数来标记空运行(或在我们的域名中为 precast ),就像您的解决方案2 ,如此处所述:Dry run strategy for REST API。它会返回相同的错误代码和消息,这些错误代码和消息会在发生错误时产生非预测性的请求。

由于我们使用反应式付款处理器,因此我们需要此功能,但是只有在预付款成功后才启动。该过程开始后,该过程会立即将该预测结果作为响应返回给用户,从而提高了UI的响应度。实际付款将花费一秒钟的时间进行实际处理,因为某些支票会与其他服务进行反应。甚至可能失败,最终用户将收到有关最终状态的通知,但这很少见。

如果您查看HTTP规范,则POST处理资源的方式是相当随意的,则无需对任何内容进行永久更改:https://tools.ietf.org/html/rfc7231#section-4.3.3

  

POST方法请求目标资源处理      根据资源的要求包含在请求中的表示形式      自己的特定语义

     

[...]

     

如果已在原始服务器上将一个或多个资源创建为      成功处理POST请求的结果,原始服务器      应该发送包含Location标头的201(已创建)响应      为创建的主要资源提供标识符的字段      (第7.1.2节)和描述状态的说明      请求,同时引用新资源。

只需确保记录查询参数。 编辑:Kubernetes做到了:https://kubernetes.io/docs/reference/using-api/api-concepts/#dry-run

Stripe API有所不同,因为如果您发送请求,它将被预订,就不会空运行(/capture调用是由付款人而不是付款人进行的,因此它是另一个用例)。

,

我建议您创建2个端点,这通常在付款服务提供商(如UsaEPay,Stripe等)中完成。

第一个端点将类似于:POST .../authorize,并将接收进行付款所需的所有信息,例如金额,付款人信息和付款方式信息,然后它将创建一个paymentAuthorization如果授权成功,则返回authorizationToken的状态。

第二个端点将类似于:POST .../capture,在此端点中,您将仅查找与之前生成的paymentAuthorization相关的authorizationToken并继续进行付款>

您也可以查看Stripes文档https://stripe.com/docs/api/payment_intents,以了解有关这种系统结构的更多信息

,

我同意将选项2与两个端点一起使用以减少歧义的其他答案。

您在问题中使用“验证”一词,我相信它比模拟更好地传达了正在发生的事情。我希望模拟呼叫返回与付款相同的响应,但不允许付款通过。

验证请求将更直观地让用户知道API会评估该请求,并至少告诉您该请求是否可接受。

选项1将违反标准设计原则,因为GET请求通常会忽略主体(如果存在)。

按照域的uri路径设计,或使用其他答案中提到的某些资源。

POST .../Payment
POST .../Validate/Payment
,

根据您使用的付款类型,您可能会对两阶段提交方法感兴趣。与类似RPC的“是否可以”调用相比,这也更符合REST接口。
这里的想法是,您创建一个资源(我们将其称为付款授权POST /payment-authorizations),以确保所有资源都可用,在这种情况下,将用户的帐户保留为付款金额,并返回新付款的ID。

现在,用户可以查看付款(GET /payment-authorizations/{id})。
他们可以根据需要取消DELETE /payment-authorizations/{id},以释放资金。
或者他们可以将其定稿(PUT /payments/{id})。

这种方法的主要优点是

  • 这是RESTfull
  • 付款是幂等的(您可以尝试完成多次付款,但一次只能汇款一次)
  • 付款验证步骤实际上是有用的

在最后一项上做更多详细说明:您正在进行的这些API调用是异步的,并且完全有可能出现竞争条件。您可能会遇到类似

的情况
Alice                        Alice's Account    Chuck
                                  $10
"can I send $5 to Bob?" ->        
                        <-       "yes"  
                                             <- "can I withdraw $6 for rent?"
                                 "yes"       ->
                                             <- "withdraw $6 for rent"
                                 "ok"        ->
                                  $4
"send $5 to Bob"        ->
                        <- "insufficient funds"

现在您的客户很困惑,系统表示可以付款,但不能付款。通过两阶段提交,您将拥有

Alice                        Alice's Account    Chuck
                                  $10
"authorize $5 to Bob" ->      "ok,authz #5"
                                  $5(+5)
                                             <- "authorize $6 for rent"
                        "insufficient funds" ->
"send payment #5"     ->         "ok"
                                  $5

现在,爱丽丝仍然不知所措,但是我们给出的所有答案都是准确的。

,

如我所见,您对URI路径设计感兴趣。

通常:

  • 单数名词用于将单个文档资源引用到您的URL中。
  • 复数名词用于指代集合或存储。
  • 句柄表示动作,可以将其视为控制器,例如 Validate Store

在REST中,POST类型的请求可用于在集合中创建新资源或执行控制器。因此,使用Post似乎是您API的正确选择。

现在,根据您的情况,您需要执行两个操作 Create Validate

在您的情况下,我将创建两个可能的URL,一个用于创建付款,另一个用于验证它,发送付款ID。

POST .../Create/Payment
POST .../Simulate/Payment/{IdPayment}

我将“付款”视为单个文档,并将“ 创建”和“ 模拟”作为控制者。在“模拟”的情况下,我在“付款”文档中添加了一个ID以进行识别。

有一本O'Reilly的书,它易于阅读,并包含您所需要的所有信息。这本书是REST API Design Rulebook

我希望这些信息对您有所帮助。

本文链接:https://www.f2er.com/3112426.html

大家都在问