Basic Checkout

In this tutorial, we'll manually create an order, add customer information, shipping details, payment, and completing the order—essentially handling everything ourselves without any automation. This isn't a checkout setup we're expected to build in a real-world scenario, but it serves to introduce some of the core concepts behind the system. In most cases, we'll use a platform adapter to streamline the process. We'll cover how to integrate the Norce adapter in a later section.

Create an order

Here is some product information and cart information we've been provided with, when the customer entered our Checkout.

SKU Name Price Excluding VAT VAT
T001 Thing 10 0.25
Item ID Cart ID SKU
cart-item-no-1 our-first-cart T001

On our order, reference is used for external IDs, so we'll use Cart ID for order/cart/reference and Item ID for our first and only item, order/cart/items[0]/reference. We need to calculate the total price including VAT for our item and we need to sum up all our items totals for our order/cart/total.

In the response we'll find our order id, both in the body and in the location header.

Create order

Create order requestCreate order response
Copy
Copied
POST /api/v0/checkout/orders
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Content-Type: application/json

{
  "merchant": "thingsandstuff",
  "channel": "se",
  "cart": {
    "reference": "our-first-cart",
    "items": [
      {
        "reference": "cart-item-no-1",
        "sku": "T001",
        "name": "Thing",
        "quantity": 1,
        "total": {
          "includingVat": 12.5,
          "excludingVat": 10
        },
        "vatRate": 0.25
      }
    ],
    "total": {
      "includingVat": 12.5,
      "excludingVat": 10
    }
  }
}
Copy
Copied
201 Created
location: /api/v0/checkout/orders/oaAaAaAA
Content-Type: application/json

{
  "id": "oaAaAaAA"
}

We can now fetch our order and we'll see that the order received a few new fields, including a state with the current status checkout. The order has also received a total, calculated from cart and shippings, but we don't have any shippings yet.

Get order

Get order requestGet order response
Copy
Copied
GET /api/v0/checkout/orders/oaAaAaAA
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Copy
Copied
200 OK
Content-Type: application/json

{
  "id": "oaAaAaAA",
  "merchant": "thingsandstuff",
  "channel": "se",
  "created": "2024-01-01T01:01:01.0000001Z",
  "lastModified": "2024-01-01T01:01:01.0000001Z",
  "state": {
    "currentStatus": "checkout",
    "transitions": [
      {
        "status": "checkout",
        "timeStamp": "2024-01-01T01:01:01.0000001Z",
      }
    ]
  },
  "cart": {
    "reference": "our-first-cart",
    "items": [
      {
        "id": "ciaAaaAAAAAAAaaaAAaAAAAaaAaA",
        "reference": "cart-no-1",
        "name": "Thing",
        "sku": "T001",
        "quantity": 1,
        "price": {
          "includingVat": 12.5,
          "excludingVat": 10
        },
        "vatRate": 0.25
      }
    ],
    "total": {
      "includingVat": 12.5,
      "excludingVat": 10
    }
  },
  "total": {
    "includingVat": 12.5,
    "excludingVat": 10
  }
}

Cart references are unique in Norce Checkout, meaning only one order can exist per platform cart. When a customer enters the checkout, an order is created. If they exit to modify their cart and return later, the existing order will be updated instead. Attempting to create a new order with the same cart reference will result in a conflict, signaling that the previous order should be retrieved and updated.

Customer information

Next we need to get some customer information in order to know where to deliver the item to. Let's assume we got that from a form in our checkout. We can then add that information to the order, by updating the order/customer/shipping.

Update Customer Shipping

Update customer requestUpdate customer response
Copy
Copied
PUT /api/v0/checkout/orders/oaAaAaAA/customer/shipping
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Content-Type: application/json

{
  "type": "Person",
  "givenName": "Henrikinho",
  "familyName": "Undulatsson",
  "streetAddress": "Odengatanvägen 12",
  "streetAddress2": "Lgh 1203",
  "postalCode": "915 20",
  "city": "Skellefteå",
  "country": "SE",
  "phone": "0701740612",
  "email": "henrikinho.undulatsson@example.com"
}
Copy
Copied
200 OK

Delivery

Now we can add a delivery option to the order. Our merchant handles all the delivery themselves and the platform contains information about the delivery option.

Delivery ID Name Price Excluding VAT VAT
thing-to-home-delivery Thing to Home Delivery 6 0.25

We don't actually have a shipping session to deal with here, so we'll just set the delivery method id as a reference, assuming that will all be handled after the order is completed.

Just as when we created an order, we get the id in our response body as well as in our location header.

Create Shipping

Add shipping requestAdd shipping response
Copy
Copied
POST /api/v0/checkout/orders/oaAaAaAA/shippings
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Content-Type: application/json

{
  "reference": "thing-to-home-delivery",
  "name": "Thing to Home Delivery",
  "total": {
    "includingVat": 7.5,
    "excludingVat": 6
  },
  "vatRate": 0.25
}
Copy
Copied
201 Created
location: /api/v0/checkout/orders/oaAaAaAA/shippings/saAaaAAAAaaaaAAAAaAAAAAAaaA
Content-Type: application/json

{
  "id": "saAaaAAAAaaaaAAAAaAAAAAAaaA"
}

Fetching our order again, we can see that the added shipping price has been included in our order total.

Get order

Get updated order requestGet updated order response
Copy
Copied
GET /api/v0/checkout/orders/oaAaAaAA
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Copy
Copied
200 OK
Content-Type: application/json

