Copied to clipboard

Flag this post as spam?

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


  • Sibren 39 posts 211 karma points c-trib
    Jun 21, 2021 @ 09:07
    Sibren
    0

    Returning paymentpage from ApiController

    Hi Matt,

    We're currently implementing a new site, where we use VueJS for the frontend. I've created a service, which saves the order with the paymentmethod etc. I'm missing what I need to do to return the form from the selected paymentmethod.

    Right now I'm doing something like this:

    order.SetShippingCountryRegion(country);
                order.SetShippingMethod(shipmentMethod);
                order.SetPaymentCountryRegion(country);
                order.SetPaymentMethod(paymentMethod);
                order.InitializeTransaction();
                order.Finalize(order.TotalPrice.Value, order.Id.ToString(), paymentStatus: Vendr.Core.Models.PaymentStatus.Initialized);
                _vendrApi.SaveOrder(order);
    
                uow.Complete();
                var paymentShizzle = JsonConvert.DeserializeObject<InvoicingSettings>(JsonConvert.SerializeObject(paymentMethod.PaymentProviderSettings));
                return paymentShizzle.ContinueUrl;
    

    But how do I go about combining this with the right paymentform (like Paypal or something)? I'm now just returning the ContinueUrl.

    I've got a GenerateForm for the paymentmethod, but I'm missing some kind of link. I guess... The missing link... For returning the needed GenerateForm.

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Jun 21, 2021 @ 09:30
    Matt Brailsford
    100

    Hi Sibren,

    Ok, well firstly, you probably shouldn't finalize the order at this point. You really should only call this once you have some kind of notification from payment gateway as once an order is finalized, there is no going back.

    In terms of generating the HTML form to render, unfortunately we only currently have one way of doing this, which is by using the @Html.BeginPaymentForm helper which runs in a razor file.

    You might be able to get the payment providers form definition by calling the paymentProvider.GenerateForm method, but you'd be responsible for converting that into an actual form.

    To do this, you'd probably need to do something like

    var paymentMethod = paymentMethodService.GetPaymentMethod(writableOrder.PaymentInfo.PaymentMethodId.Value);
    var paymentProvider = paymentProviderService.GetPaymentProvider(paymentMethod.PaymentProviderAlias);
    var settings = new ReadOnlyDictionary(translationService.TranslateValues(paymentMethod.PaymentProviderSettings, writableOrder.LanguageIsoCode));
    
    var continueUrl = uriResolver.GetContinueUrl(paymentMethod.PaymentProviderAlias, orderReference, hashProvider);
    var cancelUrl = uriResolver.GetCancelUrl(paymentMethod.PaymentProviderAlias, orderReference, hashProvider);
    var callbackUrl = uriResolver.GetCallbackUrl(paymentMethod.PaymentProviderAlias, orderReference, hashProvider);
    
    var formResult = paymentProvider.GenerateForm(writableOrder, continueUrl, cancelUrl, callbackUrl, settings);
    

    This is ultimately what the Html.BeginPaymentForm helper does and then renders an MvcForm based on the formResult settings.

    A few things to note though.

    1) The Html.BeginPaymentForm method is generally also responsible for ensuring at the last minute that if there is a logged in member, that their member ID is assigned to the order. If you need this behavior, you'll have to implement this too.

    2) The formResult object can also contain a MetaData property which it is expected that whatever is in this, is copied over to the order's properties collection so again you'll need to do this. This can be essential if the payment provider stores values in the order that it expects when it comes to finalize the order later.

    You'r implementation for this should be something like

    if (formResult.MetaData != null && formResult.MetaData.Count > 0)
    {
        writableOrder.SetProperties(formResult.MetaData
            .ToDictionary(x => x.Key, x => new PropertyValue(x.Value, true, false)), SetBehavior.Merge);
    }
    

    As such, you may want to move your _vendrApi.SaveOrder(order); and uow.Compelte() to run AFTER this update.

    We do need to make all this a bit nicer / easier for SPA usage but I need to put some time aside with some devs to discuss what this API would look like.

    In the meantime you'll either need to do the above, or, look at doing something where you ajax load in a razor partial that actually calls Html.BeginPaymentForm.

    Hope this helps

    Matt

  • Sibren 39 posts 211 karma points c-trib
    Jun 22, 2021 @ 11:34
    Sibren
    0

    Hi Matt,

    Thank you, that did it!

    However, when I have an invoice, it gets set as an error in Vendr 1.8:

    using (var uow = vendrApi.Uow.Create())
            {
                var store = currentPage.GetStore();
                var country = vendrApi.GetCountries(store.Id).First();
                var paymentMethod = vendrApi.GetPaymentMethods(store.Id).FirstOrDefault(x => x.Alias == model.PaymentMethod);
                var shipmentMethod = vendrApi.GetShippingMethods(store.Id).FirstOrDefault();
                var order = vendrApi.GetCurrentOrder(store.Id)?
                    .AsWritable(uow)
                    .SetProperties(new Dictionary<string, string>
                    {
                            { VendrConstants.Properties.Customer.EmailPropertyAlias, model.EmailAddress },
                            { VendrConstants.Properties.Customer.FirstNamePropertyAlias, model.FirstName },
                            { VendrConstants.Properties.Customer.LastNamePropertyAlias, model.LastName },
                            { "billingAddressLine1", model.Street + " " + model.StreetNumber },
                            { "billingCity", model.City },
                            { "billingZipCode", model.PostalCode },
                            { "billingTelephone", model.PhoneNumber },
                            { "comments", model.Remark },
                            { "ipAddress", GetIPAddress() }
                    });
    
                if (order == null)
                {
                    throw new ArgumentNullException("Order not found. Perhaps already completed");
                }
    
    
                order.SetShippingCountryRegion(country);
                order.SetShippingMethod(shipmentMethod);
                order.SetPaymentCountryRegion(country);
                order.SetPaymentMethod(paymentMethod);
                order.InitializeTransaction();
                var returnString = "";
                if (paymentMethod.Alias == "invoicing")
                {
                    var paymentShizzle = JsonConvert.DeserializeObject<InvoicingSettings>(JsonConvert.SerializeObject(paymentMethod.PaymentProviderSettings));
                    order.Finalize(order.TotalPrice.Value, order.Id.ToString(), paymentStatus: PaymentStatus.Initialized);
    
                    returnString = paymentShizzle.ContinueUrl;
                }
                else
                {
                    // removed for clarity
                }
    
                vendrApi.SaveOrder(order);
                uow.Complete();
                return returnString;
            }
    

    Am I missing some required fields?

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Jun 23, 2021 @ 08:13
    Matt Brailsford
    0

    Hi Sibren,

    As I said before, you shouldn't really be calling Finalize on the order at this point. This is the responsibility of the payment provider to do.

    RE the order having an error state, what is the orders OrderStatusCode?

    Matt

  • Sibren 39 posts 211 karma points c-trib
    Jun 23, 2021 @ 12:12
    Sibren
    0

    Hi Matt,

    Thanks, yeah, I'm moving that part to the webhook-callback. While working on the webhook, I saw the OrderStatusCode was 'InconsistentPayment'. From there on, I changed the code and just set the right OrderStatusCode. I think I'm fine now.

    Thanks for your help.

Please Sign in or register to post replies

Write your reply to:

Draft