alt

Important information

Please be advised that there will be a scheduled downtime across our API network on November 05 and November 07, 2024. For more information, visit our platform status portal.:
- Scheduled maintenance on November 5, 2024
- Scheduled maintenance on November 7, 2024

Unzer

Integrate using Embedded Payment Page (v2)

Beta

Accept payments using a customizable and ready-to-use payment page that is seamlessly integrated into your shop.

Overview

Embedded Payment Page (EPP) is a website overlay prepared by Unzer.
When a customer selects the Pay button in your shop, an overlay displays your available payment methods.
The customer can then make the payment using their desired option.

Using Embedded Payment Page, you can support multiple payment methods with one simple integration.

Embedded payment page

The basket can be expanded: Embedded payment page

Read this guide for a general overview on how to accept payments with Embedded Payment Page. For a list of all payment methods supported by Embedded Payment Page, go to Supported Payment methods.

Before you begin

Check the basic integration requirements

How it works

To integrate payments using EPP, you need to perform steps on both client and server side.

  1. First, set up the payment page – prepare the customer and basket resources and initialize the payment page on the server side.
  2. Using information from the previous step, you can now initialize the payment page on the client side and handle customer’s ‘pay’ action in your checkout.
  3. After the payment, check its status on the server side and display the result to the customer on the client side.
  4. Perform more operations on the server side once the payment has been made, for example, charging the authorized amount.

Step 1: Set up the payment page
server side

First, you should prepare resources required when initializing the payment page on the server side – customer (recommended), basket (recommended), and the metadata resource (optional).

The customer resource contains information about the customer and is required for the payment methods Unzer Invoice, Direct Debit Secured, Unzer Installment, and Klarna payment methods.

We recommend that you always provide the customer resource. To use an existing customer resource, you just need its corresponding customerId. If you don’t have an existing customer resource, you can create it on the server side.

POST https://api.unzer.com/v1/customers

{
  "lastname": "Mustermann",
  "firstname": "Max",
  "salutation": "mr",
  "customerId": "51222",
  "birthDate": "1970-01-01",
  "email": "info@unzer.com",
  "phone": "+49 6221 - 64 71 100",
  "mobile": "+49 172 123 456",
  "billingAddress": {
    "name": "Max Mustermann",
    "street": "Schöneberger Str. 21a",
    "zip": "10963",
    "city": "Berlin",
    "country": "DE"
  },
  "shippingAddress": {
    "name": "Max Mustermann",
    "street": "Schöneberger Str. 21a",
    "zip": "10963",
    "city": "Berlin",
    "country": "DE"
  }
}
$unzer = new Unzer('s-priv-xxxxxxxxxx');

$address = (new Address())
            ->setName('Max Mustermann')
            ->setStreet('Schöneberger Str. 21a')
            ->setZip('10963')
            ->setCity('Berlin')
            ->setCountry('DE');

$customer = (new Customer())
            ->setFirstname('Max')
            ->setLastname('Mustermann')
            ->setSalutation(Salutations::MR)
            ->setCompany('Unzer GmbH')
            ->setBirthDate('1972-12-24')
            ->setEmail('Max.Mustermann@unzer.com')
            ->setMobile('+49 123456789')
            ->setPhone('+49 123456789')
            ->setBillingAddress($address)
            ->setShippingAddress($address);

$unzer->createCustomer($customer);
Address address = new Address();
address
  .setName("Max Mustermann")
  .setStreet("Schöneberger Str. 21a")
  .setCity("Berlin")
  .setZip("10963")
  .setCountry("DE");
      
Customer customer = new Customer("Max", "Mustermann");
customer
  .setCustomerId(customerId)
  .setSalutation(Salutation.mr)
  .setEmail("max.mustermann@unzer.com")
  .setMobile("+49123456789")
  .setBirthDate(getDate("12.12.2000"))
  .setBillingAddress(address)
  .setShippingAddress(address);

Unzer unzer = new Unzer("s-priv-xxxxxxxxxx");
customer = unzer.createCustomer(customer);

Payment types which require customer resource will not be available if neither customer ID nor customer form is provided (for example, payment page is set to “payment_only”).

For a full description of customer resource, please refer to relevant server-side integration documentation page: Manage customer (direct API calls), Manage customer (PHP SDK), Manage customer (Java SDK).

The basket resource stores information about the purchased products, used vouchers, and shipment costs. It is required for Unzer Invoice, Unzer Installment, Direct Debit Secured, and Klarna payment methods. We recommend that you always create a basket resource.

icon info
Note that you must send the basket resource within the payment request.
POST https://api.unzer.com/v2/baskets

