Order management in Klarna Checkout Module
Links to the first two posts in this series:
These posts covered the checkout process - at this point Klarna has confirmed to us that payment is ok. The customer may have paid using invoice, which is the default option, or by using Visa/Mastercard - regardless of payment option selected a reservation is made in Klarnas system and the reservation id is what we save when we create the purchase order in Commerce.
The Klarna checkout module supports all payment operations following standard Commerce workflow processes:
Capture: Used to complete an Authorization transaction that was successfully authorized through the payment gateway. Note: An Authorization and Capture together are considered one complete transaction. Once the Capture is submitted, the transaction will be sent for settlement.
Void: Used to cancel an original transaction that is not yet settled and prevents it from being sent for settlement.
Credit: Returns the specified amount (posts a credit) to the cardholder’s account.
When complete shipment occurs (the order is shipped from the warehouse), the Episerver Commerce CompleteShipmentWorkflow will run. As part of the process, the payment type is passed to the payment gateway and the gateway executes the payment transaction with the payment system. Payment gateways provide an interface to the system which provides payment processing.
Klarna payment gateway will activate the reservation as part of the capture payment event. At this time the reservation will be made into an invoice in Klarnas system, and the customer will receive the invoice by email. Or if the customer has paid with Visa/Mastercard the amount reserved will be charged.
Here is a simplified sample of the call to Klarna order api for activating the order:
var api = new Api(CurrentConfiguration);
api.OrderId1 = orderId;
api.Update(reservationNumber); // update with order id and cart items
var response = api.Activate(reservationNumber);
As part of the response from Klarna we receive an invoice number which we save to the purchase order.
// we need to save invoice number incase of returns later
purchaseOrder[MetadataConstants.InvoiceId] = response.InvoiceNumber;
As you can see from the code above we update the order before activiating it. We do this to support partial shipping - you may have ordered 3 boxers, but they only had 2 left in stock.
If no items are shipped (VOID operation), the order is cancelled in Commerce and the Klarna reservation is cancelled.
Any returns are handled through the gateway Credit operation. Below is a small example of the code, please note that for simplicity I have left out parts of the code. The full source is located in KlarnaCheckoutPaymentGateway.cs
// Determine if this is full refund, in that case we will call CreditInvoice
// If payment.Amount = captured amount then do full refund
var capturedAmount = orderGroup.OrderForms.Payments
.Where(p => p.TransactionType == "Capture" & p.Status == PaymentStatus.Processed.ToString())
.Sum(p => p.Amount);
var result = new RefundResponse();
if (capturedAmount == payment.Amount) // full refund
result = orderApiClient.CreditInvoice(invoiceNumber);
var returnItems = returnFormToProcess.LineItems.Select(item => item.ToCartItem()).ToList();
// if shipment is part of returnForm, then we will return shipping cost as well
var shipment = returnFormToProcess.Shipments;
if (shipment != null && shipment.ShippingTotal > 0)
result = orderApiClient.HandleRefund(invoiceNumber, returnItems);
payment.Status = result.IsSuccess ? PaymentStatus.Processed.ToString() : PaymentStatus.Failed.ToString();
What happens next depends on the payment option selected:
- Prior to invoice due date: Klarna will send a new and updated invoice to the customer
- Invoice payed: Klarna will contact customer to obtain details for a refund
- Paid with card: refund made to the card used