Skip to content
intermediate Phase 45 · Checkout Fundamentals

Shipping and Payment in Checkout

Address handling, shipping method selection, and payment method selection in the checkout process

45m
0 problems
Topic Progress 0%

Address Handling

Quote Address Model

// Magento\Quote\Model\Quote\Address
namespace Magento\Quote\Model\Quote\Address;

class Address extends \Magento\Framework\DataObject implements
    \Magento\Quote\Api\Data\AddressInterface
{
    /**
     * Address types
     */
    const TYPE_SHIPPING = 'shipping';
    const TYPE_BILLING = 'billing';

    public function getAddressType(): string
    {
        return $this->getData('address_type');
    }

    public function getCountryId(): string
    {
        return $this->getData('country_id');
    }

    public function getRegion(): ?\Magento\Directory\Api\Data\RegionInterface
    {
        return $this->getData('region');
    }

    public function getPostcode(): ?string
    {
        return $this->getData('postcode');
    }
}

Setting Addresses on Quote

namespace Vendor\Checkout\Service;

class AddressManager
{
    public function __construct(
        private \Magento\Quote\Api\CartRepositoryInterface $cartRepository
    ) {}

    public function setShippingAddress(
        int $cartId,
        array $addressData
    ): void {
        $quote = $this->cartRepository->get($cartId);

        $address = $quote->getShippingAddress();
        $address->addData([
            'firstname' => $addressData['firstname'],
            'lastname' => $addressData['lastname'],
            'street' => $addressData['street'],
            'city' => $addressData['city'],
            'region' => $addressData['region'],
            'region_id' => $addressData['region_id'],
            'postcode' => $addressData['postcode'],
            'country_id' => $addressData['country_id'],
            'telephone' => $addressData['telephone'],
            'email' => $addressData['email'],
        ]);

        $this->cartRepository->save($quote);
    }

    public function setBillingAddress(int $cartId, array $addressData): void
    {
        $quote = $this->cartRepository->get($cartId);

        $billingAddress = $quote->getBillingAddress();
        $billingAddress->addData($addressData);

        // Same as shipping checkbox
        if (!empty($addressData['same_as_shipping'])) {
            $quote->getShippingAddress()->setSameAsBilling(1);
        }

        $this->cartRepository->save($quote);
    }
}

Shipping Method Selection

Shipping Method Assignment

namespace Vendor\Checkout\Service;

class ShippingManager
{
    public function __construct(
        private \Magento\Quote\Api\CartRepositoryInterface $cartRepository,
        private \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
    ) {}

    public function collectShippingRates(
        int $cartId,
        string $addressId = 'shipping'
    ): array {
        $quote = $this->cartRepository->get($cartId);
        $address = $quote->getShippingAddress();

        $rates = $address->collectShippingRates()->getGroupedAllShippingRates();

        $availableMethods = [];
        foreach ($rates as $carrierRates) {
            foreach ($carrierRates as $rate) {
                $availableMethods[] = [
                    'carrier' => $rate->getCarrier(),
                    'method' => $rate->getMethod(),
                    'carrier_title' => $rate->getCarrierTitle(),
                    'method_title' => $rate->getMethodTitle(),
                    'price' => $rate->getPrice(),
                ];
            }
        }

        return $availableMethods;
    }

    public function setShippingMethod(
        int $cartId,
        string $carrierCode,
        string $methodCode
    ): void {
        $quote = $this->cartRepository->get($cartId);
        $address = $quote->getShippingAddress();

        $address->setShippingMethod($carrierCode . '_' . $methodCode);
        $address->setCollectShippingRates(true);
        $address->collectShippingRates()->save();

        $this->cartRepository->save($quote);
    }
}

Payment Method Selection

Payment Method Assignment

namespace Vendor\Checkout\Service;

class PaymentManager
{
    public function __construct(
        private \Magento\Quote\Api\CartRepositoryInterface $cartRepository
    ) {}

    public function setPaymentMethod(
        int $cartId,
        string $methodCode,
        array $additionalData = []
    ): void {
        $quote = $this->cartRepository->get($cartId);
        $payment = $quote->getPayment();

        $payment->setMethod($methodCode);
        $payment->addData($additionalData);

        $this->cartRepository->save($quote);
    }

    public function getAvailablePaymentMethods(
        int $cartId
    ): array {
        $quote = $this->cartRepository->get($cartId);

        $methods = $quote->getPayment()->getAvailableMethods();

        $result = [];
        foreach ($methods as $method) {
            $result[] = [
                'code' => $method->getCode(),
                'title' => $method->getTitle(),
            ];
        }

        return $result;
    }
}

Checkout Step Data Flow

Checkout Data Persistence

// REST API: Set shipping address and method
POST /rest/V1/carts/mine/shipping-information
{
    "addressInformation": {
        "shipping_address": {
            "firstname": "John",
            "lastname": "Doe",
            "street": ["123 Main St"],
            "city": "New York",
            "region_id": 43,
            "postcode": "10001",
            "country_id": "US",
            "telephone": "555-1234"
        },
        "shipping_method_code": "flatrate",
        "shipping_carrier_code": "flatrate"
    }
}

// REST API: Set payment method and place order
POST /rest/V1/carts/mine/payment-information
{
    "paymentMethod": {
        "method": "checkmo"
    },
    "billingAddress": {
        "firstname": "John",
        "lastname": "Doe",
        "street": ["123 Main St"],
        "city": "New York",
        "region_id": 43,
        "postcode": "10001",
        "country_id": "US",
        "telephone": "555-1234"
    }
}

Checkout Session State

// Quote holds all checkout state
$quote = $this->cartRepository->get($cartId);

// Shipping info
$shippingAddress = $quote->getShippingAddress();
$shippingMethod = $shippingAddress->getShippingMethod();
$shippingRates = $shippingAddress->getAllShippingRates();

// Payment info
$payment = $quote->getPayment();
$paymentMethod = $payment->getMethod();
$paymentData = $payment->getData();

// Recalculate totals after changes
$quote->collectTotals();

Quiz

1. How is the shipping method stored on the quote?

Question 1 options

2. How do you get available shipping rates?

Question 2 options

3. What happens when 'same as shipping' is set?

Question 3 options

Flashcards

Question

How to set shipping method?

Answer

$address->setShippingMethod('carriercode_methodcode')

Question

Where are shipping rates collected?

Answer

$address->collectShippingRates()

Question

Payment method storage?

Answer

$quote->getPayment()->setMethod('method_code')

Question

Address types?

Answer

TYPE_SHIPPING and TYPE_BILLING on Quote\Address

Revision Notes

Key Takeaways

  • 1. Quote addresses (shipping/billing) store customer address data during checkout
  • 2. Shipping methods are collected based on address and cart contents
  • 3. Payment methods are set on the quote's payment object
  • 4. All checkout data persists on the quote until order placement
  • 5. collectTotals() must be called after address or method changes

Interview Tips

  • Describe the flow: address → shipping rates → method selection → payment → totals
  • Explain how shipping rate calculation depends on address and cart weight/price
  • Discuss the separation of concerns between shipping and payment in checkout

Cheat Sheet

Shipping & Payment:
  Address: $quote->getShippingAddress()->addData([...])
  Rates:   $address->collectShippingRates()
  Method:  $address->setShippingMethod('flatrate_flatrate')
  Payment: $quote->getPayment()->setMethod('checkmo')
  Totals:  $quote->collectTotals()

REST APIs:
  POST /V1/carts/mine/shipping-information
  POST /V1/carts/mine/payment-information