Checkout flow documentation
Learn about different checkout flow options, submit handling, and form validation behavior when integrating UI components v2.
Customized checkout flowTo simplify the integration, you can use the <unzer-checkout>
custom web component. This tag encapsulates core functionality needed to manage the checkout process efficiently.
At a minimum, <unzer-checkout>
should be used with a checkout button as its immediate child.
If you’re using a custom button, it’s important that the button supports the disabled
property. This allows <unzer-checkout>
to dynamically control the button’s state based on the current status of the checkout form. For example:
myButton.disabled = true; // should disable the button
myButton.disabled = false; // should enable the button
If the disabled
property is not present or supported, <unzer-checkout>
will not be able to control the button’s interactivity.
<unzer-checkout id='unzer-checkout'>
<button type="submit">Pay</button>
</unzer-checkout>
Manual control
If you prefer to implement your own logic for enabling or disabling the checkout button, you can pass the manualCheckoutButtonControl
attribute to the tag.
In this mode, <unzer-checkout>
will dispatch events to indicate when the button should be enabled or disabled, allowing you to implement your own logic and criteria for managing the button state.
<unzer-payment
id="unzer-payment"
publicKey="s-pub-xyz"
locale="de-DE">
<unzer-card></unzer-card>
</unzer-payment>
<unzer-checkout id='unzer-checkout' manualCheckoutButtonControl>
<button type="submit">Pay</button>
</unzer-checkout>
Promise.all([
customElements.whenDefined("unzer-payment"),
customElements.whenDefined("unzer-checkout"),
customElements.whenDefined("unzer-card"),
])
.then(() => {
const unzerCheckout = document.getElementById("unzer-checkout");
const unzerPayment = document.getElementById("unzer-payment");
unzerPayment.addEventListener("stateChanged", (event) => {
const enableCheckout = event.detail.enableCheckout;
// Add custom logic here and apply the button state
});
})
.catch((error) => {
/* Handle loading and initialization error */
})
If you prefer not to use <unzer-checkout>
at all, events will be dispatched in a similar manner
<unzer-payment
id="unzer-payment"
publicKey="s-pub-xyz"
locale="de-DE">
<unzer-card></unzer-card>
</unzer-payment>
<div>
<button type="submit">Pay</button>
</div>
Promise.all([
customElements.whenDefined("unzer-payment"),
customElements.whenDefined("unzer-card"),
])
.then(() => {
const unzerCheckout = document.getElementById("unzer-checkout");
const unzerPayment = document.getElementById("unzer-payment");
unzerPayment.addEventListener("stateChanged", (event) => {
const enableCheckout = event.detail.enableCheckout;
// Add custom logic here and apply the button state
})
.catch((error) => {
/* Handle loading and initialization error */
})
Custom checkout flow
For more information on checkout flow customization please see Integrate UI without the unzer-checkout component
Integrate UI without the unzer-checkout component
Learn how to integrate UI components v2 without using the <unzer-checkout>
component for maximum control over the payment flow.
Overview
While the <unzer-checkout>
component provides a simplified integration experience, you can also integrate UI components v2 without it for more control over the payment flow, custom validation, and event handling.
Basic integration structure
Non-checkout code example<unzer-payment
id="unzer-payment"
publicKey="s-pub-xyz"
locale="de-DE">
<!-- ... Here you will need to add the Unzer payment type tag, so the form UI elements will be inserted -->
<!-- e.g <unzer-paylater-invoice></unzer-paylater-invoice> -->
<p>Shipping Information</p>
<unzer-shipping-address></unzer-shipping-address>
<p>Billing Information</p>
<unzer-billing-address></unzer-billing-address>
<button type="submit" id="yourPaymentButtonId">Pay</button>
</unzer-payment>
Promise.all([
customElements.whenDefined("unzer-payment"),
customElements.whenDefined("unzer-klarna"),
])
.then(() => {
const unzerPayment = document.getElementById("unzer-payment");
const submitButton = document.getElementById("yourPaymentButtonId");
// Event listeners for payment component
unzerPayment.addEventListener("typeCreated", (event) => {
const typeId = event.detail.id;
const typeData = event.detail.data;
console.log("Payment type created:", typeId);
console.log("Payment type data:", typeData);
// Send typeId to your server for payment processing
});
// Handle submit button click
submitButton.addEventListener("click", async (event) => {
event.preventDefault();
try {
const response = await unzerPayment.submit();
console.log("Submit response:", response);
if (response.submitResponse && response.submitResponse.success) {
const typeId = response.submitResponse.data.id;
console.log("Payment type ID:", typeId);
// Process payment on server
} else {
console.error("Submit failed:", response);
console.error("Payment submission failed");
}
} catch (error) {
console.error("Submit error:", error);
console.error("An error occurred during payment submission");
}
});
})
.catch((error) => {
console.error("Initialization error:", error);
console.error("Failed to initialize payment components");
});
Key differences from checkout component
- Manual submit handling: You call
unzerPayment.submit()
directly instead of relying on the checkout component - Event-driven architecture: You listen to events emitted by the payment component
- Custom validation handling: You manage form validation state manually
- Flexible UI control: You have full control over the submit button and user interface
- Direct response handling: You handle the submit response directly without the checkout component’s abstraction
Benefits of non-checkout integration
- Full control: Complete control over the payment flow and user interface
- Custom validation: Implement your own validation logic and error handling
- Flexible styling: No constraints from the checkout component’s styling
- Event-driven: React to specific events as they occur
- Integration flexibility: Easier to integrate with existing forms and workflows
- Shop system compatibility: Better integration with shop systems where submit button handling is not under your control
Submit payment without checkout component
When not using the <unzer-checkout>
component, you need to manually handle the submit process and event handling.
Manual submit handling
Instead of using <unzer-checkout>
, you can call the submit()
method directly on the <unzer-payment>
element:
const unzerPayment = document.getElementById("unzer-payment");
const submitButton = document.getElementById("yourPaymentButtonId");
submitButton.addEventListener("click", async (event) => {
const response = await unzerPayment.submit();
console.log("response: ", response);
if (response.submitResponse) {
console.log("submit response: ", response.submitResponse);
}
});
Getting payment type ID
After successful submission, you can access the payment type ID from the response:
const response = await unzerPayment.submit();
if (response.submitResponse && response.submitResponse.success) {
const typeId = response.submitResponse.data.id;
// Use typeId for server-side payment processing
console.log("Payment type ID:", typeId);
}
Form validation behavior
Important: Unzer form validation is automatically triggered only when you call the submit()
method. It is not possible to manually trigger Unzer’s built-in validation outside of the submit process.
However, you can implement your own additional validation logic before calling submit()
:
const unzerPayment = document.getElementById("unzer-payment");
const submitButton = document.getElementById("yourPaymentButtonId");
submitButton.addEventListener("click", async (event) => {
// Your custom validation logic
if (validateCustomFields()) {
// Only call submit() if your validation passes
const response = await unzerPayment.submit();
// Handle response...
} else {
// Handle validation errors
console.log("Custom validation failed");
}
});
function validateCustomFields() {
// Implement your custom validation logic here
// Return true if validation passes, false otherwise
return true;
}
This approach allows you to:
- Perform custom validation before Unzer validation
- Control when the submit process starts
- Handle validation errors according to your application’s needs
- Integrate with existing form validation frameworks