Confirm the Purchase

In this tutorial you will learn how to confirm that you have received and created an order in your system. This confirmation is needed in response to a push notification from Klarna, indicating that the customer has completed a purchase.

Use Case

A customer has completed a purchase and you want to create the associated order in your system.

Prerequisites

A customer has completed a purchase with Klarna Checkout.

1. Handle the POST Request

Once a customer has completed a purchase, Klarna will notify you by sending a POST request. The POST request will be sent to the push notification URL that you provided when you created the checkout order.

Note: There is approximately a 2 minute delay before the order-confirmation push to the merchants is attempted.

For instance with these merchant urls:

1
2
3
4
5
6
"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://merchant.com/kco/push.php?checkout_uri={checkout.order.id}"
}

You would receive a POST request to the URL with the placeholder {checkout.order.id} replaced with the correct order_id and an empty body.

For example: http://merchant.com/kco/push.php?checkout_uri=12345

2. Request the Order from Klarna

You should now use the order id found in the query parameter checkout_uri to fetch the order from the Order Management API.

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

3. Backup Order Creation

The confirmation page might fail to load for a number of reasons, even though the purchase is confirmed by Klarna. However, once you receive a POST request at the push confirmation endpoint, you can be assured that the purchase was successful and you should make sure that you have created the order and create if it doesn’t exist. The full resource structure of an order can be found in the API Reference.

4. Acknowledge the Order

You should now send a request to Klarna saying that you’ve acknowledged the order. Note: Klarna will send the push notifications every two hours for a total of 48 hours or until you confirm that you have received the order. After 48 hours we will stop sending notifications, but the order is still open and can be captured or updated as normal.

1
2
3
POST /ordermanagement/v1/orders/order_id/acknowledge
Authorization: Basic pwhcueUff0MmwLShJiBE9JHA==
Content-Type: application/json

Order Creation and the Order Confirmation Push

  1. There should be an attempt to acknowledge the order on the confirmation page.
  2. The order confirmation push should be implemented as a backup.
  3. If the order doesn’t exist when the push is received the order should be created. If there is no intention to ship the order, it should be canceled.
  4. Every order should either be acknowledged or canceled. Orders which will not be shipped should be canceled immediately.

Ship and Capture the Order to Finalize the Payment

At this point, the order has been confirmed and you can proceed with the next steps. Once you have shipped the product, you need to capture the order in order to finalize the payment. The order can be found at Klarna’s Merchant Portal or you can integrate with our Order Management platform using the APIs provided.

Best practices

Handling the Iframe

  • The Checkout iFrame lives inside the container #klarna-checkout-container.
  • The container is created by the JS snippet retrieved in the order body.
  • The container mustn’t be styled. If the Checkout iFrame should have a restricted width, apply that rule to an element wrapping the container.
  • The width of the Checkout iFrame should at minimum be 320px.
  • The Checkout iFrame must be able to grow and shrink height-wise as the user progresses in the checkout flow.
  • Styling of elements inside the container is being taken care of by the Checkout iFrame. Make sure no merchant CSS is applied to the elements.
  • There can be hidden elements inside the container. The elements mustn’t be styled, since the Checkout iFrame is responsible for showing and hiding them.

Go to checkout

The customer has completed shopping and clicked the ‘Checkout’ button.

  • Once the customer has completed shopping and the checkout page is rendered for the first time, a session variable should be used to store the Klarna Order Location URI returned from the initial POST creating the order.
  • NOTE: This is NOT the snippet, it is the URL for the order

The reason this should be retained is that when a customer starts filling out their details they will not have to re-enter them if they leave and come back to the checkout.

Create checkout session