{
  "totalValueGross": 190.0,
  "currencyCode": "EUR",
  "note": "Test Basket",
  "orderId": "Order-12345",
  "basketItems": [
    {
      "amountDiscountPerUnitGross": 1.0,
      "amountPerUnitGross": 20.0,
      "basketItemReferenceId": "Item-d030efbd4963",
      "imageUrl": "https://a.storyblok.com/f/91629/x/1ba8deb8cc/unzer_primarylogo__white_rgb.svg",
      "quantity": 10,
      "subTitle": "This is brand new Mid 2019 version",
      "title": "SDM 6 CABLE",
      "type": "goods",
      "unit": "m",
      "vat": 19.0
    }
  ]
}
$unzer = new Unzer('s-priv-xxxxxxxxxx');

$basketItem = (new BasketItem())
    ->setBasketItemReferenceId('Item-d030efbd4963')
    ->setQuantity(10)
    ->setUnit('m')
    ->setAmountPerUnitGross(20.00)
    ->setAmountDiscountPerUnitGross(1.00)
    ->setVat(19.0)
    ->setTitle('SDM 6 CABLE')
    ->setSubTitle('This is brand new Mid 2019 version')
    ->setImageUrl('https://a.storyblok.com/f/91629/x/1ba8deb8cc/unzer_primarylogo__white_rgb.svg')
    ->setType(BasketItemTypes::GOODS);

$basket = (new Basket())
    ->setTotalValueGross(190.00)
    ->setCurrencyCode('EUR')
    ->setOrderId('Order-12345')
    ->setNote('Test Basket')
    ->addBasketItem($basketItem);

$unzer->createBasket($basket);
BasketItem basketItem = new BasketItem()
        .setBasketItemReferenceId("Item-d030efbd4963")
        .setQuantity(BigDecimal.valueOf(10))
        .setUnit("m")
        .setAmountPerUnitGross(BigDecimal.valueOf(20.00))
        .setAmountDiscountPerUnitGross(BigDecimal.valueOf(1.00))
        .setVat(BigDecimal.valueOf(19.0))
        .setTitle("SDM 6 CABLE")
        .setSubTitle("This is brand new Mid 2019 version")
        .setImageUrl(new URL("https://a.storyblok.com/f/91629/x/1ba8deb8cc/unzer_primarylogo__white_rgb.svg"))
        .setType(BasketItem.Type.GOODS);

Basket basket  = new Basket()
        .setTotalValueGross(BigDecimal.valueOf(190.00))
        .setCurrencyCode(Currency.getInstance("EUR"))
        .setOrderId("Order-12345")
        .setNote("Test Basket")
        .addBasketItem(basketItem);

Unzer unzer = new Unzer("s-priv-xxxxxxxxxx");
unzer.createBasket(basket);

For a full description of basket resource, please refer to relevant server-side integration documentation page: Manage basket (direct API calls), Manage basket (PHP SDK), Manage basket (Java SDK).

(Optional) Create metadata

Metadata is the additional information you can append to each payment. By adding metadata, you can store important information about the order or the payment. Add the metadata by adding it in the additional resources. To learn more about metadata, go to the Manage metadata page.

Step 2: Create the payment page
server side

Now you can combine the resources with the data about the transaction and payment page configuration options to make an initialization call for the payment page. However, before you initialize the Payment Page, you need to issue a new bearer token for authentication against the Payment Page API.

Issue a new bearer token for authentication

As long as a token is valid, it can be used multiple times for calls to Payment Page API.

To keep the token authentication mechanism safe and secure, there are some measures that need to be taken into account:

  1. A requested token is valid for 7 minutes‚ after which it expires, and you need to request a new one.
  2. There is a rate limit in place that allows 2 token creations per second.
icon
If you are using one of our SDKs, the token handling is done automatically as long as you are reusing the Unzer instance.

Authorization: Basic auth with your merchant private key.

GET https://token.upcgw.com/v1/auth/token

{
  "accessToken": "eyJraWQiOiJhbGlhcy9jb25uZWN0aXZpdHktdjItdG9rZW4ta21zIiwiYWxnIjoiUlMyNTY..."
}

To learn more, go to the Authentication page.

Initialize a new Payment Page

You can initialize the payment page to support either charge or authorize transactions. For a more detailed description of charge and authorize transactions, please refer to relevant server-side integration documentation page: Manage API resources (direct API calls), Manage API resources (PHP SDK), Manage API resources (Java SDK).

Some payment methods support Two-step payments (both authorize and charge) transactions. For these payment methods, you can choose the transaction type during the payment page creation.

However, some payment methods only support One-step payments (charge). In such a case if the payment page is called with type authorize (Two-step flow), the One-Step payment methods will be displayed as well. A charge will be automatically executed for the One-Step only payment methods if one of these is selected for payment.

To learn more about which payment methods support One-step or Two-step flows, go to Support payment methods.

