Embed the Checkout Snippet

This tutorial starts after the customer has selected their product(s) on your site, and wants to proceed to checkout.

In the steps below, you will be guided in how to render the Klarna Checkout HTML snippet on your checkout page. The Checkout snippet is where the customer enters their address details and completes their payment with one of the payment methods offered within the checkout.

Authentication

Klarna uses HTTP Basic Auth for authentication. Use the API credentials provided to you to authenticate with Klarna. The credentials consists of two elements:

  • Username: a username linked to your Merchant ID at Klarna
  • Password: a unique password that is associated with the username

Authentication: Base64(username:password)

Endpoints (URLs)

Klarna’s European and North American environments have different endpoints (URLs) for testing and for live purchases. All requests to Klarna go through HTTPS. Read more here.

Create a Checkout Order

1. Configure the Checkout Order

In order for Klarna to construct a checkout order, we require that you set some configurations which reflect your website endpoints. These are the items that you should configure:

  • Specify the merchant ID and API Credentials provided to you by Klarna.
  • Set the currency, language (locale) and country to be used.
  • Endpoints to be used by Klarna Checkout:
    • Terms: URL for your terms and conditions. Mandatory.
    • Checkout: URL to your checkout page. Mandatory.
    • Confirmation: URL to your confirmation page. This is where customers will be redirected after completing their purchase. Mandatory.
    • Push: URL to which Klarna will send an HTTP post request to confirm the order. Mandatory.
    • Order validation, Tax & Shipping changes and other order notifications. Learn more about Tax & Shipping click
    • (Only DE, AT) Cancellation: URL of merchant cancellation terms. Optional.
This section only applies to the regions:
Finland
If you are working with the **SmartPost** delivery option in Finland, then the Phone number entered in Klarna checkout needs to be used for sending the SmartPost SMS PIN. The SmartPost address shall be sent to Klarna as a “shipping option”

Find out more in the API reference on the Merchant Urls Object.

Note:

  • Use the locale and purchase country/currency to match the customer experience you want to render.
  • If a checkout session already exists, you should use the order from that session instead of creating a new one.

Optimize the Checkout for Returning Customers

When you render the checkout snippet you may choose to add data about the customer. We recommended this feature for customers who have already registered with your website and provided auxiliary data about themselves. If you choose to add customer data, a lot of the customer-defined fields on the checkout form will be pre-populated, which will increase your conversion. To find more about this feature visit the API Reference.

2. Create a Checkout Order

Once all configurations and cart items have been set, it’s time to create an order in Klarna’s system.

Create Checkout Order Request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
POST /checkout/v3/orders
Authorization: Basic pwhcueUff0MmwLShJiBE9JHA==
Content-Type: application/json
{
"purchase_country": "se",
"purchase_currency": "sek",
"locale": "en-GB",
"billing_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"order_amount": 503341,
"order_tax_amount": 100668,
"order_lines": [
  {
    "type": "physical",
    "reference": "19-402-SWE",
    "name": "Camera Travel Set",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 603341,
    "tax_rate": 2500,
    "total_amount": 503341,
    "total_discount_amount": 100000,
    "total_tax_amount": 100668,
    "image_url": "http://merchant.com/logo.png"
  }
],
"merchant_urls": {
  "terms": "http://merchant.com/tac.php",
  "checkout": "http://merchant.com/checkout.php?sid={checkout.order.id}",
  "confirmation": "http://merchant.com/thankyou.php?sid={checkout.order.id}",
  "push": "http://localhost/kco/push.php?checkout_uri={checkout.order.id}"
},
"shipping_options": [
  {
    "id": "free_shipping",
    "name": "Free Shipping",
    "description": "Delivers in 5-7 days",
    "price": 0,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": true,
    "shipping_method": "Home"
  },
  {
    "id": "pick_up_store",
    "name": "Pick up at closest store",
    "price": 399,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": false,
    "shipping_method": "PickUpStore"
  }
]
}

Note: The numeric values in the create checkout order request are 1/100-eds (e.g. 100 = 1.00 SEK and tax rate 2500 = 25.00%).

