vuestorefront / vue-storefront-1

The open-source frontend for any eCommerce. Built with a PWA and headless approach, using a modern JS stack. We have custom integrations with Magento, commercetools, Shopware and Shopify and total coverage is just a matter of time. The API approach also allows you to merge VSF with any third-party tool like CMS, payment gateways or analytics. Newest updates: https://blog.vuestorefront.io. Always Open Source, MIT license.
https://www.vuestorefront.io
MIT License
18 stars 13 forks source link

[RFP] New Checkout structure #47

Closed bloodf closed 3 years ago

bloodf commented 3 years ago

From vue-storefront created by pkarw: vuestorefront/vue-storefront#3024

Summary

[summary]: We need to refactor the Checkout page to be more flexible, easy to extend and get rid of the current way of adding payment/shipping modules which are solely based on the Event Bus (#3020)

This is the open request for proposals/feedback on how the best possible Checkout feature should work like from the developers perspective.

Motivation

[motivation]: We're moving towards https://storefrontui.io to be used in the themes. Current checkout is pretty messy, based on events - hard to extend and to event understand to be the new-comers. The idea is to make the payment/shipping modules less error prone plus increase the extensibility (adding/removing/changing) of the checkout steps.

Guide-level explanation

It would be great to focus on the following features of the checkout with the proposals - on which we'll form the final design for the Checkout feature:

  1. How to hook-in into checkout process - currently there are events like https://github.com/danrcoull/vsf-payment-braintree/blob/d42a2e6f2ccc227aad6c183ea8c089da032a73cb/hooks/beforeRegistration.ts#L25 that modules hook in. How should it be handled?
  2. How to override the Checkout components? Should it be kind of API like dispatch('checkout/addStep'),dispatch('checkout/removeStep') ... ?
  3. How to modify/extend the Checkout UI - especially the payment modules should have an option to hook in and add some forms / inject JS code. For example, the stripe module is expecting us to add the UI manually (probably it's not an optimal way): https://github.com/develodesign/vsf-payment-stripe#integration-the-stripe-component-to-you-theme
  4. How to handle the validation? Should we stick to the Vuelidate that we're using currently or switch to another library? How to hook in the validation process for the custom steps?

Happy to hear Your comments / code snippets / requests on this feature./

bloodf commented 3 years ago

I will probably extend this suggestion soon but generally everything should be Vuex-driven and as simple as possible.

Ideally we should have Vuex state fields for:

Also getters + setters/validators as flags true/false (actions) for all above + placeOrder method. Then we can simply consume all of those in a frontend no matter if it's a one-step checkout, multi-step checkout etc.

Also we should have actions related to cache regarding shipping and personal details.

The Vuex implementation shouldn't force any form of checkout steps. People can either validate let's say personalDetails after filling part fo the form or validate all of the fields at the end at once (by calling all validators)

Also in state we should place a field called "custom" which is just an object containing custom data. Let's say we are adding new field called Foo so it will be held under custom.foo and there should be a getter called getCustom('foo') (and mutation) that return/set custom fields.

bloodf commented 3 years ago

@dimasch @lukeromanowicz @lukeromanowicz @filrak @patzick @Igloczek would be great to get Your feedback on that :)

bloodf commented 3 years ago

here are my 2-cents on this topic; I would expect VSF not to care about what goes into an order, and as a consequence not to have any required fields for the checkout.

Whatever fields are there were defined by the developer, and are posted to the backend platform. We can introduce some interfaces that help with suggesting the fields either Shopware, Magento or whatever other system is expecting, but again it's a suggestion.

Payment is separate. Methods are fetched, a choice is made by the user. Once the order is dispatched we take the chosen payment method and send the authorization request to the PSP. This gets us a response that triggers a visual notification for the user.

The actual payment registration in the order in the backend platform is outside of the scope of Vuestorefront. The PSP can use callback and notification URLs for that.

bloodf commented 3 years ago

Hi, it would be great if the checkout redesign utilizes a dedicated confirmation page, since most external payment gateways need a page to redirect to, where the order is finally placed and confirmed - something which is not possible with the current checkout (though it is not hard to build an extra page which places the order on theme level).

bloodf commented 3 years ago
bloodf commented 3 years ago

The question is WHO is going to prepare a PoC? :)

bloodf commented 3 years ago

Thanks for Your feedback. Having this in mind I would say we need to:

  1. Propose an interface for the payments method to comply with.

To change the current way they register:

    // Update the methods
    let paymentMethodConfig = {
      'title': 'Cash on delivery',
      'code': 'cashondelivery',
      'cost': 0,
      'costInclTax': 0,
      'default': true,
      'offline': true,
      'is_server_method': false
    }
    rootStore.dispatch('payment/addMethod', paymentMethodConfig)

to something like:

    // Update the methods
    let paymentMethodConfig = {
      meta: {
      'title': 'Cash on delivery',
      'code': 'cashondelivery',
      'cost': 0,
      'costInclTax': 0,
      'default': true,
      'offline': true,
      'is_server_method': false
}, 
handler: { // kind of state-machine for payments
    init: (checkoutData) => {},  // called whtn user selects this method
    create: (checkoutData) => { }, // called when the order has been placed and we can create the payment
    authorize: (checkoutData) => { }, // called back on the approval 
    cancel: (checkoutData) => {} // called back on canceling the payment flow
}
    }
    rootStore.dispatch('payment/registerMethod', paymentMethodConfig)

.. so the handler lifecycle methods are called instead of current events:

checkout-before-placeOrder

and then

checkout-do-placeOrder

which is in fact called back by the payment method. So we need to take over the control of the process from payment method fully to the Checkout.

  1. Make the checkout fields really dynamic - manageable 100% in the theme. The Vuex store should be just for placing an order (prepared in the Checkout theme component and validated beforehand). Kind of current prepareOrder.

  2. The Vuex store of order and checkout should be merged all into one single checkout module.

  3. The checkout Vuex state should be not typed - to not have static "persionalDetails" whatsoever. The User's checkout should be able to register these sections like: dispatch('checkout/addSection', { name: 'personalDetails' }) of course there should be also dispatch('checkout/removeSection').

The idea we discussed was to make Vuex completely unaware of the checkout state @patzick but it's not probably something we can do as the for example cart/syncTotals requires the data from checkout to estimate shipping costs.

So I agree with @filrak that we should have some defaults + getters for them (as we currently have in the checkout module) + extend it for a user to let them register another section.