You need to save the paypageId contained in the create paypage response. The paypageId will be required to open the embedded payment page overlay and to check the payment status later.

To create an Embedded Payment Page, in the create payment page request, set the type flag to embedded.

{
  "mode": "authorize",
  "shopName": "UNZER SHOP",
  "amount": "84.9000",
  "currency": "EUR",
  "type": "embedded", // hosted, embedded , linkpay
  "checkoutType": "full",
  //full: The entire customer data is displayed on the payment page and can be edited.
  //payment_only: Customer data is not displayed and cannot be edited.
  //no_shipping: Customer data is displayed, but the shipping address is read-only.
  //"recurrenceType": "scheduled" // unscheduled
  "orderId": "Order12",
  "invoiceId": "InvoiceID34",
  "paymentReference": "Payment Online Shop",
  "urls": {
      "termsAndCondition": "https://www.unzer.com",
      "privacyPolicy": "https://www.unzer.com",
      "imprint": "https://www.unzer.com",
      "help": "https://www.unzer.com",
      "contact": "https://www.unzer.com"
      "returnSuccess": "https://www.unzer.com",
      "returnPending": "https://www.unzer.com",
      "returnFailure": "https://www.unzer.com",
      "returnCancel": "https://www.unzer.com"
  },
  //There is a difference beetween customization styles options for the types "embedded", "hosted" and "linkpay".
  //the type "hosted" is the type who is able to consume all of the customization styles.
  "style": {
      "logoImage": "https://www.mydomain.de/img/logo_rb_uzr.png",
      "backgroundColor": "#CCC",
      "footerColor": "#FFFFFF",
      "headerColor": "#FFFFFF",
      "linkColor": "#2E6FB7",
      "textColor": "#000",
      "brandColor": "#2E6FB7",
      "cornerRadius": "1",
      "hideUnzerLogo": "false",
      "backgroundImage": "https://www.mydomain.de/img/logo3.png",
      "font": "Arial",
      "shadows": "true",
      "favicon": "https://www.mydomain.de/img/logo_rb_uzr.png"
  },
  "paymentMethodsConfigs": {
      "default": {
          "enabled": false
      },
      "cards": {
          "enabled": true,
          "order": 1
      },
      "paypal": {
          "enabled": true,
          "order": 2
      },
      "klarna": {
          "enabled": true,
          "order": 3
      },
      "eps": {
          "enabled": false,
          "order": 0
      }
  },
  "customerSettings": {
      "type": "b2c",
      "allowedCountries": [
          "DE"
      ]
  },
  "resources": {
      "customerId": "{{customerId}}",
      "basketId": "{{basketId}}"
  }
}
$unzer = new Unzer('s-priv-xxxxxxxxxx');
$paypage = new Paypage(9.99, 'EUR'); // charge as default type.
//or if authorize is preferred:
//$paypage = new Paypage(9.99, 'EUR', 'authorize');

$paypage->setType("embedded");

//it is recommended to add a customer object.
$customer = $unzer->createCustomer(CustomerFactory::createCustomer('Max', 'Mustermann'));

$resources = new Resources($customer->getId(), null, null);
$paypage->setResources($resources);

$unzer->createPaypage($paypage);
// Redirect to the paypage
redirect($paypage->getRedirectUrl());
Coming Soon!

The response looks similar to the following example:

{
  "paypageId": "01927c33-871f-73fa-9e68-22577cc4c369-b4818aba-d4a2-4193-818a-bad4a2e19352",
  "redirectUrl": "https://static.int.unzer.com/v2/paypage/#/01927c33-871f-73fa-9e68-22577cc4c369-b4818aba-d4a2-4193-818a-bad4a2e19352?publicKey=cy1wdWItMmExMGFlQU1Xd0VNSGx0SEpqUW8zMmowRk5UakJNWkQ=",
  "qrCodeSvg": null
}

For a complete list of parameters, see the Payment Page Reference.

Optional: Common features

Recurring payments

To create a Payment Page for recurring payments, you need to provide the recurrenceType flag in the create Payment Page call.

icon
The recurrenceType flag is optional and only needed if you want to create a Payment Page with recurring payments.

The following recurrence types are supported by our payment pages: unscheduled and scheduled.

The recurrence type oneclick is automatically set whenever a previously stored One-click payment type is used or the customer enables the checkbox to store the payment type for future payments.

icon
Currently, the recurrence types scheduled and unscheduled are only supported for the card payment method. This means that the list of payment methods will be reduced to this payment method and the other payment methods will be hidden.

For more information, go to the recurring payments page.