Create Checkout Order Response

The JSON response from the create checkout order call contains a unique order_id generated by Klarna which you need to keep track of since it is a reference to the order you created. The JSON response payload also contains the HTML snippet that you need to include on your page to render the checkout.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{
"order_id": "1203c28c-f101-765f-bed8-f57a2d5e83e0",
"status": "checkout_incomplete",
"purchase_country": "se",
"purchase_currency": "sek",
"locale": "en-GB",
"billing_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"customer": {},
"shipping_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"order_amount": 503341,
"order_tax_amount": 100668,
"order_lines": [
  {
    "type": "physical",
    "reference": "19-402-SWE",
    "name": "Camera Travel Set",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 603341,
    "tax_rate": 2500,
    "total_amount": 503341,
    "total_discount_amount": 100000,
    "total_tax_amount": 100668,
    "image_url": "http://merchant.com/logo.png"
  }
],
"merchant_urls": {
  "terms": "http://merchant.com/tac.php",
  "checkout": "http://merchant.com/checkout.php?sid={checkout.order.id}",
  "confirmation": "http://merchant.com/thankyou.php?sid={checkout.order.id}",
  "push": "http://localhost/kco/push.php?checkout_uri={checkout.order.id}"
},
"html_snippet": "<div id=\"klarna-checkout-container\".................",
"started_at": "2018-01-24T14:21:55Z",
"last_modified_at": "2018-01-24T14:21:55Z",
"options": {
  "allow_separate_shipping_address": false,
  "date_of_birth_mandatory": false,
  "require_validate_callback_success": false
},
"external_payment_methods": [],
"external_checkouts": [],
"shipping_options": [
  {
    "id": "free_shipping",
    "name": "Free Shipping",
    "description": "Delivers in 5-7 days",
    "price": 0,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": true,
    "shipping_method": "Home"
  },
  {
    "id": "pick_up_store",
    "name": "Pick up at closest store",
    "price": 399,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": false,
    "shipping_method": "PickUpStore"
  }
],
"selected_shipping_option": {
  "id": "free_shipping",
  "name": "Free Shipping",
  "description": "Delivers in 5-7 days",
  "price": 0,
  "tax_amount": 0,
  "tax_rate": 0,
  "preselected": true,
  "shipping_method": "Home"
}
}

3. Render the Snippet in Your Checkout Page

It’s now time to render the checkout snippet.

Get the value of the html_snippet from the create checkout order call response and embed it into your page where you would like the Klarna Checkout to be rendered. You can either:

  • Embed the HTML snippet in your page served by your backend from an endpoint
1
2
String htmlSnippet = "<div id=\"klarna-checkout-container\"...";
System.out.println(String.format("<div>%s</div>", htmlSnippet));
  • Get the snippet via an ajax call from you server and inject it dynamically, using javascript, into your page. In this case, we should be sure that the script tag(s) are parsed and evaluated, which means inserting the snippet. Using innerHTML is not going to work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
getSnippet(function (htmlSnippet) {
  var checkoutContainer = document.getElementById('my-checkout-container')
  checkoutContainer.innerHTML = htmlSnippet
  var scriptsTags = checkoutContainer.getElementsByTagName('script')
  // This is necessary otherwise the scripts tags are not going to be evaluated
  for (var i = 0; i < scriptsTags.length; i++) {
      var parentNode = scriptsTags[i].parentNode
      var newScriptTag = document.createElement('script')
      newScriptTag.type = 'text/javascript'
      newScriptTag.text = scriptsTags[i].text
      parentNode.removeChild(scriptsTags[i])
      parentNode.appendChild(newScriptTag)
  }
})

Note: The most straightforward approach for rendering the checkout page is to include the snippet via server side.

This is what it should look like:

Example Image. This can be different dependent on the region you are in.

Handling an Existing Order

You should keep track of the Klarna order_id associated with the current customer to avoid creating a new order every time the customer loads the checkout page. This will allow the customer to reload the checkout page without having to re-enter any information they have already provided.

When the customer loads the checkout page and have a Klarna order_id associated with their session you should fetch the order from Klarna. If the order contents have changed you should make an update to the order.

