Integrate using Link Pay Page (v1)
Accept payments through a customizable, ready-made Link Pay page hosted on your server.
Link Pay Payment Page v1 will be deprecated soon.
- If you have an existing integration, go the Migration guide for more details.
- If you are integrating for the first time, go to Linkpay payment page v2.
Overview
Link Pay is an all-in-one solution that displays the configured payment methods on a Unzer-hosted webpage. You do not have to manually implement individual payment methods on your website. Instead, you only need to call Unzer API once and create a common URL (unlike unique URL created via Hosted Payment Page) that you will use to redirect your users to finalize their payments.
User interface
Depending on your requirements, you can render the Link Pay UI in different ways.
If you have a basket with various items, it is displayed with a list of all your configured payment methods on the right hand side. You can also choose not to display any basket items at all and only render the payment method list. These two options are identical to the Hosted Payment Page.
In addition, you will have an option to show a box containing amount and currency input fields. These fields can (but don’t have to) be editable by the end users. The box will be visible only in case amount or currency values are not passed when creating an instance of Link Pay.
All these options are fully responsive on tablets and phones.
Different scenarios for using Link Pay:
- Use Link Pay with a fixed amount if the customer should pay a fixed amount. You can also provide basket information to show what the customer is purchasing. Alternatively, you can also skip the amount. In this case the customer has to enter the amount themselves.
- Specify the
orderId
orinvoiceId
if you want the customer to enter an order ID or invoice ID so that you can clearly assign the payment to the order of one customer. - You can also specify an
alias
. Thealias
is also used within the URL. This is good in case you want to provide the customer a human readable link. For example, the following is the view of a Link Pay page with amount and currency box:
Before you begin
Check the basic integration requirements.
How it works
- First, you need to set up the Link pay page – create
customer
andbasket
resources. - Now initialize the Link pay page on the server side by making a Link Pay POST request to the Unzer API that returns a Link Pay URL.
- Once you have the URL, you can send your customers to this link where they will be able to finalize a purchase.
- With
basketId
When the basket exists, the customer can verify the list of items in the basket that they are buying. The basket is rendered on the left side of the page. - Without
basketId
and amount or currency When the basket does not exist, and either amount or currency are not set when making a POST/PUT request, the users will see the amount and currency box, and will be able to add the values themselves.
- With
- The customer makes the payment using this link.
- After the payment is made you should check its status on the server side and display the result to the customer on the client side.
- You can perform more operations on the server side once the payment has been made – most common example would be cancelling the payment.
Once your customer gets redirected to the Link Pay Page, there are a few possible cases:
Another difference between Link Pay and Hosted or Embedded Payment Pages is that there are no keys required when initializing a Link Pay page.
Step 1: Set up the Link Pay pageserver side
First, you should prepare resources needed when initializing the Link Pay page on the server side—customer
, basket
(recommended), and the metadata (optional) resources.
Create the customer resource (recommended)
The customer
resource contains information about the customer and is required for card, Unzer Invoice, Direct Debit Secured, Unzer Installment, and Klarna payment methods.
The customer resource is also required for the deprecated payment methods.
- When you provide a
customerId
when crating the link, you should only send the link to the customer that was specified when creating thelinkpay
resource. - We recommend that you always provide the customer resource.
To use an existing customer
resource, you 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"
}
}
Linkpay currently not supported.
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);
customer
resource available, built-in customer forms are displayed on the Link Pay page.If you want to pass a customerId
to your Link Pay page, add it to the resources object within the request body:
Create the basket resource (recommended)
The basketId
contains all the product information relevant to the transaction. It is required for Unzer Invoice, Direct Debit Secured, Unzer Installment, and Klarna . We recommend that you always create a basket
resource.
POST https://api.unzer.com/v1/baskets
{
"amountTotalGross" : 200.00,
"amountTotalDiscount" : 10.00,
"amountTotalVat" : 33.33,
"currencyCode" : "EUR",
"orderId" : "Order-12345",
"note" : "Test Basket",
"basketItems" : [ {
"basketItemReferenceId" : "Item-d030efbd4963",
"unit" : "m",
"quantity" : 10,
"amountDiscount" : 10.00,
"vat" : 0.2,
"amountGross" : 200.00,
"amountVat" : 33.33,
"amountPerUnit" : 16.667,
"amountNet" : 166.67,
"title" : "SDM 6 CABLE",
"subTitle" : "This is brand new Mid 2019 version",
"imageUrl" : "https://a.storyblok.com/f/91629/x/1ba8deb8cc/unzer_primarylogo__white_rgb.svg",
"type": "goods"
} ]
}
Linkpay currently not supported.
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);
Once you have the basketId
, you can pass it to the Link Pay request body.
For a full description of basket
resource, check the relevant server-side-integration documentation page: Manage basket (direct API calls), Manage basket (PHP SDK), Manage basket (Java SDK).
If chose to pass a basketId
to Link Pay, add it to the resources object within the request body:
{
...
"resources": {
"basketId": "s-bsk-1"
}
...
}
(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. You can append additional information for each payment. Add the metadata by adding it in the additional resources.
{
...
"resources": {
"basketId": "s-bsk-1",
"customerId": "s-cst-1",
"metadataId": "s-mtd-1",
},
...
}
Step 2: Initialize Link Pay page
You can initialize the Link Pay page to support either charge
or authorize
transactions. For a description of charge
and authorize
transactions, refer to relevant server-side integration documentation page: Manage API resources (direct API calls), Manage API resources (PHP SDK), Manage API resources (Java SDK).
Initialize Link Pay page for the charge or authorize transaction
POST - https://api.unzer.com/v1/linkpay/charge
Request body:
{
"amount": "100",
"alias": "unique-alias",
"currency": "EUR",
"returnUrl": "https://www.unzer.com",
"expires": "2200-10-20",
"card3ds": "true",
"billingAddressRequired": "false",
"shippingAddressRequired": "false",
"orderIdRequired":"false",
"invoiceIdRequired":"false",
"fullPageImage": "https://www.any.ed/photos/302743/pexels-photo-302743.jpeg",
"shopDescription": "Your purchase",
"logoImage": "https://insights.unzer.com/static/unzerLogo.svg",
"tagline": "Established 1862",
"shopName": "Company XYZ",
"helpUrl": "https://www.unzer.com",
"contactUrl": "https://www.unzer.com",
"termsAndConditionUrl": "https://www.unzer.com",
"privacyPolicyUrl": "https://www.unzer.com",
"imprintUrl": "https://www.unzer.com",
"intention": "Checkout",
"additionalAttributes": {
"exemptionType": "lvp"
},
"resources": {
"customerId": "s-cst-1",
"basketId": "s-bsk-1",
"metadataId": "s-mtd-1"
}
}
Linkpay currently not supported.
// Currently only available for charge.
Unzer unzer = new Unzer("s-priv-xxxxxxxxxx");
Linkpay linkpay = new Linkpay();
linkpay.setAmount("100");
linkpay.setAlias("unique-alias");
linkpay.setCurrency("EUR");
linkpay.setReturnUrl(unsafeUrl("https://www.unzer.com"));
linkpay.setExpires("2200-10-20");
linkpay.setCard3ds("true");
linkpay.setBillingAddressRequired("false");
linkpay.setShippingAddressRequired("false");
linkpay.setOrderIdRequired("false");
linkpay.setInvoiceIdRequired("false");
linkpay.setFullPageImage(unsafeUrl("https://www.any.ed/photos/302743/pexels-photo-302743.jpeg"));
linkpay.setShopDescription("Your purchase");
linkpay.setLogoImage("http://www.any.ed/images/page/info-img.png");
linkpay.setTagline("Established 1862");
linkpay.setShopName("Company XYZ");
linkpay.setHelpUrl("https://www.unzer.com");
linkpay.setContactUrl("https://www.unzer.com");
linkpay.setTermsAndConditionUrl(unsafeUrl("https://www.unzer.com"));
linkpay.setPrivacyPolicyUrl(unsafeUrl("https://www.any.ed/policy"));
linkpay.setImprintUrl(unsafeUrl("https://www.any.ed/impressum"));
Map<String, String> additionalAttributes = new HashMap<>();
additionalAttributes.put("exemptionType", "lvp");
linkpay.setAdditionalAttributes(additionalAttributes);
linkpay.setCustomerId("s-cst-1");
linkpay.setBasketId("s-bsk-1");
linkpay.setMetadataId("s-mtd-1");
// Initialize the linkpay
linkpay = unzer.linkpay(linkpay);
The response looks similar to the following example:
POST - https://api.unzer.com/v1/linkpay/charge
Request body:
{
"id": "s-lpy-xyz",
"redirectUrl": "https://sbx-payment.unzer.com/v1/paypage/linkpay/s-lpy-xyz",
"version": "1",
"alias": "unique-alias",
"orderId": "",
"invoiceId": "",
"amount": "100",
"currency": "EUR",
"returnUrl": "https://www.unzer.com",
"logoImage": "http://www.any.ed/images/page/info-img.png",
"shopName": "Company XYZ",
"shopDescription": "Your purchase",
"tagline": "Established 1862",
"css": {},
"termsAndConditionUrl": "https://www.unzer.com",
"privacyPolicyUrl": "https://www.unzer.com",
"imprintUrl": "http://www.any.ed/impressum",
"helpUrl": "https://www.unzer.com",
"contactUrl": "https://www.unzer.com",
"card3ds": "true",
"billingAddressRequired": "false",
"shippingAddressRequired": "false",
"expires": "2200-10-20",
"intention": "Checkout",
"paymentReference": "",
"additionalAttributes": {
"effectiveInterestRate": "3",
"exemptionType": "lvp"
},
"orderIdRequired":"false",
"invoiceIdRequired":"false",
"oneTimeUse": "false",
"excludeTypes": [],
"resources": {
"paymentId": "",
"customerId": "s-cst-1",
"basketId": "s-bsk-1",
"metadataId": "s-mtd-1"
},
"action": "CHARGE"
}
- You need to request a new payment page every time your customer pays. That also includes failed transactions.
- Each payment page expires after 60 minutes.
- Each payment page becomes invalid after a successful payment.
- Each payment page becomes invalid if an unrecoverable error occurs, which mean that the payment type creation was successful but payment transaction failed.
Set additional attributes
Depending on the use case of your pay page integration, you might need to set the following additionalAttributes
:
Additional attributes
Parameter | Description | Example value |
---|---|---|
effectiveInterestRate | For Unzer Installment you need to provide the effectiveInterestRate parameter in the Authorize call. Positive floating point value allowed. | "4.99" |
exemptionType | Exemption type is used for card payment method. Allowed values:lvp : See more Low Value Exemptionstra : See more Transaction Risk Analysis | lvp |
disabledCOF | Allows disabling COF for defined payment types. Available values that can be passed as a coma-separated string: card , paypal , sepa-direct-debit | card |
recurrenceType
is not supported by Linkpay.When using the Google Pay payment method, make sure to set required additionalAtributes
as listed below.
Parameter | Type | Description | Example values |
---|---|---|---|
googlepay.countryCode | string | The countryCode can be set to the one submitted to merchant upfront in the contract or in a separated email. Currently supported values are CH and DK . Default value is DK . | CH or DK |
googlepay.buttonColor | string | The buttonColor can be set to change the color of the button. Default value is black . | white . |
When using the Apple Pay payment method, make sure to set required additionalAtributes
as listed below.
Parameter | Type | Description | Example values |
---|---|---|---|
applepay.countryCode | string | The merchant’s two-letter ISO 3166 country code. For more information, see countryCode | "DE" |
applepay.merchantCapabilities | string | Comma separated string of the payment capabilities that the merchant supports, such as credit or debit. For more information, see merchantCapabilities | "supports3DS, supportsCredit" |
Link Pay specific properties
alias
When creating a Link Pay page, you can pass a unique value for the alias
key.
The value of this key can be used to replace a long ID that you receive by default as the last part of the redirectUrl
value.
An alias
can not be used in combination with orderId
or invoiceId
.
Using this feature, you can customize the Link Pay URL according to your corporate image requirements.
alias
can only be set during the initial POST call.expires
You can choose whether you wish your Link Pay instance to expire after a certain time frame. Accepted formats are YYYY-mm-dd or YYYY-mm-dd hh:mm:ss.
If you don’t add any value, your Link Pay instance will never expire.
oneTimeUse
With oneTimeUse
you can set the Link Pay instance to only be usable for one payment. After a successful payment Link Pay resource will contain a paymentId
as linked resource.
You can not set oneTimeUse
directly. To create a Link Pay page with oneTimeUse
, it is required to set the orderId
or invoiceId
in your initialization request.
The created resource will then have set oneTimeUse
to “true”, which can be found in the response.
orderIdRequired
The default value of this property is false
. If this property is set as true
, users always have to pass orderId
in any transaction request (authorize or charge) using the Link Pay. If the orderId
is not already defined, an input field is displayed for the customer to add this value themselves.
invoiceIdRequired
The default value of this property is false
. If this property is set as true
, users always have to pass invoiceId
in any transaction request (authorize or charge) via Link Pay. In case invoiceId
is not already defined, an input field is displayed for the customer to add this value themselves.
Update the Link Pay instance
The update option is one of the unique features of Link Pay (on contrary, it is not possible to update an instance of Hosted Payment Page).
This step includes making a PUT request to our API, and sending a JSON object with correct values. You can use your Link Pay page’s ID or alias values for creating a PUT request.
In case all data is valid, the Link Pay instance that you have already created will be updated.
PUT - https://api.unzer.com/v1/linkpay/{{linkpayId}}
// Linkpay can also be updated using {{alias}} instead of {{linkpayId}}
Request body:
{
// request body can contain the same keys as in the POST request
}
Currently not supported.
Delete the Link Pay instance
If you want, you can delete the instance of your Link Pay. To delete, make a DELETE request to our API and pass either a valid ID or alias.
DELETE - https://api.unzer.com/v1/linkpay/{{linkpayId}}
// Linkpay can also be deleted using {{alias}} instead of {{linkpayId}}
Currently not supported.
Optional: Exclude payment methods
If you want to exclude some of the payment methods from the Embedded Payment Page, add the arrayexcludeTypes
when initializing on the server side. Put all payment types you want to exclude from the page in an array:
POST https://api.unzer.com/v1/linkpay/{authorize|charge}
Body:
{
...
"excludeTypes": ["paypal", "sepa-direct-debit"],
...
}
...
String[] excludeTypes = {"paypal", "sepa-direct-debit"};
linkpay.setExcludeTypes(excludeTypes);
...
For a list of all possible excludeTypes
array values, see Payment methods.
Step 3: Forward the customer to the Link Pay Page
After validating the data, the response containing a redirectUrl
key is created. Use the redirectUrl
to send the customer to the instance of your Link Pay, where they can finalize the payment.
If a redirect payment method is selected, the customer is redirected to the third party payment page, where the payment is finalized. After the customer finalizes the payment, they are redirected back to the returnUrl
that you have provided when you created or updated your Link Pay page.
After the redirect, fetch the payment resource using the GET method and handle the order depending on its status, that is redirect to success if it is successful or show a failure message if there was an error.
If any other payment method is selected, the customer is redirected to the returnUrl
that you passed.
In case you did not pass any value to returnUrl
, the user is redirect to the Unzer-hosted success page.
Customization
You can customize the following elements of the Link Pay Page:
- Images
- Colors
- UI text
Customize the images
You can define some of the images that appear on the Link Pay page. To do that, set the following properties when initializing the Link Pay page in Step 2:
fullPageImage
logoImage
Unlike the Hosted Pay Page, Link Pay cannot be customized by passing URL-encoded parameters (except for language). All customization for Link Pay is done by passing key-value pairs to the css
object in the request body.
For each customizable element, you can choose to change its backgroundColor
, fontColor
and fontSize
.
Basket image
If you want to set individual basket images on the Link Pay page, you can do so by specifying the image URL in the imageURL
property of each basketItems
entity.
Customize the header
To customize the header section, you can choose one of the following:
- Pass the style values to the options object as the second parameter of the checkout method (in Step 3).
- Pass a CSS key when initializing payment page on the server side (in Step 2).
For Link Pay, you can choose to pass values for shopDescription
, header
, shopName
, tagline
, helpUrl
, contactUrl
, orderId
, invoiceId
and backToMerchantLink
.
Pass a CSS object when initializing the Link Pay page
Another way to customize the header section is to pass a CSS object. This option is more flexible and lets you select individual elements. You can pass values for:
header
tagline
shopName
For each element, you can change:
backgroundColor
fontColor
fontSize
To use this option, add the CSS object when initializing payment page on the server side in Step 2:
POST https://api.unzer.com/v1/linkpay/{authorize|charge}
{
...
"css": {
"shopDescription": "color: blue; font-size: 30px",
"tagline": "color: yellow; font-size: 10px",
"header": "background-color: white",
"shopName": "color: white; font-size: 24px",
"contactUrl": "color: green; font-size: 10px",
"helpUrl": "background-color: black",
"invoiceId": "color: rgb(230, 185, 64)",
"orderId": "color: rgb(230, 185, 64)",
"backToMerchantLink": "color: rgb(230, 185, 64)"
},
...
}
...
Map<String, String> cssMap = new HashMap<String, String>();
cssMap.put("shopDescription", "color: blue; font-size: 30px");
cssMap.put("tagline", "color: yellow; font-size: 10px");
cssMap.put("header", "background-color: white");
cssMap.put("shopName", "color: white; font-size: 24px");
cssMap.put("contactUrl", "color: green; font-size: 10px");
cssMap.put("helpUrl", "background-color: black");
cssMap.put("invoiceId", "color: rgb(230, 185, 64)");
cssMap.put("orderId", "color: rgb(230, 185, 64)");
cssMap.put("backToMerchantLink", "color: rgb(230, 185, 64)");
linkpay.setCss(cssMap);
...
- When creating CSS that you send to the backend, use vanilla CSS with camel cased key names.
- If you send several values for an individual element, separate these values with a semicolon
;
. - We recommend testing the UI changes for all device sizes, especially when passing font-size values.
- When you pass styles for the same element through the checkout method and the CSS object, the latter takes precedence.
The CSS sent to the backend should look exactly the same as when writing vanilla CSS (except for the names of the keys, which follow camel case naming convention). If you choose to send more than one value for an individual element, you will have to separate the values with a colon
;
.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 reduce or cancel a reservation on the customer account 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 unzer = new Unzer("s-priv-xxxxxxxxxx");
Authorization authorization = unzer.fetchAuthorization('s-pay-1');
Cancel cancel = authorization.cancel();
POST https://api.unzer.com/v1/payments/s-pay-1/authorize/cancels
{
"amount" : "100.00"
}
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 unzer = new Unzer("s-priv-xxxxxxxxxx");
Cancel cancel = unzer.cancelCharge("s-pay-1", "s-chg-1");
{
"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": "",
"linkPayId": "",
"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.
To learn about payment management for specific payment methods, go to the relevant payment method page.
<h2 id="error-handling">Error handling</h2>
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.
<h2 id="test--go-live">Test & go live</h2>
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.