{
  "mode": "authorize",
  "amount": "84.9000",
  "currency": "EUR",
  "recurrenceType": "scheduled",
  "resources": {
    "customerId": "{{customerId}}",
    "basketId": "{{basketId}}"
  }
}
$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setRecurrenceType("scheduled");
$unzer->createPaypage($paypage);
Coming Soon!

Select a checkout type

Payment pages support different checkout types. The following checkout types are supported:

  • full: Customer-related data, like billing and shipping address, are required and corresponding form fields are rendered. If a customerId is set in the initial request, the forms will be preloaded.
  • payment_only: Customer-related forms are not rendered.
  • no_shipping: Only the billing address form are rendered. This is useful for digital goods or services.

If you create a payment page with disabled customer form, keep in mind that some payment methods require a customer object. In these cases, the customerId needs to be provided in the create payment page call, otherwise those payment methods will not be available.

{
  "mode": "authorize",
  "amount": "84.9000",
  "currency": "EUR",
  "checkoutType": "payment_only",
  "resources": {
    "customerId": "{{customerId}}",
    "basketId": "{{basketId}}"
  }
}
$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setCheckoutType("payment_only");
$unzer->createPaypage($paypage);
Coming Soon!

Create a payment page with custom return URLs

icon
The returnURL is only required for LinkPay and Hosted Payment Page.

To redirect the end customer to the correct result URL in your system, you can set the following URLs.

If no URL is set, the payment page will render default result pages instead.

{
  ...
  "urls": {
    "returnSuccess": "https://example.com/success",
    "returnPending": "https://example.com/pending",
    "returnFailure": "https://example.com/failure",
    "returnCancel": "https://example.com/cancel"
  }
  ...
}
$urls = new Urls();
$urls->setReturnSuccess('https://returnsuccess.com');
$urls->setReturnPending('https://returnpending.com');
$urls->setReturnFailure('https://returnfailure.com');
$urls->setReturnCancel('https://returncancel.com');

$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setUrls($urls);

$unzer->createPaypage($paypage);
Coming Soon!

To redirect the end customer to the correct informational pages of your shop, such as imprint, contact, help, you can set the corresponding URLs in the urls section of the request body.

icon
If no URL is set, the corresponding link will not be rendered.
{
  ...
  "urls": {
    "termsAndCondition": "https://example.com",
    "privacyPolicy": "https://example.com",
    "imprint": "https://example.com",
    "help": "https://example.com",
    "contact": "https://example.com"
  },
  ...
}
$urls = new Urls();
$urls->setTermsAndCondition('https://termsandcondition.com');
$urls->setPrivacyPolicy('https://privacypolicy.com');
$urls->setImprint('https://imprint.com');
$urls->setHelp('https://help.com');
$urls->setContact('https://contact.com');

$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setUrls($urls);

$unzer->createPaypage($paypage);
Coming Soon!

Exclude payment methods

You can configure payment methods so that a subset of the available payment methods is displayed or is available during checkout. In such cases, you can either disable single payment methods to limit the list by setting specific payment method related enabled flag to false, or disable all of them using the default.enabled flag and enable only the ones you want to offer in the checkout.

You can specify the order or sort the payment methods in the payment form by setting the order as described in the example here.

icon
By default, all payment methods configured in your account are enabled and displayed on your payment pages.
{
  "mode": "charge",
  "amount": "84.9000",
  "currency": "EUR",
  "paymentMethodsConfigs": {
    "default": {
      "enabled": false
    },
    "cards": {
      "enabled": true,
      "order": 0
    },
    "bancontact": {
      "enabled": true,
      "order": 1
    },
    "googlepay": {
      "enabled": true,
      "order": 2
    }
  },
  "resources": {
    "customerId": "{{customerId}}",
    "basketId": "{{basketId}}"
  }
}
$enabledConfig = new PaymentMethodConfig(true, 1);
$paylaterConfig = (new PaymentMethodConfig(true, 1))
    ->setLabel('Paylater');
$cardConfig = (new PaymentMethodConfig(true, 1))
    ->setCredentialOnFile(true)
    ->setExemption(ExemptionType::LOW_VALUE_PAYMENT);

$configs = (new PaymentMethodsConfigs())->setPreselectedMethod('cards')
    ->setDefault((new PaymentMethodConfig())->setEnabled(false)) //enable or disable all payment methods by default
    ->addMethodConfig(Card::class, $cardConfig)
    ->addMethodConfig(PaylaterInstallment::class, $enabledConfig)
    ->addMethodConfig(Googlepay::class, $enabledConfig)
    ->addMethodConfig(Applepay::class, $enabledConfig)
    ->addMethodConfig(PaylaterInvoice::class, $paylaterConfig);

$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setPaymentMethodsConfigs($configs);
$unzer->createPaypage($paypage);
Coming Soon!

Risk settings

The following risk related settings can be passed and may increase the acceptance rate.