The user may have already hit this page, then clicked the back button or a link to return to the shopping pages to modify their cart.

  • Check if the Klarna Order Location session variable is assigned before creating a new order.
  • I.e: https://api-na.playground.klarna.com/checkout/v3/orders/[KlarnaOrderId] or in EU, use the EU playgrund site https://api-eu.playground.klarna.com/checkout/v3/orders/[KlarnaOrderId]
  • If it exists perform a GET request using this Location.
  • A JSON object containing the current Klarna order is returned which can be updated instead of creating a new order.
  • Deserialize this to a CheckoutOrder object to simplify working with the order.
  • This also includes the snippet that is used to render the checkout.
  • If you get a 4XX or 5XX or any other type of error, a new checkout should be created.
  • Klarna checkout orders are only valid for 48 hours and expire after that. This expiration is normal.
  • Checkout orders could also expire early for other internal system issues, so error handling must also be implemented in this step to create a new Checkout Order if the URI is invalid.
  • If a new order:
  • Assign the merchant_url’s collection to be used for callbacks.
  • Assign the locale properties (Country, Currency, Locale).
  • Assign the order_line object properties for the cart items.
    • The cart items are assigned a ‘type’ = ‘physical’. Other types included are:
      • sales_tax - generally added when the address_update url is called
      • discount - entered as a negative value to be subtracted from the order total
      • store_credit - entered as a negative value to be subtracted from the order total
      • shipping_fee - used when a shipping fee is added to the order
      • gift_card - this is when they purchase a gift card
      • digital - this is when they purchase something intangible like a license
      • surcharge - used for additional fees
  • Since sales tax is calculated based on the shipping address, it may not be computed at this time. However, a line item for sales_tax could be loaded for the order with a default tax, or assign 0.
  • Assign the checkout options object properties to customize the Klarna snippet. Any not sent will default to False
    • AllowSeparateShippingAddress
    • ColorButton
    • ColorButtonText
    • ColorCheckbox
    • ColorCheckboxCheckmark
    • ColorHeader
    • ColorLink
    • DateOfBirthMandatory
    • ShippingDetails
  • Assign the optional Shipping option properties and add them to the shipping_options collection. If these are not supplied here, they should be supplied after the shipping address is updated. If these are dependent on shipping address, do not add them now.
  • Create the Order Resource object and assign the properties.
  • Convert the order object to a JSON string
    • NOTE - if the customer has logged into the site prior to checking out and their customer information is known (name, email, billing and shipping address, …), these should be populated with the initial order creation. The merchant should not implement strict schema checking.
  • Perform a POST request to Create the order
    • The Url should be to (playground). Remove ‘playground’ to POST to production
    • The request properties are
      • AllowAutoRedirect = false
      • Method = ‘POST’
      • ContentLength = The length of the request JSON body of the order
      • Header
        • User-Agent
          • Library/XXX
          • OS/XXX
          • Language/XXX
          • Webserver/XXX
        • Content-Type = application/json
        • Credentials
          • UserId = MerchantId
          • Password = SharedSecret
    • The response properties are
      • Headers - The main one here is the location url of the order. Save this to the Klarna Order Location session variable.
      • Payload - Returns the order as JSON.
      • Status - Returns a status code of 2XX if successful.
    • Deserialize the JSON to obtain the HTML Snippet and display in the <div> tag.
  • If an existing order:
  • GET (Fetch) the order using the order location uri from the saved session variable.
  • Add/Update the cart items collection.
    • All cart items should be resent. This assures that any items removed are excluded from the checkout if initially sent.
  • Update the order amounts (tax and total).
  • Perform a POST request to update the cart items and properties.
    • You should get a 2XX status code with the response.
    • The response body contains the updated order in Klarna including the new snippet.
  • The location stored in the session variable should not change.
  • Show the html snippet returned from the POST.
  • Status will be ‘checkout_incomplete’ in KCO (Klarna Checkout).

Checkout snippet

The response from the prior GET or POST returned the checkout order data. This includes an HtmlSnippet containing a ‘<div>’ tag with HTML Markup to be displayed on the checkout page.

  • Parse the Checkout Order Data for the html snippet and assign this to the checkout web page.

Render checkout

The checkout page contains:

  • Merchants order summary panel showing summary of items purchased, cost, quantity, tax, order total, optional discounts and shipping options. This panel can be shown above or beside the Klarna panel.
  • Klarna panel (html_snippet div tag)
  • For a newly created order the html snippet will contain the labels: * email address * zip code * ‘Continue’ button
  • For existing orders the snippet will be pre-filled and contain: * The billing address if the email address and zip existed in Klarna or the information was sent with the initial order creation. These should be prefilled. * Labels to enter the billing and shipping addresses if the email address and zip did not exist in Klarna * Summary link to display the total order amount, tax, options, etc.

Modify Merchant Cart Panel from checkout page - optional

With the checkout page rendered, the user may change shipping options, enter promo codes, or remove line items or update item quantity from the merchant panel. Anytime this occurs, the Klarna panel will not reflect these changes and will need to be refreshed. This is done by suspending and resuming the checkout process.

Suspend and Resume

