Implementing Klarna Checkout
In this tutorial we're going to look at how we can implement Klarna Checkout on our webshop in a few easy steps.
This tutorial assumes you've already got a functional webshop, as well as user credentials from Klarna.
The first thing you'll want to do before implementing Klarna Checkout is to update your website to the latest version of Relatude. If you're already using Relatude with Nuget then just go ahead and grab the latest version from there; otherwise you might want to have a look at this article.
Once you've made sure that you have the latest version of Relatude installed, go to the Relatude UI and locate the Shop-content you want to use Klarna on.
Create a new CreditCardPaymentMethod for the shop, by adding a PaymentMethod.
You will need to fill out the MerchantId
, Token
, Return Url
and Callback Url
values. Under the 'Payment method' tab you'll need to set 'Type of payment' to 'Two phase' and set 'Payment provider' to:
WAF.Common.Webshop.Providers.PaymentMethodProviders.CreditCardPaymentProviders.KlarnaCheckoutProvider
Also make sure that your shop is present in the 'Shops' relation field, and add any other shops you want to use with this payment method.
The merchantId should be your Klarna merchantId, and the token should be your merchantId and your Klarna password joined by a colon ':'. Like this: MerchantId:Password
Remember to check the "Test mode enabled" if you are using test credentials from Klarna.
The default value for 'Return Url' is 'https://your.site/wafclient/paymentprovider/KlarnaCheckoutConfirmOrder?klarna_order_id={checkout.order.id}'
The default value for 'Callback Url' is 'https://your.site/wafclient/paymentprovider/KlarnaCheckoutPush?klarna_order_id={checkout.order.id}'
Now we can implement the necessary code on our checkout page.
Here's our example checkout page:
Once we click on 'Next', we're going to render an html-snippet from Klarna in an empty <div> below the button. Here's the code:
protected void btnNext_Click(object sender, EventArgs e) {
// Fetch order
var order = WAFShopHelper.GetCurrentOrder(Request, Response);
order.CalculateAndSaveAmounts();
order.UpdateChanges();
order = WAFContext.Session.GetContent<WAF.Engine.Content.Native.Order>(order.NodeId);
// Get the PaymentMethod and PaymentMethodProvider
var paymentMethod = order.PaymentMethod.Get();
var paymentProvider = paymentMethod.GetPaymentProvider();
// Create payment data
var paymentMethodData = new PaymentMethodData();
if (paymentProvider is KlarnaCheckoutProvider) {
paymentMethodData.PaymentData.Add("Terms", string.Format("{0}/{1}", WAFRuntime.UrlFromRootToApp.TrimEnd('/'), "termsExampleUrl"));
}
paymentMethodData.PaymentMethodNodeId = paymentMethod.NodeId;
paymentMethodData.SetPropertiesFromOrder(order);
// Create or update order at Klarna. Get html snippet
var paymentActionResult = paymentProvider.CreateSession(paymentMethodData);
if (paymentActionResult.Success) {
var html_string = paymentActionResult.PostValues.Get("html_snippet");
if (!string.IsNullOrEmpty(html_string))
CreateKlarnaCheckoutSession(html_string);
}
}
/// <summary>
/// Render html snippet from Klarna
/// </summary>
/// <param name="html_snippet"></param>
private void CreateKlarnaCheckoutSession(string html_snippet) {
var sb = new StringBuilder();
sb.AppendLine("<div id=\"my-checkout-container\">");
sb.AppendLine(html_snippet);
sb.AppendLine("</div>");
litHtml.Text = sb.ToString();
btnNext.Visible = false;
}
Resulting view:
The rest of the checkout logic is handled by Klarna.
When Klarna Checkout finishes, the user is redirected to your "OrderReceived" page. This page can be changed under the "Settings" tab in the Shop module. The order reference (QueryString: "orderRef", Property: WAF.Engine.Content.Native.Order.OrderReference) is also provided in the QueryString to the "OrderReceived" page.
Now we need to handle when the user arrives at the 'Order received' page.
We're going to render another html snippet. Here's how:
public partial class OrderReceivedPage : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
// Check if there's an 'orderref' parameter. If there is, fetch the corresponding order
if (Request["orderref"] != null) {
Order order = WAFContext.Session.Query<Order>().Where(AqlOrder.OrderReference == Request["orderref"].ToString()).Execute(1).FirstOrDefault();
if (order != null) {
// Get the payment method and payment method provider
var pm = order.PaymentMethod.Get();
var provider = pm.GetPaymentProvider();
// If the payment method provider is Klarna Checkout, get the html snippet and render it in an empty <div>
if (provider is KlarnaCheckoutProvider) {
// Create PaymentMethodData based on the order
var pmd = new PaymentMethodData();
pmd.SetPropertiesFromOrder(order);
var snippet = ((KlarnaCheckoutProvider)provider).GetCheckoutConfirmationSnippet(pmd).PostValues.Get("html_snippet");
litOrderRef.Text = snippet;
} else {
// Handle other payment methods here
}
}
}
}
}
And here's the result:
Extra:
Merchant Urls:
Klarna also has the option of adding endpoints related to the payment process. If you would like to take advantage of any of these endpoints you could add the urls before you create the session, the same way that the Terms-url is added.
paymentMethodData.PaymentData.Add("Terms","https://www.example.com");
paymentMethodData.PaymentData.Add("Validation","https://www.example.com");
paymentMethodData.PaymentData.Add("ShippingOptionUpdate","https://www.example.com");
paymentMethodData.PaymentData.Add("AddressUpdate","https://www.example.com");
paymentMethodData.PaymentData.Add("Notification","https://www.example.com");
paymentMethodData.PaymentData.Add("CountryChange","https://www.example.com");