ParameterTypeDescriptionExample values
risk.customerGroupstringCustomer classification for the customer if known. Valid values:
TOP: Customers with more than 3 paid transactions
GOOD: Customers with more than 1 paid transactions
BAD: Customers with defaulted/fraudulent orders
NEUTRAL: Customers without paid transactions
"GOOD"
risk.confirmedAmountintThe amount/value of the successful transactions paid by the end customerPositive number: 891
risk.confirmedOrdersintThe number of successful transactions paid by the end customerPositive number: 10
risk.registrationLevelstringCustomer registration level
0=guest, 1=registered
"0"
risk.registrationDatestringCustomer registration date in your shop
(YYYYMMDD)
"2019-01-01"
{
  "mode": "authorize",
  "amount": "84.9000",
  "currency": "EUR",
  "risk": {
    "registrationLevel": "string",
    "registrationDate": "string",
    "customerGroup": "top",
    "confirmedOrders": 0,
    "confirmedAmount": 0
  },
  "resources": {
    "customerId": "{{customerId}}",
    "basketId": "{{basketId}}"
  }
}
$risk = new RiskData();
$risk->setCustomerGroup('TOP')
    ->setConfirmedAmount(1234)
    ->setConfirmedOrders(42)
    ->setRegistrationLevel('1')
    ->setRegistrationDate('20160412');

$paypage = new Paypage(9.99, 'EUR', 'charge');
$paypage->setRisk($risk);
$unzer->createPaypage($paypage);
Coming Soon!

Credentials on file (COF)

You can enable storing payment methods on your payment page to make it easier for returning customers to pay.
This feature is called Credentials on File (COF) and is supported by the following payment methods:

  1. card
  2. sepa-direct-debit
  3. paypal

Enable the feature for a payment method by use of the flag credentialOnFile in the corresponding object within paymentMethodConfigs.

icon
  • COF payments in combination with cards automatically triggers a One-click payment.
  • Because the payment methods related to the customer are presented in the frontend, this feature requires the customerId to be set.
{
  "mode": "authorize",
  "amount": "84.9000",
  "currency": "EUR",
  "paymentMethodsConfigs": {
    "card": {
      "credentialOnFile": true
    }
  },
  "resources": {
    "customerId": "p-cst-1234"
  }
}
$paypage = new Paypage(9.99, 'EUR', 'charge');

$cardConfig = (new PaymentMethodConfig())->setCredentialOnFile(true);
$config = (new PaymentMethodsConfigs())->addMethodConfig(Card::class, $cardConfig);
$paypage->setPaymentMethodsConfigs($config);

$unzer->createPaypage($paypage);
Coming Soon!

Step 3: Initialize payment page
client side

Load the JS script

Add Unzer’s JavaScript to your website. You should always load the script directly from https://static-v2.unzer.com:

<script type="text/javascript" src="https://static-v2.unzer.com/v2/ui-components/index.js"></script>
icon
Faster load time
To make your website load faster, insert the JavaScript at the bottom of your HTML document.

Step 4. Handle the customer’s Pay action
client side

Now implement a function that listens to a click or submit event on your checkout page. When a customer calls the checkout action, use checkout.open() to display the Embedded Payment Page overlay. You can also register your event listeners on the following events:

  • checkout.abort() - on abort, for example, when the client cancels payment by selecting the close button.
  • checkout.success() - on payment success.
  • checkout.error() - on error (non-recoverable, the payment page has become invalid).
<unzer-payment publicKey="p-pub-123">
  <unzer-pay-page payPageId="123"></unzer-pay-page>
</unzer-payment>
// Add your event listener for abort event
checkout.abort(function() {
  // handle abort event.
  $errorHolder.html('Transaction canceled by user.');
  $submitButton.attr("disabled", false);
});

// Add your event listener for success event
checkout.success(function(data) {
    // handle success event.
    // for example, redirect to success page.
    window.location.href = 'ReturnController.php';
});

// Add your event listener for error event
checkout.error(function(error) {
  // handle error event.
  // you can use checkout._hideIframe() to close payment pop-up
  $errorHolder.html(${JSON.stringify(errorData, null, 2)});
  $submitButton.attr("disabled", false);
});

// open the Embedded Payment Page overlay
checkout.open();

