Order life cycle in drupal commerce

Drupal commerce has rather good documentation for D8 commerce but I will try to summarise here how each order is made, what it needs to be completed and what goes on in lifespan of an order.
So lets start by order entity it self, check

namespace Drupal\commerce_order\Entity 

class Order extends CommerceContentEntityBase implements OrderInterface {

and lets check baseFieldDefinitions method, you will see there are 3 required fields, order_id, state and store, all the rest will be filled in during order life cycle. One of the first things that will be filled is UID, which is entity reference field. Then there is billing_profile, which is also reference field, there is adjustments field, which is reference to adjustments done on order total(discounts). In the end there is bunch of "flags" and values fields like total_price, data field which is a "map" type field and is "serialized array of additional data" where you can store whatever you might need extra when using orders, various time/date fields, state(check) etc.

If you check Database table of commerce_order, you will see there is more columns there. Like different payment columns, they come from other module, payment module. It is done the old school drupal 7 way with hooks, check the commerce_payment.module and see commerce_payment_entity_base_field_info. This  is where we hook into order entity and add this 2 reference fields, payment_gateway and payment_method. Payment method is reference to saved payment method ID and payment_gateway is name of configuration entity of particular payment we are using for this order. In similar way commerce_checkout module adds checkout_flow entity reference field and checkout_step which is just a string name of step this order is on.

So lets move to CART as this is first step of order journey, cart is basically our order displayed with a View, as you can see it here 

namespace Drupal\commerce_cart\Controller 

class CartController extends ControllerBase {

this is controller that displays our view with building a "build" array in cartPage method, with order id and html tags to build a form. This is all called and displayed in renderer class but this part is not something we will cover here. At this point our order DB row is mostly empty as we didn't define much, order items(line items in d7) data is not stored in commerce_order table, this can be found in commerce_order_item table and each item is referenced to order it belongs to. Cart items get added through 

namespace Drupal\commerce_cart 

class CartManager implements CartManagerInterface {

 there is addOrderItem method that fires on adding items to cart, there is also updateOrderItem, that updates items when for example you update number of items in cart.

Moving on to next step, when we click checkout button we start to get into checkout process, which is just an abstraction for lots of forms. Depending on your checkout flow you will encounter different checkout panes, they can be custom created, or imported as part of some payment gateway but most commonly there will be default drupal commerce panes in default checkout flow so we will cover them here. 
So first we will encounter billing info pane which is at 

namespace Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane

class BillingInformation extends BillingInformationPaneBase {

and in buildPaneForm there is an  inline_form which builds billing information form and collects data we enter, once we submit this form this data goes into db and is saved to commerce_order table as reference id. Similar thing happens with shipping info pane but a bit more complex and shipping reference is not saved in commerce_order table but is similarly referenced as commerce_order_item table to commerce_order. There is also contact information pane which just saves email to order when you are not logged in.
Also in this checkout step it is often or rather by default added payment information pane, this is pane which has story by itself and it needs special section.

So payment info pane, this is where we are dealing with payments. So dig into 

namespace Drupal\commerce_payment\Plugin\Commerce\CheckoutPane 

class PaymentInformation extends BillingInformationPaneBase {

and see how form is built, buildPaneForm is checking for possible payment gateways for this order, 

$payment_gateways = $payment_gateway_storage->loadMultipleForOrder($this->order);

this line fetches all payments that pass all conditions for order we are dealing with and that can be set on admin of payment gateways through UI. Once we have available gateways, form is built so you can choose them with select option, with default gateway rendered, when you switch to other, then new default is rendered and set over previous one through ajax. This is also place where previously saved payment_methods are displayed, payment_method is tokenized data about user payment method, saved per particular user, so her we can reuse it for repeated purchase. They are created after this form is submitted, but once you come again to this pane, you can see previous ones used and saved.
Payment forms are created through buildPaymentMethodForm method, this is the part where we are calling particular payment gateway form with inline form

$inline_form = $this->inlineFormManager->createInstance('payment_gateway_form', ['operation' => 'add-payment-method',], $payment_method);

this will check our payment gateway main class and its annotations, for example if we are using stripe, in 

namespace Drupal\commerce_stripe\Plugin\Commerce\PaymentGateway 

class Stripe extends OnsitePaymentGatewayBase implements StripeInterface {

there is definition to where we can find "add-payment-method" form for this payment, it is here
 

