结账模块如何处理订单
本文将深入探讨结账流程的内部机制。更具体地说,当用户点击“提交订单”按钮后会发生什么。
结构
以下区域与处理用户的结账过程相关。
支付注册表 (文件)
支付注册表存储每个支付方法的所有配置信息。 我们可以使用 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() 函数,以便在将付款方式显示给用户作为可选项之前进行验证。