A full working example with a simple button, which displays the Embedded Payment Page:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="utf-8" />
    <title>Embedded Payment Page</title>
    <script>
        Promise.all([
            customElements.whenDefined("unzer-payment"),
            customElements.whenDefined("unzer-pay-page"),
        ]).then(() => {
            const btnCheckout = document.getElementById("btn-checkout");
            btnCheckout.addEventListener("click", showCheckout);
        });

        function showCheckout() {
            const unzerContainer = document.getElementById("unzer-container");
            unzerContainer.innerHTML = `
            <unzer-payment publicKey="{{PUBLIC_KEY}}">
                <unzer-pay-page
                    id="checkout"
                    payPageId="{{PAYPAGE_ID}}"
                ></unzer-pay-page>
            </unzer-payment>
        `;

            const checkout = document.getElementById("checkout");

            // Subscribe to the abort event
            checkout.abort(function () {
                // handle abort event.
                console.log("checkout -> aborted");
                //$errorHolder.html("Transaction canceled by user.");
                //$submitButton.attr("disabled", false);
            });

            // Subscribe to the success event
            checkout.success(function (data) {
                // handle success event.
                console.log("checkout -> success", data);
                window.location.href = "ReturnController.php";
            });

            // Subscribe to the error event
            checkout.error(function (error) {
                console.log("checkout -> error", error);
                // handle error event.
                // you can use checkout._hideIframe() to close payment pop-up in this case
            });

            // Render the Embedded Payment Page overlay
            checkout.open();
        }
    </script>

    <script
            type="module"
            src="https://static-v2.unzer.com/v2/ui-components/index.js"
    ></script>
</head>

<body>
  <button id="btn-checkout">Checkout</button>
  <div id="unzer-container"></div>
</body>
</html>

Step 5: Check payment status
server side, client side

For payment methods that don’t require the customer to redirect to an external site to complete the payment, the checkout.success() or checkout.error() events will be triggered after the customer clicks the Pay button.
In your event listeners, you can react to the given event, handle the payment status and display the result to your customer as shown in the example in Step 4.
Check all possible payment states here.

For redirect payment methods, the customer gets redirected to an external payment site to finalize their payment.
Once the payment is done, they are redirected to one of the return URLs, that you set in Step 2.
Now you can fetch the payment resource and check its status.

There are a few ways the payment can be verified after the return URL is called:

  • Via a GET call and the paypageId here, which returns paymentId and transaction status.
  • Via a GET call and the paymentId here, which returns paypageId and payment details.
  • Via Webhook: Subscribe to the payment webhook and receive the paymentId.
icon
  • Don’t forget to verify that the paymentId that you receive in the returnUrl belongs to the paypageId.
  • For security reasons, we recommend that you always check that the payment ID that you received in the return URL matches the paypage ID. This is because of the risk when the browsers allow their users to manipulate any query parameters.

Get payments via Paypage ID

This endpoint can be called after the payment page is finished and the customer has returned to the shop. It will contain the paymentId, status and information about failures. For LinkPay with multiuse, this endpoint will contain all payments.

The current status of the payment can be seen in the response.

GET https://paypage.unzer.com/v2/merchant/paypage/{paypageId}
{
  "payments": [
    {
      "paymentId": "s-pay-1",
      "transactionStatus": "success",
      "creationDate": "2024-08-22T14:42:57.944Z",
      "messages": [
        {
          "code": "string",
          "customer": "string",
          "merchant": "string"
        }
      ]
    }
  ],
  "total": 0
}

Get Payment via Payment ID

This endpoint can be called after the payment page is finished and the customer has returned to the shop with the paymentId parameter passed in the URL. Keep in mind to verify that the paymentId received in the returnUrl belongs to the paypageId.

GET https://api.unzer.com/v1/payments/{paymentId}
{
    "id": "s-pay-131937",
    "state": {
        "id": 1,
        "name": "completed"
    },
    "amount": {
        "total": "20.0000",
        "charged": "20.0000",
        "canceled": "0.0000",
        "remaining": "0.0000"
    },
    "currency": "EUR",
    "orderId": "",
    "invoiceId": "",
    "resources": {
        "customerId": "",
        "paymentId": "s-pay-131937",
        "basketId": "",
        "metadataId": "",
        "payPageId": "12345",
        "traceId": "70ddf3152a798c554d9751a6d77812ae",
        "typeId": "s-eps-grpucjmy5zrk"
    },
    "transactions": [
        {
            "date": "2021-05-10 00:51:03",
            "type": "charge",
            "status": "success",
            "url": "https://api.unzer.com/v1/payments/s-pay-131937/charges/s-chg-1",
            "amount": "20.0000"
        }
    ]
}
icon
You should handle the status according to the payment method used by the customer.

Step 6: Display payment result
client side

After the transaction, you should display its result to the customer in the frontend using the information from the previous step.

icon
Note that depending on the payment method used, information relevant for the customer as a part of the success/error message can differ. For example, for Unzer Invoice and Unzer Prepayment you should display payment details to the customer on the success page.

Notifications