  forms = {
 *     "add-payment-method" = "Drupal\commerce_stripe\PluginForm\Stripe\PaymentMethodAddForm",
 *   },

For offsite payments this will be different and wont be rendered here in this pane. Once we submit this pane, we are triggering submitPaneForm which will ultimately
 set this 2 reference fields to order and this will be visible in commerce_order DB table

$this->order->set('payment_gateway', $payment_method->getPaymentGateway());
$this->order->set('payment_method', $payment_method);

Before all that, submit method will check if this gateway supports saving of payment method with

if ($payment_gateway->getPlugin() instanceof SupportsStoredPaymentMethodsInterface) {

if not it will not use one and not save one to order, as this is not required, if it supports it, we will check do we reuse one or we use a freshly set one from form. Also if we are using saved payment method, then here it will be assigned to order along with billing which is associated with this payment method (so user doesn't have to enter that as well).

Before we leave PaymentMethodAddForm class, lets check what it inherits, for stripe payment it is defined as
class PaymentMethodAddForm extends BasePaymentMethodAddForm which is alias for original PaymentMethodAddForm,
so lets check original PaymentMethodAddForm class in 

namespace Drupal\commerce_payment\PluginForm

class PaymentMethodAddForm extends FormBase implements ContainerInjectionInterface {

it has important buildConfigurationForm which calls buildCreditCardForm method, which is defined in this class but also overridden in Stripe PaymentMethodAddForm

    if ($payment_method->bundle() == 'credit_card') {
      $form['payment_details'] = $this->buildCreditCardForm($form['payment_details'], $form_state);
    }

using this, we are using payment details to build a basic credit card form and in the end also to submit this details we get there with submitConfigurationForm, this submit is the one that is basically creating payment_method as we are calling

$payment_gateway_plugin->createPaymentMethod($payment_method, $values['payment_details']); 

method which is again defined per payment gateway, so in stripe it can be found in stripe class and what it does.

Once we submit this forms there is review step and review pane, nothing much happens here, it is just for review and some payment gateways have put here 3DS offsite auth but I am more inclined to remove this step and just skip to the payment process step as this is the place the most important things happen, payments. So lets dive into

namespace Drupal\commerce_payment\Plugin\Commerce\CheckoutPane 

class PaymentProcess extends CheckoutPaneBase {

we are again interested in buildPaneForm method, this is where all logic is happening. So we are creating basic payment entity with

$payment = $payment_storage->create([

and after that we are checking is it onsite or offsite or manual payment method and if it is onsite we have crucial method call here

$payment_gateway_plugin->createPayment($payment, $this->configuration['capture']);

which calls main method in chosen payment gateway and is required by onsite payment interface, for example lets use stripe again where we go to Stripe class and then check createPayment method. This is where Stripe API is used and we make different calls to authorize or/and capture funds we need to get. We get response from remote site (stripe) and we can use this info to put into out payment entity and save it. In stripe class there is also capturePayment, voidPayment and refundPayment, these can be used for custom actions we can provide in our custom modules (modules for auto approval and capturing of orders) or used in admin UI forms to do those actions. Once this pane is done, we are going to final step of checkout, which is complete, in that moment our order has all the data filled in and on that last step we add some messages, surveys, logins for anonymous etc. Before we finish off, lets just check structure of payment entities and what is added there.

So payment entity at 

namespace Drupal\commerce_payment\Entity 

class Payment extends ContentEntityBase implements PaymentInterface {

lets skip all the other methods and go to baseFieldDefinitions method which defines our DB fields, 
we have reference to payment_gateway and payment_method reference to we are using for this payment, then there is order_id reference field and most importantly remote_id string field, which is where we reference ID of remote payment, this ID will be used for capturing funds or refund/voids, there is also state field and other dates field that will complete this entity and information it stores. Payment gateway entity or rather commerce_payment_gateway  is a config entity we are referencing from payment entity and as it is not content entity it doesn't define fields, it depends on config or particular payment gateways and where they are defined. Finally we have 

namespace Drupal\commerce_payment\Entity

class PaymentMethod extends ContentEntityBase implements PaymentMethodInterface {

PaymentMethod class and entity, which is content entity and has entity reference field to saved payment methods, we have field for user it belongs to and billing_profile that is associated with this payment method. There is also remote_id info and expires field so we know when does this payment method expires, finally there are dates fields and field that stores info if this method is reusable, but this kind of beats the purpose of storing the method so its not clear why we should have this.