pageState == 'cancel')pageState == 'error'){
"pageState": null,
"status": "Start",
"checkout": {
"netValue": 0,
"netValueText": "0.00 €",
"vatValue": 0,
"vatValueText": "0.00 €",
"finalPrice": 0,
"finalPriceText": "0.00 €",
"billingAddress": {
"id": "Address Id",
"name": "Sample name",
"firstName": "Sample first name",
"lastName": "Sample last name",
"phoneNumber": "Sample phone",
"address1": "Sample address",
"city": "Sample city",
"state": "Sample state",
"country": "Sample country",
"countryCode": "XX",
"postalCode": "Sample postal code",
"email": "sample@example.com"
},
"shippingAddress": {
"id": "Address Id",
"name": "Sample name",
"firstName": "Sample first name",
"lastName": "Sample last name",
"phoneNumber": "Sample phone",
"address1": "Sample address",
"city": "Sample city",
"state": "Sample state",
"country": "Sample country",
"countryCode": "XX",
"postalCode": "Sample postal code",
"email": "sample@example.com"
},
"cartItems": [
{
"id": "Cart line Id",
"productId": "Product Id",
"productVariantId": "Variant Id",
"quantity": 1,
"productTitle": "Sample product title",
"link": "sample-product-link",
"imageLink": "https://example.com/sample",
"finalPrice": 0,
"finalPriceText": "0.00 €",
"originalPrice": 0,
"originalPriceText": "0.00 €",
"subTotalNetValue": 0,
"subTotalPrice": 0,
"subTotalVatValue": 0
},
...
],
"pricingBeforeDiscount": {
"netValue": 0,
"netValueText": "0.00 €",
"vatValue": 0,
"vatValueText": "0.00 €",
"finalPrice": 0,
"finalPriceText": "0.00 €"
}
},
"carriers": {
"globalConfig": {
"freeAtPrice": 0,
"freeAtPriceText": "0.00 €",
"freeAtWeightText": " kg"
},
"list": [
{
"carrierId": "Carrier Id",
"carrierCode": "sample",
"title": "Sample carrier title",
"type": "Manual",
"netPrice": 0,
"totalAmount": 0,
"totalAmountText": "0.00 €",
"vatLines": []
},
...
]
},
"payments": [
{
"provider": "Sample provider",
"providerId": "Provider Id",
"name": "Sample payment name",
"message": "<p>Sample message</p>",
"installmentsEnabled": false
},
...
],
"deliveryZonesEnabled": true,
"countriesList": [
{
"code": "XX",
"name": "Sample country name"
},
...
],
"addresses": [
{
"name": "",
"isSelectable": true,
"address": {
"id": "Address Id",
"firstName": "Sample first name",
"lastName": "Sample last name",
"phoneNumber": "Sample phone",
"address1": "Sample address",
"city": "Sample city",
"state": "Sample state",
"country": "Sample country",
"countryCode": "XX",
"postalCode": "Sample postal code",
"email": "sample@example.com"
},
"requiresInvoice": false
},
...
],
"name": "Checkout",
"view": "Default",
"section": "SectionA",
"settings": {
"id": "Component Id",
"section": "SectionA",
"type": "NoirCheckout",
"name": "Checkout",
"configuredInContentApi": true,
"view": "Default",
"displayName": "Sample display name",
"cssClass": ""
},
"translations": {
"completeOrder": "Sample translation",
"backToCart": "Sample translation",
"orderSummary": "Sample translation",
"...": "..."
}
}settings.idcomp-{{ id }}checkoutsettings.cssClass(UNDEFINED).pageStatecancel → Payment cancelled/failed pageerror → Order creation failed pageaddresses, countriesListcarriers, paymentsx-data='checkoutdefault.initComponent({{ checkout | serialize | escape }})'initComponent(...) returns the Alpine component state + methods for:servicesreusabledefault.updateCheckout(...))servicesreusabledefault.proceedToCheckout(...))checkout object and returns the Alpine state + handlers.checkoutToken from cookies, stores it in localStorage, initializes Alpine.store("checkout"), and sends GA beginCheckout when cart data exists.IntersectionObserver that tracks whether the aside “Complete order” button is visible, and stores the result in isAsideButtonVisible.Object.create(null)), optionally copying source. Field names are merchant-authored, so a field called __proto__ or constructor must not read or write the prototype.customFieldValues from checkoutData.customFields for every entry in orderCustomFields and resets customFieldErrors. Stored values are converted to strings, so JSON booleans match the "true"/"false" radio bindings.isCustomFieldEmpty(name) returns true when the trimmed value of the field is empty.customFieldAt(index) returns the custom field at a template-generated index. The markup addresses fields by index, never by name, so merchant-supplied names never end up inside an Alpine expression.customFieldNameAt(index) returns the field name at index, or "".customFieldValueAt(index) returns the current value of the field at index, or "".customFieldHasErrorAt(index) returns true while the field at index is flagged "required".customFieldClassAt(index) index-based wrapper for customFieldClass.setCustomFieldAt(index, value) index-based wrapper for setCustomField.validateCustomFieldAt(index) index-based wrapper for validateCustomField.customFieldClass(name) returns the { invalid, valid } state classes, using the same convention as the Form component. Only required fields are marked, and valid waits for a value so an untouched field is not painted green.validateCustomField(name) sets customFieldErrors[name] = "required" for an empty required field and removes the entry otherwise. An entry exists only while the field is in error.customFieldDisplayValue(field, value) returns the text the customer saw. For a Boolean field this is the merchant's option label instead of "true"/"false".setCustomField(name, value) (async) stores the value, validates the field and rebuilds checkout.customFields with name, value, label and displayValue for every field. The label and wording are captured at that moment, so the confirmation email and invoice PDF match what the customer saw even if the merchant later edits the field..checkout-order-custom-fields into view (below the header) and focuses the first missing field. Returns true when nothing is missing.validCheckout based on whether the consent checkbox #concent-order is checked.servicesreusabledefault.updateCheckout(this.checkout).;).this.isCouponAdding)couponLastInputstate = "default"isCouponAdding = truethis.coupons = []loyaltyPricing:usePoints: this.isPointsRedeemeduseCoupon: truecouponCodes: [couponInput]this.checkout.loyaltyPricing, then calls:servicesreusabledefault.updateCheckout(this.checkout)addCouponErrorMessagethis.checkout = response.datacheckout.loyaltyPricing.errorCode exists:state = "invalid"couponStatus string (e.g. invalidCode, alreadyUsedCode, discountExceeded, etc.)state = "valid"this.isCouponRedeemed = truethis.couponscouponStatus = "validCode"couponLabel and couponsDiscountText from checkout responseisCouponAdding in finally.removeCoupon(lastIndex, ...)index from this.coupons.this.checkout.loyaltyPricing:useCoupon = hasCouponscouponCodes = this.couponsservicesreusabledefault.updateCheckout(this.checkout)removeCouponErrorMessagethis.checkout = response.datastate to "invalid" if there are still coupons and backend returns errorCode, else "default"couponsDiscountText from responsecheckout.loyaltyPricing object; make sure points-related flags don’t get lost when refactoring.isCouponAdding = true (re-using the “busy” flag).usePoints: this.isPointsRedeemeduseCoupon: falsecouponCodes: []updateCheckout.isCouponAdding, returns.state = "default"isCouponRedeemed = falseisCouponAddingprepareListProducts([item])sendGAEvent("selectItem", { listName, items, position })selectItem, beginCheckout, etc.).const checkoutData = Alpine.store("checkout").data;this.checkout:billingAddress, shippingAddress, invoiceDatathis.isCompleting = trueservicesreusabledefault.proceedToCheckout(this.checkout)completeCheckoutErrorMessageisCompleting and returnsthis.checkout = response.dataisCompletingthis.checkout.status == "Completed":isRedirecting = truecartToken, checkoutToken)/checkout/order-completed/<checkoutToken>proceedToCheckout returns a payment redirect URL (for card payments), you may need to handle that case separately; current logic focuses on status == "Completed".$store.checkout.Alpine.store("checkout").set(this.checkout)Alpine.store("checkout").datathis.checkout before proceedingAlpine.store("toast").removeAll();
Alpine.store("toast").add(message, "ic-warning", "error");servicesreusabledefault.updateCheckout(checkout)servicesreusabledefault.proceedToCheckout(checkout)checkout.status == "Completed"), it:/checkout/order-completed/<checkoutToken>checkout, toastcheckoutToken cookiecartData localStorage (GA + summary consistency)updateCheckout(...)proceedToCheckout(...)checkoutToken available in cookies. If missing, init throws an error.pageState == 'cancel' → renders a “payment failed/cancelled” UI and CTA back to checkout.pageState == 'error' → renders a “checkout error” UI and CTA back to checkout.x-data='checkoutdefault.initComponent({{ checkout | serialize | escape }})'Reusables\\BillingRetail\\Default)Reusables\\Shipping\\Default)Reusables\\Payment\\Default)window.checkoutConfig and also available as Liquid settings).handleCoupons().--loading modifier class is applied.