We recommend subscribing to the payment event to receive notifications about any changes to the payment resource. As soon as the event is triggered you should fetch the payment and update the order status in your shop according to its status.

  {
    "event":"payment.pending",
    "publicKey":"s-pub-xxxxxxxxxx",
    "retrieveUrl":"https://api.unzer.com/v1/payments/s-pay-774",
    "paymentId":"s-pay-774"
  }

For more details on implementing webhooks to receive notifications, see Notifications page.

Localization

To localize your page, pass the locale value in the locale attribute of the <unzer-payment> component. If the locale is not set, the browser language will be used. We will fall back to our default locale, which is “en-GB” in case of any trouble detecting a valid/supported locale.

Please refer to the following list of supported locales/languages:

  • en, en-GB (default)
  • de, de-DE
  • nl, nl-NL
  • da, da-DK
<unzer-payment publicKey="p-pub-123" locale="de-DE">
  <unzer-pay-page payPageId="123456789"></unzer-pay-page>
</unzer-payment>

Customization

The following customization options are available for the Payment Pages:

ParameterTypeDescriptionDefault value
style.fontstringThe font to be used through out the Payment Page.
TBD
style.brandColorstringThe color to be used as base color, such as the button color. Other colors will be derived from this color. For example, interactive state colors such as hover, focus and pressed, selected, loader and component colors.
TBD
style.shadowsbooleanThe style for the shadows.
TBD
style.textColorstringThe color of text, icons and borders on the page.#0C1332
style.linkColorstringThis will affect the link color and the inverse link color.#1B6AD7
style.backgroundColorstringThe background color of the payment page.#F1F1F3
style.cornerRadiusstringThe corner radius of elements in pixels.6
style.hideUnzerLogobooleanWill show “Secure checkout” instead of “Secure checkout by Unzer” in the bottom right corner of the payment page.false
style.logoImagestringWill show the given logo image in the top left of the payment page. The following formats are supported: jpg, svg and png.Will show the shopName if not set.
style.backgroundImagestringWill render the given image in the background of the payment page. The following formats are supported: jpg and png.Will use the backgroundColor if not set.
style.footerColorstringChanges the footer color to the given value.
TBD
style.headerColorstringChanges the header color to the given value.white
style.hideBasketbooleanHides the basket information within the “ORDER SUMMARY” section. It will appear as if no basket has been set on init payment page, however payment methods requiring the basket will still be availablewhite
style.faviconstringURL to your favicon file. Supported formats: ico, gif, png.
Link Pay and Hosted Page only
none
shopNamestringShop name will be shown next to the shop logo, as alias to the logo image and in the title (not EPP).none
POST https://paypage.unzer.com/v2/merchant/paypage

{docker build ./mocks --tag "connectivity/mocks:latest"
  ...
  "shopName": "My Shop Name",
  "style": {
      "font": "arial",
      "headerColor": "#123456",
      "footerColor": "#123456",
      "brandColor": "#123456",
      "textColor": "#123456",
      "linkColor": "#123456",
      "backgroundColor": "#123456",
      "cornerRadius": "6",
      "logoImage": "https://logo-image-url",
      "backgroundImage": "https://background-image-url",
      "shadows": true,
      "hideUnzerLogo": true,
      "hideBasket": true,
      "favicon": "https://favicon-url"
  },
  ...
}
// ...
$paypage->setLogoImage('https://logo-image-url');
// ...
...
paypage.setLogoImage('https://logo-image-url');
...

Customize the basket item images

You can set individual basket images that show on the Payment Page. Check the Basket resource documentation page for details: Manage basket (direct API calls), Manage basket (PHP SDK), Manage basket (Java SDK).

{
  "totalValueGross": "84.9000",
  "currencyCode": "EUR",
  "orderId": "",
  "basketItems": [ {
      "basketItemReferenceId": "item-1",
      "quantity": "2",
      "vat": "0E-7",
      "amountDiscountPerUnitGross": "0.0000",
      "amountPerUnitGross": "20.0000",
      "title": "Hoodie",
      "unit": "Pc.",
      "subTitle": "Clothes",
      "type": "goods",
      "imageUrl": "https://stg-static.unzer.com/assets/images/baskets/ZippHoodie_Unzer.jpg"
    },
    {
      "basketItemReferenceId": "item-2",
      "quantity": "6",
      "vat": "0E-7",
      "amountDiscountPerUnitGross": "0.0000",
      "amountPerUnitGross": "5.0000",
      "title": "Writing Pad",
      "unit": "Pc.",
      "subTitle": "Office Supplies",
      "type": "goods",
      "imageUrl": "https://stg-static.unzer.com/assets/images/baskets/WritingPad.jpg"
    },
    {
      "basketItemReferenceId": "item-6",
      "quantity": "10",
      "vat": "0E-7",
      "amountDiscountPerUnitGross": "0.0000",
      "amountPerUnitGross": "1.9900",
      "title": "Screws",
      "unit": "Pc.",
      "subTitle": "hardened aluminium",
      "type": "goods",
      "imageUrl": "https://stg-static.unzer.com/assets/images/baskets/WritingPad.jpg"
    },
    {
      "title": "10 EUR voucher newsletter registration",
      "basketItemReferenceId": "item-3",
      "quantity": 1,
      "amountPerUnitGross": 0.00,
      "amountDiscountPerUnitGross": 10.00,
      "vat": 1,
      "type": "voucher"
    },
    {
      "title": "Shipment costs",
      "basketItemReferenceId": "item-4",
      "quantity": 1,
      "amountPerUnitGross": 5.00,
      "vat": 1,
      "subTitle": "Insured standard shipment",
      "type": "shipment"
    }]
}

