Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • William Zhang 39 posts 243 karma points
    Jul 02, 2016 @ 15:39
    William Zhang
    0

    Klarna Checkout integration

    Hi,

    I'm trying to integrate Klarna Checkout (https://developers.klarna.com/en/se/kco-v2/checkout) with Merchello, and I've run into a major issue.

    Klarna Checkout handles the entire checkout process through iframed forms, and I've implemented a custom PaymentMethodUiController that handles this, taking advantage of the resolvable payment form feature in Merchello.

    Due to the way Klarna Checkout is designed, we can't create an order/invoice until we've received a confirmation from Klarna (after the customer confirms the purchase). This is done through an HTTP POST request to a special push URL that we've configured earlier.

    The problem, however, is that Merchello's checkout flow uses the merchello cookie to identify the customer, and there is no such cookie in the request when we receive the confirmation via the push URL. This means that there is no customer info from the previous steps in checkout flow when we try to create the order (using BasketCheckoutPaymentManager.AuthorizePayment()), causing the CheckoutPaymentManagerBase.IsReadyToInvoice() to return false.

    According to Klarnas dev support order creation must take place in the push URL endpoint, so moving it to an earlier step when the merchello cookie is available is not an option either.

    Since we have access to the Klarna order ID one possiblity could be to store all the customer info in a temporary DB using the order ID as key and somehow populate the customer context right before we attempt to create the order?

    Or is there a better solution? Has anyone else had any experience with implementing Klarna Checkout?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Jul 05, 2016 @ 17:03
    Rusty Swayne
    0

    Hi William,

    I don't think the problem is with the Merchello cookie (it'll be there), it's the fact that you are circumventing the CheckoutManager and not saving the billing and shipping addresses into it - which is why the IsReadyToInvoice() call is returning false.

    I'm not familiar with Klarna (you'll have to consider whether or not the shipping and taxation are handled in their checkout process), but it seems like what you really want to do is create a custom invoice in the POST endpoint. Then accept a payment against the invoice.

    You could either write you're own CheckoutManager (so that you have all of the Merchello options by extending the checkout manager base classes - like we've done with the basket checkout managers https://github.com/Merchello/Merchello/tree/merchello-dev/src/Merchello.Web/CheckoutManagers) or simply create and save an invoice in a controller and then accept payment against that invoice. In this case, you'll have to empty the basket manually ...

  • William Zhang 39 posts 243 karma points
    Jul 06, 2016 @ 09:05
    William Zhang
    0

    Hi Rusty,

    I see... But as far as I know I'm not circumventing the CheckoutManager (at least not on purpose), as I do save the billing and shipping addresses earlier in the checkout flow. In fact, if I look at the extended data in CheckoutContext.Customer in the step where I render the Klarna payment form, they're there.

    But when I confirm the purchase and a request is made by Klarna to the POST endpoint, the extended data in CheckoutContext.Customer is empty if I look at it again inside the POST enpoint action method.

    As you can see in the following QuickWatch excerpt (of CheckoutContext.Customer), the key is different:

    Before POST endpoint:

    -       customer    {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.ICustomerBase {Merchello.Core.Models.AnonymousCustomer}
    -       [Merchello.Core.Models.AnonymousCustomer]   {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.AnonymousCustomer
    -       base    {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.CustomerBase {Merchello.Core.Models.AnonymousCustomer}
    -       base    {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.EntityBase.Entity {Merchello.Core.Models.AnonymousCustomer}
    +       CreateDate  {2016-07-06 10:33:57}   System.DateTime
            HasIdentity true    bool
    +       Key {f9c3cf0e-d9f4-4158-9ace-59b2d69b2c37}  System.Guid
    +       UpdateDate  {2016-07-06 10:50:50}   System.DateTime
    +       Static members      
    +       Non-Public members      
    -       ExtendedData    Count = 5   Merchello.Core.Models.ExtendedDataCollection
    +       [0] {[merchPaymentMethod, cba95287-d68c-4e67-b9c4-ec4d05ae9f5d]}    System.Collections.Generic.KeyValuePair<string,string>
    +       [1] {[merchOfferCodeTempData, {"VersionKey":"c41f4a75-a6d9-4816-a471-38c78f7ebb8c","Data":[],"ResetWasCancelled":false}]}   System.Collections.Generic.KeyValuePair<string,string>
    +       [2] {[merchBillingAddress, <Address xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Merchello.Core.Models"><Address1>Testvägen 1</Address1><Address2></Address2><AddressType>Billing</AddressType><CountryCode>SE</CountryCode><Email>[email protected]</Email><IsCommercial>false</IsCommercial><Locality>Stockholm</Locality><Name>Test Person</Name><Organization i:nil="true" /><Phone>070123456</Phone><PostalCode>12345</PostalCode><Region i:nil="true" /></Address>]} System.Collections.Generic.KeyValuePair<string,string>
    +       [3] {[merchShippingDestinationAddress, <Address xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Merchello.Core.Models"><Address1>Testvägen 1</Address1><Address2></Address2><AddressType>Shipping</AddressType><CountryCode>SE</CountryCode><Email>[email protected]</Email><IsCommercial>false</IsCommercial><Locality>Stockholm</Locality><Name>Test Person</Name><Organization i:nil="true" /><Phone i:nil="true" /><PostalCode>12345</PostalCode><Region i:nil="true" /></Address>]}  System.Collections.Generic.KeyValuePair<string,string>
    +       [4] {[merchNote, {"VersionKey":"c41f4a75-a6d9-4816-a471-38c78f7ebb8c","Data":[],"ResetWasCancelled":false}]}    System.Collections.Generic.KeyValuePair<string,string>
    +       Raw View        
            IsAnonymous true    bool
    +       LastActivityDate    {2016-07-06 10:50:50}   System.DateTime
    +       Static members      
    +       Non-Public members      
            IsAnonymous true    bool
    +       LastActivityDate    {2016-07-06 10:50:50}   System.DateTime
    

    In POST enpoint:

    -       contextCustomer {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.ICustomerBase {Merchello.Core.Models.AnonymousCustomer}
    -       [Merchello.Core.Models.AnonymousCustomer]   {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.AnonymousCustomer
    -       base    {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.CustomerBase {Merchello.Core.Models.AnonymousCustomer}
    -       base    {Merchello.Core.Models.AnonymousCustomer}   Merchello.Core.Models.EntityBase.Entity {Merchello.Core.Models.AnonymousCustomer}
    +       CreateDate  {2016-07-06 10:49:25}   System.DateTime
            HasIdentity true    bool
    +       Key {1ac6da73-5625-4c31-9cc1-e8bedc4942e5}  System.Guid
    +       UpdateDate  {2016-07-06 10:49:25}   System.DateTime
    +       Static members      
    +       Non-Public members      
    +       ExtendedData    Count = 0   Merchello.Core.Models.ExtendedDataCollection
            IsAnonymous true    bool
    +       LastActivityDate    {2016-07-06 10:49:25}   System.DateTime
    +       Static members      
    +       Non-Public members      
            IsAnonymous true    bool
    +       LastActivityDate    {2016-07-06 10:49:25}   System.DateTime
    

    Could this be due to a different Merchello cookie being submitted (and thus a new anonymous customer being created) when Klarna makes the request?

    Would there be a way to "restore" the previous customer in that case?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Jul 06, 2016 @ 16:11
    Rusty Swayne
    0

    Ah right - I see. You're correct that the customer association is done through the cookie and it does look like the post back is creating a new anonymous customer. Is there a way to pass the customer key to Klarna when you initiate it's checkout and pass it back in the post?

    You could then query for the customer with the CustomerService, and get back into the CheckoutManager ...

  • William Zhang 39 posts 243 karma points
    Jul 06, 2016 @ 18:32
    William Zhang
    0

    Yes, that was what I was thinking too, as a matter of fact I'm currently passing it as a query parameter :)

    But I'm not sure how I would restore it in the CheckoutManager - I haven't found any methods for doing this in the interface. Or maybe I can retrieve it from the CustomerService and call CustomerContext.Reinitialize()? But would this work for anonymous customers as well? Since CustomerService.GetByKey() returns an ICustomer (not IAnonymousCustomer).

    Also, what is the best practice for creating a new invoice "manually" inside the POST endpoint?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Jul 06, 2016 @ 20:13
    Rusty Swayne
    100

    Hey William,

    I don't think it makes sense to try to re-establish a customer context in the post handler - just go directly through the customer ... Try:

    // Get by any will query anonymous first then (if not found) customer
    var customer = customerService.GetByAny([Key]);
    
    // Context settings NEED to match what you originally used or the manager could potentially reset
    var checkoutManager = customer.Basket().GetCheckoutManager([optional context settings]);
    
  • William Zhang 39 posts 243 karma points
    Jul 07, 2016 @ 18:04
    William Zhang
    0

    Thanks Rusty, that worked perfectly!

  • Gopal 14 posts 83 karma points
    Jul 08, 2016 @ 11:16
    Gopal
    0

    Hi William can you help for how me to integrate Klarna checkout for Umbraco in Merchello Bazzar or how to start work for Merchello +Klarna. Becasue i have no idea how to do this. Also can you give steps for Integration

  • William Zhang 39 posts 243 karma points
    Jul 08, 2016 @ 15:28
    William Zhang
    1

    Hi Gopal,

    The first thing you need to do is to set up a Klarna merchant account, since you will need a merchant ID and secret key in order to talk to the Klarna APIs.

    I would recommend that you implement Klarna through Merchello's payment provider system. In other words, you will need to implement a KlarnaPaymentGatewayProvider and a KlarnaPaymentGatewayMethod. You can basically copy-paste from any other payment provider (e.g. the built-in CashPaymentGateway classes), and customize the Authorize and Capture methods. Merchello will then automatically invoke the correct methods when you authorize/capture the payment through the CheckoutPaymentManager in the checkout flow.

    In order for the Klarna payment provider to show up in the backoffice, you need to configure it using the GatewayProviderActivation attribute (on your KlarnaPaymentGatewayProvider). See the CashPaymentGatewayProvider for examples.

    You will also need a MVC controller to render the Klarna Checkout forms, I used a PaymentMethodUiController in order to utilize the resolvable forms feature in Merchello. There are examples of this feature in the Bazaar project, see e.g. CheckoutConfirmationForm.cshtml.

    As for the actual steps I would recommend that you read the material related to Klarna Checkout in Klarna's Developer Portal (https://developers.klarna.com/en/de/kco-v2/checkout), it provides step-by-step instructions with code samples.

    If you need more help you're welcome to start a new thread so that we don't pollute this thread.

  • Gopal 14 posts 83 karma points
    Jul 12, 2016 @ 05:39
    Gopal
    0

    Hi William thanks for Reply and can we make new thread to start more discussion and here is link for this "https://our.umbraco.org/forum/developing-packages//78631-how-to-integrate-klarna-with-merchello-bazaar"

  • Fabian 68 posts 172 karma points
    Sep 14, 2016 @ 15:05
    Fabian
    0

    Hi William,

    I have a project where I also need to integrate Klarna with merchello. It would be great if you can kindly share the code with me for the custom stuff you had to develop like for example the custom PaymentGatewayProvider, etc.

    In an ideal world such shared code would be done as a plugin, like others have done in the past to contribute to the community, for example: https://github.com/BarryFogarty/Merchello.Plugins.SagePay

    Thanks a lot in advance. Would love to hear what you think.

    Kind Regards, Fabian

  • William Zhang 39 posts 243 karma points
    Sep 14, 2016 @ 18:08
    William Zhang
    0

    Hi Fabian,

    I agree, in an ideal world I'd love to contribute with a Klarna payment plugin , but unfortunately I haven't had the time for this - we're racing against the clock to finish our own project :/

    If you'd like I can email you the relevant classes along with a brief explanation, which should be enough to get you started. Hopefully I'll have the time to write a Klarna plugin in the near future when things calm down :)

  • Fabian 68 posts 172 karma points
    Sep 15, 2016 @ 08:10
    Fabian
    0

    Hi William,

    Thanks a lot for your help and prompt reply, I really appreciate it. Yes I feel you it is always a race against time. If i figure it out, hopefully I will be able to contribute and do it as a plugin.

    That sounds great William, can you please do so when you have some spare time, I will be forever grateful. My email address is [email protected]

    Email me whatever you think its relevant and I will figure it out from there.

    Again thanks a lot william, appreciate your support.

    Kind Regards, Fabian

  • Dharmesh 50 posts 210 karma points
    Apr 25, 2017 @ 11:44
    Dharmesh
    0

    Hi William,

    Can you please provide me the plugin for klarna payment integration with merchello if you have implemented it successfully ? I would be grateful to you. Hope you will help to implement this payment integration. Thanks in advance :)

Please Sign in or register to post replies

Write your reply to:

Draft