跳到主要内容

结账模块如何处理订单

本文将深入探讨结账流程的内部机制。更具体地说,当用户点击“提交订单”按钮后会发生什么。

结构​

以下区域与处理用户的结账过程相关。

支付注册表 (文件)​

支付注册表存储每个支付方法的所有配置信息。 我们可以使用 registerPaymentMethod 和 registerExpressPaymentMethod 函数在此处注册新的支付方法,这些函数也供其他插件使用。

数据存储​

数据存储用于跟踪可能在用户会话期间发生变化的数据,例如,当前使用的支付方法、结账是否存在错误等。 我们根据关注的领域对这些数据存储进行分割,因此我们有两个与结账相关的数据存储:wc/store/checkout (文件) 和 wc/store/payment (文件)。 数据存储位于 assets/js/data 文件夹中。

上下文 (Contexts)​

上下文用于将数据提供给结账模块。 每个上下文都通过钩子提供与特定领域相关的数据和函数。 例如,如果我们要使用 PaymentEventsContext 上下文中的 onPaymentSetup 句柄,可以这样操作:

const { onPaymentSetup } = usePaymentEventsContext();

上下文的另一个作用是为我们的结账模块运行副作用。 通常,CheckoutEvents 和 PaymentEvents 会监听结账和支付数据存储的变化,并根据某些逻辑,基于这些变化分发操作到这些存储中。

例如,在 CheckoutEvents 上下文中,当结账状态为 before_processing 时,我们会分发 emitValidateEvent 操作。 还有很多类似的逻辑,它们会响应来自这两个存储的状态和数据的变化。

结账上下文包括:

上下文描述
CheckoutEvents提供与结账相关的事件句柄
PaymentEvents 提供与支付相关的事件句柄
CustomerData 提供与当前客户相关的数据
ShippingData 提供与配送相关的错误数据和操作

结账处理器 (checkout-processor.js)​

结账处理器组件会订阅结账或支付数据存储的变化,将部分数据打包起来,并在满足条件时调用 Store API 的 /checkout 接口。

结账提供者​

结账提供者 将上述所有上下文封装在 CheckoutProcessor 组件中。


结账用户流程​

以下是完整的结账流程:

1. 点击“提交订单”按钮​

结账流程从用户点击按钮开始。

2. 结账状态设置为 before_processing 文件​

当用户点击“提交订单”按钮后,我们将结账状态更改为 "before_processing"。 在这里,我们处理结账信息的验证。

3. 触发 checkout_validation_before_processing 事件 文件​

在这里,WooCommerce Blocks 插件和其他插件可以注册事件监听器来处理验证。 此事件的监听器将运行,如果存在错误,我们将结账状态设置为 idle 并向用户显示错误。

如果没有错误,我们将进入下面的第 4 步。

4. 结账状态设置为 processing 文件​

processing 状态由下面的第 5 步用于更改付款状态。

5. 付款状态设置为 processing 文件​

在完成所有结账处理并且没有错误后,付款处理开始。

6. 触发 payment_processing 事件 文件​

触发 payment_processing 事件。 其他插件可以注册此事件的监听器并运行自己的代码。

例如,Stripe 插件在这里检查地址和付款详情,并使用 Stripe API 在 Stripe 中创建客户和付款参考。

重要提示:实际的付款操作不是在这里进行的。它像一个预付款钩子,用于在尝试实际付款之前运行任何付款插件的代码。

7. 执行 payment_processing 事件监听器,并根据情况设置付款和结账状态 (file)​

如果注册的事件监听器返回错误,我们将向用户显示该错误。

如果事件监听器被认为是成功的,我们将同步结账的地址与付款地址,将 paymentMethodData 存储在付款存储中,并设置付款状态属性 { isProcessing: true }。

8. POST 请求发送到 /wc/store/v1/checkout (file)​

如果不存在付款错误,则会调用 /checkout StoreApi 端点。该端点会获取最终的客户地址和选择的付款方式,以及任何其他付款数据,然后尝试付款并返回结果。

重要:付款尝试是通过 StoreApi 进行的,而不是通过从客户端发送的 payment_processing 事件。

9. 触发 processCheckoutResponse 操作,该操作作用于结账存储 (file)​

一旦对 StoreApi /checkout 端点的请求返回响应,我们将该响应传递给 checkout 数据存储中的 processCheckoutResponse 操作。

它将执行以下操作:

  • 它设置重定向 URL,用于在订单完成后重定向到该 URL。
  • 它将付款结果存储在 checkout 数据存储中。
  • 它将结账状态更改为 after_processing(步骤 10)。

10. 将结账状态设置为 after_processing (file)​

after_processing 状态表示我们已完成主要的结账处理步骤。在此步骤中,我们执行清理操作,并显示在上一步骤中触发的任何错误。

11. 发出 checkout_after_processing_with_success 事件 (file)​

如果没有错误,则会触发 checkout_after_processing_with_success 事件。这是其他插件可以在结账过程成功后运行代码的地方。

在 checkout_after_processing_with_success 事件上注册的任何事件监听器都将被执行。如果事件监听器没有返回错误,则会调用 checkout 数据存储中的 setComplete 操作,以将状态设置为 complete(步骤 13)。事件监听器也可能在此处返回错误,该错误将显示给用户。

12. 发出 checkout_after_processing_with_error 事件 (文件)​

如果从第 5 步出现错误,则会发出 checkout_after_processing_with_error 事件。 其他插件可以注册事件监听器,以便在此处向用户显示错误。 事件监听器会被处理,并将任何错误显示给用户。

13. 将结账状态设置为 complete (文件)​

如果没有错误,则在结账数据存储中的 status 属性会更改为 complete。 这表示结账流程已完成。

14. 重定向 (文件)​

一旦结账状态设置为 complete,如果存在 redirectUrl 在结账数据存储中,则会将用户重定向到该网址。

其他值得注意的事项​

检查付款方式​

一个付款方式会与一个 配置对象 关联。它必须包含一个名为 canMakePayment 的函数。如果该付款方式可以用于支付当前的购物车,则该函数应返回 true。当前的购物车(商品、地址、配送方式等)会传递给此函数,并且每个付款方式负责报告它是否可用。

checkPaymentMethodsCanPay() 函数 会遍历所有已注册的付款方式,检查它们是否可用,如果可用,则将它们添加到支付数据存储器上的 availablePaymentMethods 属性。

必须在几个地方调用 checkPaymentMethodsCanPay() 函数,以便在将付款方式显示给用户作为可选项之前进行验证。