{
  "id": "oaAaAaAA",
  "merchant": "thingsandstuff",
  "channel": "se",
  "created": "2024-01-01T01:01:01.0000001Z",
  "lastModified": "2024-01-01T01:02:01.0000001Z",
  "state": {
    "currentStatus": "checkout",
    "transitions": [
      {
        "status": "checkout",
        "timeStamp": "2024-01-01T01:01:01.0000001Z",
      }
    ]
  },
  "cart": {
    "reference": "our-first-cart",
    "items": [
      {
        "id": "ciaAaaAAAAAAAaaaAAaAAAAaaAaA",
        "reference": "cart-no-1",
        "name": "Thing",
        "sku": "T00001",
        "quantity": 1,
        "price": {
          "includingVat": 12.5,
          "excludingVat": 10
        },
        "vatRate": 0.25
      }
    ],
    "total": {
      "includingVat": 12.5,
      "excludingVat": 10
    }
  },
  "shippings": [
    {
      "id": "saAaaAAAAaaaaAAAAaAAAAAAaaA",
      "state": "intent",
      "reference": "thing-to-home-delivery",
      "name": "Thing to Home Delivery",
      "total": {
        "includingVat": 7.5,
        "excludingVat": 6
      },
      "vatRate": 0.25
    }
  ],
  "total": {
    "includingVat": 20,
    "excludingVat": 16
  }
}

Payment

Our platform provides the following payment method information:

Payment Method ID Name
thing-payment Thing Payment

Similarly to our delivery method, we don't have a payment session active anywhere, so we'll just use our payment method id as reference. We'll make sure to cover the order total with our amount.

Create Payment

Add payment requestAdd payment response
Copy
Copied
POST /api/v0/checkout/orders/oaAaAaAA/payments
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Content-Type: application/json

{
  "reference": "thing-payment",
  "name": "Thing Payment",
  "type": "default",
  "amount": 20
}
Copy
Copied
201 Created
location: /api/v0/checkout/orders/oaAaAaAA/payments/paAaaAAAAaaaaAAAAaAAAAAAaaA
Content-Type: application/json

{
  "id": "paAaaAAAAaaaaAAAAaAAAAAAaaA"
}

Complete the order

When we say that we complete the order, we're referring to changing the order state to completed.

Order states

The order starts in the checkout state, where all modifications are allowed. Once the state is changed to processing, changes that affect the order total or payment amounts are no longer permitted. This state is useful for locking the order before initiating transactions, like payments. If an attempt is made to move the order back to checkout, the adapter that changed it to processing can block the reversal using hooks. The accepted state indicates the customer has finalized the order, awaiting payment confirmation, with similar restrictions as processing. Once all payments and shipments are complete, the order transitions to completed.

To complete an order, simply change order/state/currentStatus to completed. The order service will automatically transition through the processing and accepted states, validating along the way, before reaching completed. If the payment amount doesn't cover the total, the order may fail validation, and the state change will be rejected.

Update State

Update order state requestUpdate order state request
Copy
Copied
PUT /api/v0/checkout/orders/oaAaAaAA/state
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Content-Type: application/json

{
  "currentStatus": "completed"
}
Copy
Copied
200 OK

Fetching our order for the final time, we can see the transitions as the order moved from checkout, to processing, to accepted before finally ending up as completed.

Get order

Get completed order requestGet completed order response
Copy
Copied
GET /api/v0/checkout/orders/oaAaAaAA
X-Merchant: thingsandstuff
X-Channel: se
Authorization: Bearer super-secret-and-valid-token
Host: thingsandstuff.api-se.playground.norce.tech/checkout/order
Copy
Copied
200 OK
Content-Type: application/json

{
  "id": "oaAaAaAA",
  "merchant": "thingsandstuff",
  "channel": "se",
  "created": "2024-01-01T01:01:01.0000001Z",
  "lastModified": "2024-01-01T01:04:01.0000001Z",
  "state": {
    "currentStatus": "completed",
    "transitions": [
      {
        "status": "checkout",
        "timeStamp": "2024-01-01T01:01:01.0000001Z",
       },
      {
        "status": "processing",
        "timeStamp": "2024-01-01T01:04:01.0000001Z",
      },
      {
        "status": "accepted",
        "timeStamp": "2024-01-01T01:04:01.0000001Z",
      },
      {
        "status": "completed",
        "timeStamp": "2024-01-01T01:04:01.0000001Z",
      }
    ]
  },
  "cart": {
    "reference": "our-first-cart",
    "items": [
      {
        "id": "ciaAaaAAAAAAAaaaAAaAAAAaaAaA",
        "reference": "cart-no-1",
        "name": "Thing",
        "sku": "T00001",
        "quantity": 1,
        "price": {
          "includingVat": 12.5,
          "excludingVat": 10
        },
        "vatRate": 0.25
      }
    ],
    "total": {
      "includingVat": 12.5,
      "excludingVat": 10
    }
  },
  "shippings": [
    {
      "id": "saAaaAAAAaaaaAAAAaAAAAAAaaA",
      "state": "intent",
      "reference": "thing-shipping",
      "name": "Thing to Home Delivery",
      "total": {
        "includingVat": 7.5,
        "excludingVat": 6
      },
      "vatRate": 0.25
    }
  ],
  "payments": [
    {
      "id": "paAaaAAAAaaaaAAAAaAAAAAAaaA",
      "name": "Thing Payment",
      "currency": "SEK",
      "type": "default",
      "orderId": "oaAaAaAA",
      "amount": 20,
      "state": "intent",
      "reference": "thing-payment"
    }
  ],
  "total": {
    "includingVat": 20,
    "excludingVat": 16
  }
}

We should have updated the shipping and payment states to confirmed. However, we'll leave this as an exercise for you to complete.

Next Steps

In this tutorial, we manually created and managed an order, adding customer information, delivery, and payment details, and then completing the order. While this approach works for simple cases, real-world scenarios are often more complex.

Next, we'll look at how using an adapter can automate many of these tasks and streamline the order creation and management process.

Copyright © Norce 2024. All right reserved.