alt
Unzer
UnzerAI

UnzerAI

The responses generated by AI may include errors.

UnzerAI

Welcome to UnzerAI!

I'm here to help you with questions about Unzer's payment integration, APIs, and documentation.

Ask questions about Unzer and get help with your integration.

Checkout flow documentation

Learn about different checkout flow options, submit handling, and form validation behavior when integrating UI components v2.

To simplify the integration, you can use the <unzer-checkout> custom web component. This tag encapsulates core functionality needed to manage the checkout process efficiently.

icon

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

<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> -->
    
    <unzer-customer-form></unzer-customer-form>

    <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");
  });

Payment methods requiring special handling

There are a couple of payment methods that function a bit differently and require different integration. They are: Google Pay, Apple Pay and Paypal-express

Apple Pay integration without Unzer checkout component

If you prefer to implement your own logic, you can decide not to include the <unzer-checkout> component. In this mode, <unzer-checkout> will trigger a callback function, allowing you to implement your own logic and criteria for managing the button state. You can provide an onPaymentAuthorizedCallback function in the configuration, which lets you implement custom logic to approve or reject the payment by calling approve or reject based on your requirements.

<unzer-payment
  id="unzer-payment"
  publicKey="{{PUBLIC_KEY}}"
  locale="de-DE">
    <unzer-apple-pay></unzer-apple-pay>
</unzer-payment>
Promise.all([
  customElements.whenDefined("unzer-payment"),
  customElements.whenDefined("unzer-apple-pay"),
]).then(() => {
  const unzerPayment = document.getElementById('unzer-payment');
  const applePayPaymentRequest = {
    countryCode: 'DE',
    currencyCode: 'EUR',
    supportedNetworks: ['visa', 'mastercard'],
    merchantCapabilities: ['supports3DS'],
    total: { label: 'Unzer GmbH', amount: '12.99' },
    lineItems: [
      {
        "label": "Subtotal",
        "type": "final",
        "amount": "10.00"
      },
      {
        "label": "Free Shipping",
        "amount": "0.00",
        "type": "final"
      },
      {
        "label": "Estimated Tax",
        "amount": "2.99",
        "type": "final"
      }
    ],
    onPaymentAuthorizedCallback: async (paymentData, approve, reject) => {
      // Implement your business logic validation here
      // You can perform additional checks on paymentData before proceeding
      if (requirementsNotMet) {
        reject();
        // Implement user notification for rejection reason
        return;
      }

      const response = await unzerPayment.submit();
      // Perform any necessary response validation
      // ...

      // Handle the payment response and update UI accordingly
      // This step is required to proceed with the payment flow
      if (response.submitResponse.success) {
        approve();
      } else {
        reject();
      }
    },
  };
  unzerPayment.setApplePayData(applePayPaymentRequest);
}).catch((error) => {
  // Handle initialization errors
  console.error('Failed to initialize Apple Pay:', error);
});

Google Pay integration without Unzer checkout component

If you prefer to implement your own logic, you can decide not to include the <unzer-checkout> component. In this mode, <unzer-checkout> will trigger a callback function, allowing you to implement your own logic and criteria for managing the button state. You can pass the onPaymentAuthorizedCallback callback function in the configuration that will allow you to verify or stop the payment process by calling approve or reject according to your custom requirements.

<unzer-payment
  id="unzer-payment"
  publicKey="{{PUBLIC_KEY}}"
  locale="de-DE">
    <unzer-google-pay></unzer-google-pay>
</unzer-payment>
Promise.all([
  customElements.whenDefined("unzer-payment"),
  customElements.whenDefined("unzer-google-pay"),
]).then(() => {
  const unzerPayment = document.getElementById('unzer-payment');
  const googlePayPaymentRequest = {
    gatewayMerchantId: "yourUnzerChannelId",
    merchantInfo: {
      merchantId: "yourGooglePayMerchantId",
      merchantName: 'yourMerchantName'
    },
    transactionInfo: {
      countryCode: 'DE',
      currencyCode: 'EUR',
      totalPrice: '19.99',
    },
    buttonOptions: {
      buttonColor: 'black',
    },
    onPaymentAuthorizedCallback: async (paymentData, approve, reject) => {
      // Implement your business logic validation here
      // You can perform additional checks on paymentData before proceeding
      if (requirementsNotMet) {
        // reject() can optionally take a message object
        // The message will be displayed in the Google Pay overlay to the user
        // reject({message: 'Custom error message'});
        reject({message: 'Payment requirements not met'});
        return;
      }

      const response = await unzerPayment.submit();
      // Perform any necessary response validation
      
      // Handle the payment response and update UI accordingly
      // This step is required to proceed with the payment flow
      if (response.submitResponse.success) {
        approve();
      } else {
        // You can also reject with a specific error message
        // The message will be shown in the Google Pay overlay
        reject({message: 'Payment processing failed'});
      }
    },
  };
  unzerPayment.setGooglePayData(googlePayPaymentRequest);
}).catch((error) => {
  // Handle initialization errors
  console.error('Failed to initialize Google Pay:', error);
});

