Payment reusable renders the payment-method selection UI in checkout and updates the checkout state when the user selects a payment provider (and optionally installments).Components/Checkout/Default.liquid:{% render 'Reusables\\Payment\\Default', payments: payments %}{% if GlobalData.Settings.CheckoutSettings.ShowPayment %}
...
{% endif %}Payment reusable is called with a named parameter:paymentspayments comes from the checkout component model:{% assign payments = model.payments %}x-data="paymentreusabledefault"data-step="payment"$store.checkout.canShowDetails('payment')payments.size > 0):payment)@change it serializes the payment object and calls:selectPayment({{ payment | serialize }}, "{{ Reusables.Payment.Translations.PaymentErrorMessage }}")payment.serviceAmount > 0, it renders the surcharge text (payment.serviceAmountText).payment.installmentsEnabled and payment.maxInstallments > 1:selectedPayment === '<providerId>' && ($store.checkout.data?.totalAmount || 0) >= <minAmountForInstallments>payment.message exists, it is shown only for the selected provider:x-show="selectedPayment === '<providerId>'"{{ Reusables.Payment.Translations.NoPayments }}payments items (as consumed by Liquid + JS)providerproviderIdnameserviceAmountserviceAmountTextinstallmentsEnabledmaxInstallmentsminAmountForInstallments (optional, defaults to 0 in Liquid)message (optional){
"pageState": null,
"status": "Start",
"checkout": {
"finalPrice": 168,
"finalPriceText": "168,00 €",
"cartItems": [
{
"id": "Cart Item Id",
"productId": "Product Id",
"productVariantId": "Product Variant Id",
"quantity": 1,
"productTitle": "Sample title",
"link": "/sample",
"imageLink": "https://example.com/sample",
"finalPrice": 48,
"finalPriceText": "48,00 €",
"originalPrice": 49,
"originalPriceText": "49,00 €",
"subTotalNetValue": 38.71,
"subTotalPrice": 48,
"subTotalVatValue": 9.29
},
...
]
},
"payments": [
{
"provider": "COD",
"providerId": "Payment Provider Id",
"name": "Sample title",
"serviceAmount": 2,
"serviceAmountText": "2,00 €",
"installmentsEnabled": false
}
],
"settings": {
"id": "Component Id",
"cssClass": ""
},
"translations": {
"paymentMethod": "Sample text",
"paymentErrorMessage": "Sample text",
"...": "..."
}
}paymentreusabledefaultx-data="paymentreusabledefault"Alpine.store("toast").removeAll()selectedPayment = payment.providerId and resets selectedInstallmentspaymentData object and merges it into the checkout store data (Alpine.store("checkout").data)servicesreusabledefault.updateCheckout(updatedCheckoutData, "payment")paymentErrorMessageAlpine.store("checkout").steps["payment"].valid = trueaddPaymentInfo with items + payment titlesuccess === false, the UI treats the selection as failed.prepareItemsForCheckoutProcess(this.checkout.cartItems).servicesreusabledefault.updateCheckout(...) is async and can fail; the UI should remain usable.selectedInstallments from the dropdown.checkout.payment doesn’t exist, it returns without updating.installments into checkout.payment and calls:servicesreusabledefault.updateCheckout(updatedCheckoutData, "payment")console.error(...) and does not show a toast.selectPayment).$store.checkoutsteps['payment'].valid for the step indicatorisUpdating / isReady to disable the radioscanShowDetails('payment') to control expand/collapse of the stepdata as the source of truth for the checkout payload passed into updateCheckout$store.toastremoveAll() before the updateadd(...) when payment selection failsPayment reusable calls:servicesreusabledefault.updateCheckout(updatedCheckoutData, "payment")NoirDocs/5. SDK/.)Reusables/Payment/Default.liquidReusables/Payment/Default.jsReusables/Payment/Default.json$store.checkout, $store.toastservicesreusabledefault.updateCheckout(...)prepareItemsForCheckoutProcess(...), sendGAEvent(...)payments parameter is effectively required: if it’s empty/undefined, the template renders the NoPayments message.payment.installmentsEnabled, payment.maxInstallments, and $store.checkout.data.totalAmount.PaymentErrorMessage translation comes from Reusables/Payment/Default.json and is passed into JS as a string.