1. Retrieve the Order

Use the checkout order_id to fetch the order from Klarna.

Retrieve Checkout Order Request

1
2
3
GET /checkout/v3/orders/order_id
Authorization: Basic pwhcueUff0MmwLShJiBE9JHA==
Content-Type: application/json

Retrieve Checkout Order Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{
"order_id": "1203c28c-f101-765f-bed8-f57a2d5e83e0",
"status": "checkout_incomplete",
"purchase_country": "se",
"purchase_currency": "sek",
"locale": "en-GB",
"billing_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"customer": {},
"shipping_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"order_amount": 503341,
"order_tax_amount": 100668,
"order_lines": [
  {
    "type": "physical",
    "reference": "19-402-SWE",
    "name": "Camera Travel Set",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 603341,
    "tax_rate": 2500,
    "total_amount": 503341,
    "total_discount_amount": 100000,
    "total_tax_amount": 100668,
    "image_url": "http://merchant.com/logo.png"
  }
],
"merchant_urls": {
  "terms": "http://merchant.com/tac.php",
  "checkout": "http://merchant.com/checkout.php?sid={checkout.order.id}",
  "confirmation": "http://merchant.com/thankyou.php?sid={checkout.order.id}",
  "push": "http://localhost/kco/push.php?checkout_uri={checkout.order.id}"
},
"html_snippet": "<div id=\"klarna-checkout-container\"...................",
"started_at": "2018-01-24T14:21:55Z",
"last_modified_at": "2018-01-24T14:21:55Z",
"options": {
  "allow_separate_shipping_address": false,
  "date_of_birth_mandatory": false,
  "require_validate_callback_success": false
},
"external_payment_methods": [],
"external_checkouts": [],
"shipping_options": [
  {
    "id": "free_shipping",
    "name": "Free Shipping",
    "description": "Delivers in 5-7 days",
    "price": 0,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": true,
    "shipping_method": "Home"
  },
  {
    "id": "pick_up_store",
    "name": "Pick up at closest store",
    "price": 399,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": false,
    "shipping_method": "PickUpStore"
  }
],
"selected_shipping_option": {
  "id": "free_shipping",
  "name": "Free Shipping",
  "description": "Delivers in 5-7 days",
  "price": 0,
  "tax_amount": 0,
  "tax_rate": 0,
  "preselected": true,
  "shipping_method": "Home"
}
}

2. Update the Checkout Order

You should update the checkout order to reflect the changes that the customer has made to the cart. The request below will update the order with adding another item to the card.

Updating Order Request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
POST /checkout/v3/orders/order_id
Authorization: Basic pwhcueUff0MmwLShJiBE9JHA==
Content-Type: application/json
{
"order_amount": 756682,
"order_tax_amount": 151336,
"order_lines": [
  {
    "type": "physical",
    "reference": "19-402-SWE",
    "name": "Camera Travel Set",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 603341,
    "tax_rate": 2500,
    "total_amount": 503341,
    "total_discount_amount": 100000,
    "total_tax_amount": 100668,
    "image_url": "http://merchant.com/logo.png"
  },
  {
    "type": "physical",
    "reference": "19-403-SWE",
    "name": "MP3 Player with Audio",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 303341,
    "tax_rate": 2500,
    "total_amount": 253341,
    "total_discount_amount": 50000,
    "total_tax_amount": 50668,
    "image_url": "http://merchant.com/logo.png"
  }
]
}