Google Pay Express integration without Unzer checkout component

icon
Google Pay Express

Please note that setting the following parameters in the Google Pay data configuration will enable the Google Pay Express payment method. This method requires you to manually set the customer object. More information is available here.

unzerPayment.setGooglePayData({
  ...
  emailRequired: true,
  billingAddressRequired: true,
  billingAddressParameters: {
    format: 'FULL',
    phoneNumberRequired: true
  }
  ...
});
<unzer-payment
  id="unzer-payment"
  publicKey="{{PUBLIC_KEY}}"
  locale="de-DE">
    <unzer-google-pay></unzer-google-pay>
</unzer-payment>
Promise.all([
  customElements.whenDefined("unzer-payment"),
  customElements.whenDefined("unzer-google-pay"),
]).then(() => {
  const unzerPayment = document.getElementById('unzer-payment');
  const googlePayPaymentRequest = {
    gatewayMerchantId: "yourUnzerChannelId",
    merchantInfo: {
      merchantId: "yourGooglePayMerchantId",
      merchantName: 'yourMerchantName'
    },
    transactionInfo: {
      countryCode: 'DE',
      currencyCode: 'EUR',
      totalPrice: '19.99',
    },
    buttonOptions: {
      buttonColor: 'black',
    },
    emailRequired: true,
    billingAddressRequired: true,
    billingAddressParameters: {
      format: 'FULL',
      phoneNumberRequired: true
    },
    onPaymentAuthorizedCallback: async (paymentData, approve, reject) => {
      // Implement your business logic validation here
      // You can perform additional checks on paymentData before proceeding
      if (requirementsNotMet) {
        // reject() can optionally take a message object
        // The message will be displayed in the Google Pay overlay to the user
        // reject({message: 'Custom error message'});
        reject({message: 'Payment requirements not met'});
        return;
      }

      const response = await unzerPayment.submit();
      // Perform any necessary response validation
      
      // Handle the payment response and update UI accordingly
      // This step is required to proceed with the payment flow
      if (response.submitResponse.success) {
        approve();
      } else {
        // You can also reject with a specific error message
        // The message will be shown in the Google Pay overlay
        reject({message: 'Payment processing failed'});
      }
    },
  };
  unzerPayment.setGooglePayData(googlePayPaymentRequest);
}).catch((error) => {
  // Handle initialization errors
  console.error('Failed to initialize Google Pay:', error);
});

PayPal Express integration without Unzer checkout component

You can attach a click event handler on the unzer-paypal-express component to handle submission attempts manually.

<unzer-payment
  id="unzer-payment"
  publicKey="{{PUBLIC_KEY}}"
  locale="de-DE">
    <unzer-paypal-express id="paypalPaymentButtonId"></unzer-paypal-express>
</unzer-payment>
Promise.all([
  customElements.whenDefined("unzer-payment"),
  customElements.whenDefined("unzer-paypal-express"),
]).then(() => {
  const unzerPayment = document.getElementById('unzer-payment');
  const paypalSubmitButton = document.getElementById("paypalPaymentButtonId");
  paypalSubmitButton.addEventListener("click", async (event) => {
    event.stopPropagation(); 
    const response = await unzerPayment.submit();
    if (response.submitResponse) {
      // Handle payment response processing 
      console.log("submit response: ", response.submitResponse);
    }
  });
}).catch((error) => {
  // Handle initialization errors
  console.error('Failed to initialize PayPal Express:', error);
});

Key differences from checkout component

  1. Manual submit handling: You call unzerPayment.submit() directly instead of relying on the checkout component
  2. Event-driven architecture: You listen to events emitted by the payment component
  3. Custom validation handling: You manage form validation state manually
  4. Flexible UI control: You have full control over the submit button and user interface
  5. 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