Manage payment

After you have made a transaction, you can perform additional operations on it. A common example is the cancel operation which is applicable for most of the payment methods.

Cancel before money receipt (reversal)

To cancel a reservation on the customers account or reduce its amount you need to perform a cancel on the initial transaction. An example of reversal would be unblocking reserved amount on customer account after they returned a rented car.

POST https://api.unzer.com/v1/payments/s-pay-1/authorize/cancels

{
  "amount" : "100.00"
}
$unzer = new Unzer('s-priv-xxxxxxxxxx');
$payment = $unzer->fetchPayment('s-pay-1');
$unzer->cancelAuthorizationByPayment($payment, 100.00);
Unzer unzer = new Unzer("s-priv-xxxxxxxxxx");
Authorization authorization = unzer.fetchAuthorization('s-pay-1');
Cancel cancel = authorization.cancel();
{
  "id": "s-cnl-1",
  "isSuccess": true,
  "isPending": false,
  "isError": false,
  "card3ds": false,
  "message": {
    "code": "COR.000.100.112",
    "merchant": "Request successfully processed in 'Merchant in Connector Test Mode'",
    "customer": "Your payments have been successfully processed in sandbox mode."
  },
  "amount": "100.0000",
  "currency": "EUR",
  "date": "2021-06-10 10:47:43",
  "resources": {
    "customerId": "",
    "paymentId": "s-pay-1",
    "basketId": "",
    "metadataId": "",
    "payPageId": "",
    "traceId": "d9763d2fdd7830bdd73f76957423f351",
    "typeId": "s-crd-e6f2yo8ggwhg"
  },
  "paymentReference": "",
  "processing": {
    "uniqueId": "31HA07BC8174FCB9564077FB19AEF03B",
    "shortId": "4872.4846.3345",
    "traceId": "d9763d2fdd7830bdd73f76957423f351"
  }
}

Cancel after money receipt (refund)

To refund a payment you need to perform a cancel on a successful charge transaction. This transfers the money back to the customer.

POST https://api.unzer.com/v1/payments/s-pay-1/charges/s-chg-1/cancels
{
  "amount" : "12.450",
  "paymentReference": "Test cancel transaction"
}
$unzer = new Unzer('s-priv-xxxxxxxxxx');
$charge = $unzer->fetchChargeById('s-pay-1', 's-chg-1');
$cancel = $charge->cancel();
Unzer unzer = new Unzer("s-priv-xxxxxxxxxx");
Cancel cancel = unzer.cancelCharge("s-pay-1", "s-chg-1");

The response will look similar to the following example:

{
  "id": "s-cnl-1",
  "isSuccess": true,
  "isPending": false,
  "isError": false,
  "message": {
    "code": "COR.000.100.112",
    "merchant": "Request successfully processed in 'Merchant in Connector Test Mode'",
    "customer": "Your payments have been successfully processed in sandbox mode."
  },
  "amount": "12.450",
  "currency": "EUR",
  "date": "2021-06-10 10:42:31",
  "resources": {
    "customerId": "",
    "paymentId": "s-pay-1",
    "basketId": "",
    "metadataId": "",
    "payPageId": "",
    "traceId": "980df34e485a2dac0019e998b1b044cb",
    "typeId": "s-sdd-ixdcookaqpzu"
  },
  "paymentReference": "",
  "processing": {
    "uniqueId": "31HA07BC8174FCB9564040C4B8564729",
    "shortId": "4872.4815.1981",
    "traceId": "980df34e485a2dac0019e998b1b044cb"
  }
}

To learn about payment management for specific payment methods, go to the relevant payment method page.

Error handling

All requests to the API can result in an error that should be handled. Refer to the Error handling guide to learn more about Unzer API (and other) errors and handling them.

Test & go live

You should always test your integration before going live. First perform test transactions using test data. Next, check against Integration checklist and Go-live checklist to make sure the integration is complete and you’re ready to go live.

See also