Updating Order Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
{
"order_id": "1203c28c-f101-765f-bed8-f57a2d5e83e0",
"status": "checkout_incomplete",
"purchase_country": "se",
"purchase_currency": "sek",
"locale": "en-GB",
"billing_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"customer": {},
"shipping_address": {
  "given_name": "Testperson-se",
  "family_name": "Approved",
  "email": "youremail@email.com",
  "street_address": "Stårgatan 1",
  "postal_code": "12345",
  "city": "Ankeborg",
  "phone": "+46765260000",
  "country": "se"
},
"order_amount": 756682,
"order_tax_amount": 151336,
"order_lines": [
  {
    "type": "physical",
    "reference": "19-402-SWE",
    "name": "Camera Travel Set",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 603341,
    "tax_rate": 2500,
    "total_amount": 503341,
    "total_discount_amount": 100000,
    "total_tax_amount": 100668,
    "image_url": "http://merchant.com/logo.png"
  },
  {
    "type": "physical",
    "reference": "19-403-SWE",
    "name": "MP3 Player with Audio",
    "quantity": 1,
    "quantity_unit": "pcs",
    "unit_price": 303341,
    "tax_rate": 2500,
    "total_amount": 253341,
    "total_discount_amount": 50000,
    "total_tax_amount": 50668,
    "image_url": "http://merchant.com/logo.png"
  }
],
"merchant_urls": {
  "terms": "http://merchant.com/tac.php",
  "checkout": "http://merchant.com/checkout.php?sid={checkout.order.id}",
  "confirmation": "http://merchant.com/thankyou.php?sid={checkout.order.id}",
  "push": "http://localhost/kco/push.php?checkout_uri={checkout.order.id}"
},
"html_snippet": "<div id=\"klarna-checkout-container\"................",
"started_at": "2018-01-24T14:21:55Z",
"last_modified_at": "2018-01-24T15:03:10Z",
"options": {
  "allow_separate_shipping_address": false,
  "date_of_birth_mandatory": false,
  "require_validate_callback_success": false
},
"external_payment_methods": [],
"external_checkouts": [],
"shipping_options": [
  {
    "id": "free_shipping",
    "name": "Free Shipping",
    "description": "Delivers in 5-7 days",
    "price": 0,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": true,
    "shipping_method": "Home"
  },
  {
    "id": "pick_up_store",
    "name": "Pick up at closest store",
    "price": 399,
    "tax_amount": 0,
    "tax_rate": 0,
    "preselected": false,
    "shipping_method": "PickUpStore"
  }
],
"selected_shipping_option": {
  "id": "free_shipping",
  "name": "Free Shipping",
  "description": "Delivers in 5-7 days",
  "price": 0,
  "tax_amount": 0,
  "tax_rate": 0,
  "preselected": true,
  "shipping_method": "Home"
}
}

Note: Find out more about the different fields in the cart items list in the API Reference.

Update an Ongoing Checkout Order

If you want to update an order while the customer is on the checkout page, you will need to suspend the checkout, update the order, and then resume the checkout to make sure the information shown in the checkout is up to date.

The flow is visualized in the chart below:

1. Suspend the Checkout

Suspending the checkout puts it in a waiting state, preventing customer input. A loading icon is rendered on top of the iframe indicating to the customer that the checkout is loading.

You can do this by issuing a Javascript command, as per the code example below:

1
2
3
window._klarnaCheckout(function (api) {
    api.suspend();
});

2. Update the Order

Update the order as you did in the example above.

3. Resume the Checkout

Resuming the checkout forces it to fetch the most recent order data from Klarna. The loading indicator will disappear, the form will become enabled. The amount presented in the checkout will now reflect the new order total.

1
2
3
window._klarnaCheckout(function (api) {
    api.resume();
});

Extra merchant data

Providing Klarna with extra merchant data

In some cases, Klarna requires additional information regarding the customer and the purchase in order to make a correct risk assessment. In this tutorial you will learn what information Klarna requires, and how you can send it to Klarna.

Use cases

  • Airline Tickets - when creating an order to sell an airline ticket, information about the passenger and itinerary to be booked should be provided to Klarna.
  • Event sales merchant - when creating an order for selling a ticket to an event, information about the event should be provided to Klarna.
  • Recurring orders - when creating an order for subscriptions or recurring payments, subscription and customer account information should be provided to Klarna.

1. Create the extra merchant data

Add the relevant data, based on the specification and your product vertical. To know which product vertical is right for you, please contact your integration sales representative.