Used while the checkout page is rendered and the user modifies the cart within the merchant order summary panel.

  • Suspend the checkout process using the JavaScript API to the checkout.
  • This “locks” the Klarna checkout so the user may not interact with it.
  • Server side
  • Update the merchant’s cart.
  • Perform a POST to Klarna to update the order. See ‘If an existing order‘ above.
  • DO NOT create a new order at Klarna.
  • Resume the checkout process using the Klarna JavaScript API to the checkout.
  • This causes KCO to refresh with the data that was just updated via the server side POST.

Address updated

Server Side - must be completed within 10 seconds Once the address is supplied in the KCO, Klarna will default the shipping address to this address. Anytime the address changes the tax or shipping may need to be recomputed by the merchant.

  • A callback from Klarna to the merchant is made to the ‘address_update’ URL defined within the merchant_url’s for the order.
  • This address MUST be an SSL address (https://).
  • Although a self-signed certificate will work here, it would be best to obtain a real certificate since this is required for the final PUSH.
  • The POST from Klarna sends the checkout order as JSON with the billing and shipping address info now supplied. The body also contains the order_lines, order_amount and order_tax_amount.
  • The merchant should:
  • Deserialize the JSON and parse out the addresses.
  • Re-compute sales tax.
  • Parse out the sales_tax line and update or add it if not already part of the order_lines.
  • Update the order internally.
  • Determine the shipping cost.
  • Update the shipping cost line item.

Note that Klarna name and address lengths are in accordance with AVS industry standards and may extend beyond your character limit. Please be advised that this may require you to split the address or name. See below at end of document.

Available shipping options and updated cart

  • Now that the shipping address is known, the shipping options may be added to the order if not already supplied.
  • If discount codes are dependent on address, or are not already added to the order, these may be supplied.
  • Optionally, add or update the shipping_fee order line to the order_lines if not already present
  • This updated order will be sent back to Klarna as the response to the POST as JSON.
  • If the merchant responds with any status code other than 2XX, or if they do not respond within 10 seconds, the purchase will not complete and an error message will display and instruct the customer to try again. This will be logged for merchant support.

Client Side

  • Once the order is received by Klarna with the tax calculated, the KCO is changed to reflect the billing address, new total amount, and an option to change the shipping address.
  • If shipping options are supplied they will be displayed with the ‘preselected’ option checked.
  • Since the merchant panel initially showed 0 tax, it should be changed to reflect these cost changes. This is done by javascript events fired from the KCO.
  • shipping_address_change JavaScript event
  • Optionally, shipping options and discount codes displayed in the Klarna panel may change causing the total amount to change.
  • Javascript events should be wired to the form elements displaying the Tax and Total amounts.
  • Events that may be wired into the merchant panel:
  • ‘change’ – event fires anytime the email address, zip, or names supplied are changed or entered.
  • ‘shipping_address_change’ – event will fire anytime the shipping address changes.
  • ’order_total_change’ – event will fire anytime the order total change * Code should be added to handle these events and ONLY update the elements required. * Tax and summary totals should be displayed. * Available shipping options should be displayed if not already. * Discounts option elements should be displayed if not already.
  • ‘shipping_option_change’ - fired anytime the user selects a different shipping option
  • DO NOT do any of the following:
  • Refresh the entire page. The javascript events on the form elements will update the merchant panel with the changes.
  • Create a new Klarna checkout. This would create a new Klarna order id
  • Perform a POST to create or update the order. The order was updated at Klarna with the response sent back from the POST from Klarna.
  • Perform a GET with the orders location URI. What was sent back with the Response to Klarna is the most current order.

User may change shipping address or select a different shipping option or add a discount

  • If any of these occur within the KCO the appropriate events will fire allowing the merchant panel to be re-displayed without performing screen refreshes.
  • The 2 panels should always be in sync.

Complete Checkout & Validation

Once the checkout has completed at Klarna the merchant may want to validate the order items are in stock, or confirm the order items in the cart are the same as what Klarna shows.

If no validate URL is assigned to the merchant_urls the order is updated in Klarna Checkout (KCO) with a status of ‘checkout_complete’. No other changes may be made to the order through the Checkout API’s. Afterwards, changes may only be made through Klarna Order Management API.

Validate – Must complete within 3 seconds else the order is created.

If a ‘validation’ URL (MUST BE SSL ADDRESS) is assigned in the collection of merchant_url’s, then Klarna will perform a POST request to this URL. The entire order is passed back here. The status will still be ‘checkout_incomplete’ so changes may still be made. Typical issues:

  • 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.
  • Another issue here could be that the line items are out of synch because something was added to the cart after the checkout was started. Compare the current cart state to the Klarna order state (totals, shipping selection, discounts, and gift cards). If they don’t match there is an issue.
  • No Klarna PUTS or GETS should be done in this function.
  • No updates to the merchant cart done in this function since they should occur on the shopping pages.

Validate OK – Or not completed within 3 seconds

If the validation is not performed within 3 seconds it is considered valid and the confirmation redirect will occur.

  • To approve the purchase, reply with a HTTP status 2XX. The consumer will then be redirected as normal to the checkout confirmation page.

Validate Not OK

  • To deny the purchase, reply with a HTTP status 303. 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.
  • If the rejection is due to line items being out of sync, the easiest way to fix this would be for the customer to click the checkout button again which will open the checkout page and refresh it with the current cart items on the site. This will use the existing Session order URI to GET the order.
  • Complete the checkout process again.

Confirmation

  • The confirmation URL assigned to the list of merchant_url’s is called from Klarna.
  • This URL should NOT be the final page shown to the customer.
  • Klarna will update the order status to ‘checkout_complete’.
  • A final GET is performed returning the order as it exists in Klarna.
  • This page should have logic that commits the order in the merchant system.
  • If the commit of the order succeeds, then another redirect done by the merchant site should be performed to take the customer to the final confirmation page. * Now that the status has updated to ‘checkout_complete’ the <div> tag returned in the html snippet from the GET request will be different and should be rendered in a separate page.
  • If the commit fails: * The order should be cancelled in Klarna using the Order Management API. This cancel will need to be queued by the merchant since there could be a delay for the order to be accessible in the Order Management API. * The customer should be redirected to a cart page or similar where the merchant can create a new order and checkout again
  • The order is placed into a queue at Klarna waiting to load to the Order Management system.

Push

Once the queued order moves to Klarna’s Order Management a POST is made to the ‘push’ URL provided in the list of merchant_url’s. This occurs every 4 hours for 48 hours or until it’s acknowledged. The Merchant should have a process that can ‘Acknowledge’ this in Order Management.

If the order isn’t created in the merchant’s system. It should be done here. Once created the internal merchant order id should be updated to the MerchantReference1 field for the order in Klarnas order management system. If the order for any reason can’t be created in the merchant’s system the order should be canceled with Klarna using the Order Management API.

Acknowledge – through Order Management API

Once the order has been pushed to Order Management it should be ‘Acknowledged’ by the merchant.

  • Send a POST request to ‘Acknowledge’ the order.
  • This may be a good time to update the merchant_reference1 and merchant_reference2 if not already set.
  • Merchant_reference1 is ALWAYS the external customer facing ‘Order Id’ generated by the merchant.
  • Merchant_reference2 can be another id associated to the order.
  • At this point the items may be shipped.
  • Once shipped, the merchant will make capture calls using the Klarna Order Management API.

Address limitations

Example if address is limited to X characters:

  • If address line 1 is greater than X and address line 2 is empty then search for the first occurrence of these abbreviations (search whole word not just in-string):
  • APT
  • BSMT
  • BLDG
  • DEPT
  • FL
  • FRNT
  • HNGR
  • LBBY
  • LOT
  • LOWR
  • OFC
  • PH
  • PIER
  • REAR
  • RM
  • SIDE
  • SLIP
  • SPC
  • STOP
  • STE
  • TRLR
  • UNIT
  • UPPR

and if found split to address line 2.

  • Optionally, truncate Street Address 1 and 2 at X characters

Name length may be limited on your end.

  • Truncate first name at 15 characters
  • Truncate last name at XX characters (confirm length)
  • Replace any of the following characters @ $ ! % ^ & * ( ) ~ < > + # in the first name with a space
  • Confirm the validation for last_name. If needed, should also strip invalid characters from it as well.

Apply a phone number rule. It appears that phone numbers with +1 are being failed for some merchants.

Merchants should support the E.164 number formatting for all phone numbers both in the ‘to’ and ‘from’ fields. This format is the internationally-standardized format for all phone numbers, and it includes all the relevant information to route calls and SMS messages globally. E.164 numbers can have a maximum of fifteen digits and are usually written as follows: [+][country code][subscriber number including area code].

Apply a zip code rule as well that will support both 5 digit zips as well as 5-4 digit zips for the US.

What’s next?

  • You now know how to create and read a checkout order. We encourage you to take a look at the next step in the tutorial where you will test your integration to make sure everything works as expected.
  • In order to finalize the payment, and initiate the payout to you, you need to capture the order after you have shipped it to the consumer. You can either use our APIs for managing orders, or you can perform this action manually each time in our Merchant Portal.