The example below relates to recurring orders, which requires the subscription and customer_account_info details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
final List<Subscription> subscription = new ArrayList<Subscription>() {
    {
        add(new Subscription()
                .setSubscriptionName("One year monthly recurring payments")
                .setStartTime(DateTime.now())
                .setEndTime(DateTime.now().plusMonths(12))
                .setAutoRenewalOfSubscription(false));
    }
};

final List<CustomerAccountInformation> customerInfo = new ArrayList<CustomerAccountInformation>() {
    {
        add(new CustomerAccountInformation()
                .setUniqueAccountIdentifier("user@example.com")
                .setAccountRegistrationDate(DateTime.now())
                .setAccountLastModified(DateTime.now()));
    }
};

final ExtraMerchantDataBody extraMerchantDataBody = new ExtraMerchantDataBody() {
    {
        setSubscription(subscription);
        setCustomerAccountInfo(customerInfo);
    }
};

final ExtraMerchantData extraMerchantData = new ExtraMerchantData() {
    {
        setBody(extraMerchantDataBody);
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
List<Subscription> subscription = new List<Subscription>
{
    new Subscription
    {
        SubscriptionName = "One year monthly recurring payments",
        StartTime = DateTime.Now,
        EndTime = DateTime.Now.AddMonths(12),
        AutoRenewalOfSubscription  = False
    }
};

List<CustomerAccountInformation> customerInfo = new List<CustomerAccountInformation>
{
    new CustomerAccountInformation
    {
        UniqueAccountIdentifier = "user@example",
        AccountRegistrationDate = DateTime.Now,
        AccountLastModified = DateTime.Now
    }
};

ExtraMerchantData extraMerchantData = new ExtraMerchantData
{
    Body = new ExtraMerchantDataBody
    {
        Subscription = subscription,
        CustomerAccountInfo = customerInfo
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const EMD_FORMAT = 'Y-m-d\TH:m:s\Z';

$emd = [
    "subscription" => [
        [
            "subscription_name" => "Test Testperson",
            "start_time" => (new DateTime())->format(EMD_FORMAT),
            "end_time" => (new DateTime())->modify('+12 months')->format(EMD_FORMAT),
            "auto_renewal_of_subscription" => false
        ]
    ],
    "customer_account_info" => [
        [
            "unique_account_identifier" => "user@example.com",
            "account_registration_date" => (new DateTime())->format(EMD_FORMAT),
            "account_last_modified" => (new DateTime())->format(EMD_FORMAT)
        ]
    ]
];

2. Attach the data to the order

Once the data is created, you would need to include it under the attachment property. Once it is populated simply send the data as you learned in the Embed the checkout tutorial.

1
orderData.setAttachment(extraMerchantData.toAttachment());
1
orderData.Attachment = extraMerchantData;
1
2
3
4
$orderData['attachment'] = [
    "content_type" => "application/vnd.klarna.internal.emd-v2+json",
    "body" => json_encode($emd)
];

Note: Find out more about the different data fields by checking the attachments specification.

Validating the Order Before it is Completed

For a number of different reasons there could be a need to validate the order before it is completed. You can register a callback on the order create (where you can do the final merchant validation) that Klarna will call when the customer clicks the buy button. Find out more in the Order validation API.

Use Cases

Validate a checkout order

This checkout function will allow you to validate the information provided by the consumer in the Klarna Checkout iframe before the purchase is completed.

Use cases

  • Out of stock validation - for high turnaround businesses this functionality enables you to verify that an item added to a cart is indeed still in stock before the consumer completes the purchase.
  • Delivery limitations - some products cannot be shipped to certain geographies. This functionality enables you to verify that the products can be shipped to the address the consumer has provided.
  • Order number generation - certain systems have flows that require the creation of an internal order ID when order has been created, such as for tracking purposes. This functionality allows you to create an order ID upon receiving the validation callback and displaying it on the confirmation page.

1. Create a checkout order

Create a Checkout order exactly as you learned in the render the checkout snippet tutorial, and make sure to include the optional property merchant_urls.validation.

Note: All communication with the validation URI will be encrypted. For that reason you must use the HTTPS protocol for this URI.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Accept: application/json
Authorization: Basic a2xhcm5hOnVuaWNvcm5z
Content-Type: application/json

{
  "purchase_country": "gb",
  "purchase_currency": "gbp",
  "locale": "en-gb",
  "order_amount": 10000,
  "order_tax_amount": 2000,
  "order_lines": [
    {
      "type": "physical",
      "reference": "123050",
      "name": "Tomatoes",
      "quantity": 10,
      "quantity_unit": "kg",
      "unit_price": 600,
      "tax_rate": 2500,
      "total_amount": 6000,
      "total_tax_amount": 1200
    }, 
    {
      "type": "physical",
      "reference": "543670",
      "name": "Bananas",
      "quantity": 1,
      "quantity_unit": "bag",
      "unit_price": 5000,
      "tax_rate": 2500,
      "total_amount": 4000,
      "total_discount_amount": 1000,
      "total_tax_amount": 800
    }
  ],
  "merchant_urls": {
    "terms": "http://toc",
    "checkout": "http://checkout?klarna_order_id={checkout.order.id}",
    "confirmation": "http://confirmation?klarna_order_id={checkout.order.id}",
    "push": "http://push?klarna_order_id={checkout.order.id}",
    "validation": "http://validation?klarna_order_id={checkout.order.id}"
  }
}

2. Respond to Klarna’s POST request

When the consumer clicks “buy now” a POST request will be sent to the merchant_urls.validation. The body of the request will contain the current order information. The structure of the order information is identical to the result of fetching the order, as you saw in render the checkout.

Note: There is no need to fetch the order from Klarna since all the order information is included in the POST request body.

Once you receive the POST request, our system will expect a response within 3 seconds. If Klarna does not receive a response, we will approve the purchase. The response you provide Klarna will determine whether or not the purchase will be completed:

  • To approve the purchase, reply with a HTTP status 200 OK. The consumer will then be redirected as normal to the checkout confirmation page.
  • To deny the purchase, reply with a HTTP status 303 See Other. This needs to include a Location header pointing to a page which informs the consumer why the purchase was not completed. The consumer will be redirected to this page.

Note: The rejection page needs to be hosted by you, and we highly recommend that you give the consumer detailed information as to why you rejected the order.

This section only applies to the regions:
Norway

To be compliant, you have a contractual obligation to have an agreement between you and the external payment method providers (e.g. Vipps and Paypal).

Reconciliation of Vipps transactions

To simplify your bookkeeping, Klarna wants to provide a complete reporting offering.

However, as Vipps has a slightly different setup compared to our other available payment methods you will need to do some changes in your reconciliation process.

What separates Swish from our other payment method is that the money from a Vipps transaction will be paid out immediately and separately compared to Klarna’s aggregated payout.

New variables

Reconciliation of Vipps transactions will require new variables to be included in your settlement reports.

Settled by:

Klarna - Paid out by Klarna

Vipps as an External Payment Method - Paid out by Vipps

External reference

The reference that will appear on your bank account, set and controlled by Vipps.

Klarna reference

A reference number that Klarna sets and controls. This may may or may not appear on your bank account depending on which bank you are using.

New transaction types

Reconciliation of Vipps transactions will require new transaction types to be included in your settlement reports.

External payout capture

Represents the transfer of money from consumer to merchant through Vipps scheme upon purchase completion in the checkout

External payout refund

Represents the transfer of money from merchant to consumer through Vipps scheme upon return/chargeback/refund

External payout retransfer

In the case where a consumer switches payment method after the order has been activated, External payout retransfer represents the shift of responsibility for the payout from Klarna to Vipps. This transaction type will deduct money from the payout from Klarna, as money has already been transferred through the Vipps schemes.

External payout reactivation

Since capture is only concerning money transfer, and External payout retransfer fully undoes the previous activation; External payout reactivation represents the activation (shipment) of the good whereas External payout capture only represents the transfer of funds.

Important - invoice number info

Please be advised that for transactions where Vipps was selected as a payment method, Klarna can not guarantee that this transaction has an invoice number. As invoice numbers are created upon activation, some transactions that haven’t been activated yet will be included in the settlement report.

Best practice

We recommend matching the non-Vipps transactions in the same way as you currently do it.

For Vipps transactions, you can link the external reference to the order ID set by you in your ERP. You can use the invoice number in the cases you have that in the settlement report, but to keep things consistent Klarna recommends you to reconcile based on your order ID. When reconciling your bank statement, simply identify the paid orders using the external reference and reconcile these in your system.

This section only applies to the regions:
Sweden, Norway, Finland

Business to Business

Sometime an order is placed on behalf of an organization, not an individual. We refer to this as the Business to Business flow, or B2B flow, for Klarna Checkout. The B2B flow comes with some differences in the user experience and integration compared to the Business to Consumer flow (B2C).

Klarna Checkout can be configured to support B2B in Sweden, Norway and Finland.

Prerequisities

  • You have implemented Klarna Checkout
  • Your e-store ID has been enabled for B2B by Klarna (available in Sweden, Norway and Finland)

How it works

From an implementation point of view, B2B for Klarna Checkout is utilizing the same logic and API as the regular Klarna Checkout for B2C (Business to Consumer). This means you will re-use your existing Klarna Checkout integration and just make the changes described in the Implementation flow below.

When enabling support for B2B you introduce a new user flow, meaning there will visually be one option for business customers and a separate option for a regular consumer in the Klarna Checkout. The B2C flow is loaded as default, but you can optionally render the B2B flow by default to a known business customer.

  • The customer can toggle between the B2C and B2B flows in the checkout.
  • The B2B flow asks for details pertaining to an organization, such as Organization number.
  • It is possible to configure the checkout for separate shipping and billing address in the B2B flow.
  • The available payment methods in the B2B flow are Invoice and Card payments.
  • Recurring orders are supported in the B2B flow.
  • It is possible to use a separate link for the terms presented in the B2B flow, which you pass along when creating the order. If such a link is not provided, the B2C terms will be presented by default.

The B2B flow for Klarna Checkout will be configured by Klarna on the same e-store ID as the regular B2C Klarna Checkout.

Implementation flow

Follow these steps to enable the B2B flow in your existing Klarna checkout integration.

Step 1 - Configure the checkout

Before loading the checkout, you will set the relevant options to indicate that B2B should be included.

1a. Enable the option to choose between the B2C or B2B flows

When configuring the checkout order, set the options for <span>allowed_customer_types</span> to both person and organization.

“options”: { “allowed_customer_types”: [“person”, “organization"] }

1b. (Optional) - If desired, render the B2B flow instead of B2C

By default, the regular B2C user flow will be rendered when the checkout loads. If you instead want to render the B2B flow when it loads, you can optionally set the <span>customer.type</span>field to organization.

“customer”: { “type”: “organization” }

1c. (Optional) - Prefill the organization number

If you have the organization number available for this business, you can optionally prefill it in the checkout by setting it in the <span>organization_registration_id</span> field. That way the customer will not have to enter them again in the checkout, but still has the option to change it if it is incorrect.

“customer”: { “type”: “organization”, “organization_registration_id”: “556036-0793” }

1d. (Optional) - Set specific T&Cs to be presented in the B2B flow

In order for a merchant to display their b2b and b2c terms differently it is possible to have a separate links. The terms are displayed in the same place as the b2c terms. In addition to the existing field that can be used for adding legal terms for B2C (merchant.terms_uri), a separate field called merchant.organization_terms_uri is also available. If set, the terms from that field will be presented when the customer is in the b2b flow. If not set then the terms from merchant_uri will be used.

“merchant.organization_terms_uri”: { “your URI string” }

Step 2 - Load the checkout

Create the order and render the checkout as usual. The customer should now be able to switch between the B2C and the B2B flows.

Step 3 (Optional) - Listen to customer interaction events from the checkout

The customer starts entering the required fields in the B2B flow. The additional fields will be the organization id and an optional “Reference” field where they may for example add their name or department.

If you need to know which flow the customer is in before the order is placed, in order to for example always show the correct shipping options on your page, you may do so using our JavaScript API.

Start by subscribing to the load signal.

_klarnaCheckout(function(api){ api.on({ load: function(data){ console.info(data) } }) }) You will now be notified about customer data including the flow type and partial shipping address before the order is placed. When the customer switches the flow, the checkout reloads and callback is triggered again.

Here is a sample of the notification from the callback

{ “customer”: { “type”: “person” }, “shipping_address”: { “country”: “SE”, “email”: "klara.joyce@klarna.com", “postal_code”: “12345” } } In order to listen shipping address change events before the order is placed, the relevant shipping_address_change signal must be used in the same way.

Step 4 - Parse the organization’s address details from the completed order

The B2B customer places the order when they press the buy button. When you retrieve the completed order placed in the B2B flow, the customer object contains a type which identifies if this was an organization or a consumer (person).

“customer”: { “type”: “organization”, // optionally, this could be set to “person” “organization_registration_id”: “556036-0793” }, If the customer.type is organization, the <span>billing address</span> includes potentially two additional fields called <span>organization_name</span> and reference. Note that empty fields are not returned, so if the reference was not entered by the customer, it will not be available in the response.

“billing_address”: { “country”: “{{<country}}”, “given_name”: “{{<given_name}}”, “family_name”: “{{<family_name}}”, “organization_name”: “{{<organization_name}}”, “street_address”: “{{<street_address}}”, “city”: “{{<city}}”, “phone”: “{{<phone}}”, “reference”: “{{<reference}}” }, This was the final step.

Please note: You need to contact Klarna to enable B2B for any applicable e-store ID before going live.

This section only applies to the regions:
Sweden

Sum Orders

This occurs when a customer has entered a voucher / discount code that results in the cart total amounting to zero. Visually, the user will see no payment methods, but be able to have an activated Buy Button to complete the purchase directly. The confirmation page will display confirming that their purchase with a 0 sum order is successful. Note: A user cannot select a payment method at this stage, so no card payments will be applicable.

Reconciliation of Swish transactions

To simplify your bookkeeping, Klarna wants to provide a complete reporting offering.

However, as Swish has a slightly different setup compared to our other available payment methods you will need to do some changes in your reconciliation process.

What separates Swish from our other payment method is that the money from a Swish transaction will be paid out immediately and separately compared to Klarna’s aggregated payout.

New variables

Reconciliation of Swish transactions will require new variables to be included in your settlement reports.

Settled by:

Klarna - Paid out by Klarna

Swish as an External Payment Method - Paid out by Swish

External reference

The reference that will appear on your bank account, set and controlled by Swish.

Klarna reference

A reference number that Klarna sets and controls. This may may or may not appear on your bank account depending on which bank you are using.

New transaction types

Reconciliation of Swish transactions will require new transaction types to be included in your settlement reports.

External payout capture

Represents the transfer of money from consumer to merchant through Swish scheme upon purchase completion in the checkout

External payout refund

Represents the transfer of money from merchant to consumer through Swish scheme upon return/chargeback/refund

External payout retransfer

In the case where a consumer switches payment method after the order has been activated, External payout retransfer represents the shift of responsibility for the payout from Klarna to Swish. This transaction type will deduct money from the payout from Klarna, as money has already been transferred through the Swish schemes.

External payout reactivation

Since capture is only concerning money transfer, and External payout retransfer fully undoes the previous activation; External payout reactivation represents the activation (shipment) of the good whereas External payout capture only represents the transfer of funds.

Important - invoice number info

Please be advised that for transactions where Swish was selected as a payment method, Klarna can not guarantee that this transaction has an invoice number. As invoice numbers are created upon activation, some transactions that haven’t been activated yet will be included in the settlement report.

Best practice

We recommend matching the non-Swish transactions in the same way as you currently do it.

For Swish transactions, you can link the external reference to the order ID set by you in your ERP. You can use the invoice number in the cases you have that in the settlement report, but to keep things consistent Klarna recommends you to reconcile based on your order ID. When reconciling your bank statement, simply identify the paid orders using the external reference and reconcile these in your system.

What’s next?

You have integrated Klarna Checkout into your checkout page.

The next step is to render the confirmation snippet.