Copied to clipboard

Flag this post as spam?

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


  • Adam Shallcross 55 posts 211 karma points MVP c-trib
    7 days ago
    Adam Shallcross
    0

    Order errors being received but orders going through OK

    We have a few issues appearing with some of the orders coming in. We received an error on the order and it is noted as an error in the backoffice of Vendr, but the payment is going through fine in Stripe, the order looks OK as far as we can tell.

    What would this error be? and is there anywhere we can see what these errors are? Is there Vendr Logging or does it use standard Umbraco logging?

    We can't see any associated errors in the Umbraco logs though.![enter image description here][1]

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    7 days ago
    Matt Brailsford
    0

    Hi Adam,

    Orders go into the error state if any of the following are true.

    1. The order finalizes but the payment status is error
    2. The order finalizes but the amount captured differs from the amount of the order
    3. If the callback URL is requested but the order reference in the URL doesn't match the order retrieved from the database

    It looks like your payment status is Captured, so the only one I could think it could be really is that the captured payment amount isn't matching the order total amount 🤔

    Unfortunately an error order status doesn't currently log the reason for it being put into the error status. I'll add this to our issue tracker though as this obviously would be useful information.

    Matt

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    7 days ago
    Matt Brailsford
    0

    Actually, the order can also have an OrderStatusCode property which could be one of the following:

    401 - InconsistentOrderReference
    402 - InconsistentPayment
    403 - ErrorAtPaymentGateway

    Does the order have a order status code set?

  • Adam Shallcross 55 posts 211 karma points MVP c-trib
    7 days ago
    Adam Shallcross
    0

    Where does the code appear? in the DB or in the backoffice?

  • Adam Shallcross 55 posts 211 karma points MVP c-trib
    7 days ago
    Adam Shallcross
    0

    Thanks Matt, yes we have indeed noticed that the order amount is different to the amount Stripe has returned.

    The odd thing is that it is exactly £12 on both orders, which is the cost of delivery which they shouldn't be being charged anyway.

    It's odd as it is only on these 2 orders, and not the other 4 we've had.

    Any thoughts? we are investigating anyway

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    7 days ago
    Matt Brailsford
    0

    How is cost of delivery being removed? from a discount? or some other way?

  • Adam Shallcross 55 posts 211 karma points MVP c-trib
    7 days ago
    Adam Shallcross
    0

    we're using IShippingCalculator and setting the price there for different member groups.

    Over 6 bottles, the delivery should be free, under 6 bottles they are charged £12, so basically it's not removing this in the order even though Stripe is actually charging the correct price i.e. it is removing and charging the correct amount in Stripe but the order isn't removing it.

  • Łukasz Koruba 21 posts 121 karma points
    4 days ago
    Łukasz Koruba
    0

    Hello Matt,

    as Adam mentioned we're overriding ShippingCalculator class and have custom implementation of CalculateShippingMethodPrice() method. For a certarin user if quantity is 6 or higher the shipping price is set to 0. And that's what's returned from our method.

    enter image description here

    But on order summary we got shipping price set to £10.00 plus VAT which is £12.00. Card is charged amount without shipping price as it should be but order still have shipping price set to £12.00. And we got Order Error.

    enter image description here

    Below is the code of our implementation. Could you tell us what could be the reason for that behaviour. Are we missing something that's need to be overriden as well?

    public class MemberTypeShippingCalculator : ShippingCalculator
    {
        private readonly IStoreService _storeService;
        private readonly IUmbracoContextFactory _contextFactory;
    
        public MemberTypeShippingCalculator(ITaxService taxService,
            IStoreService storeService,
            IUmbracoContextFactory contextFactory)
                : base(taxService, storeService)
        {
            _storeService = storeService;
            _contextFactory = contextFactory;
        }
    
        public override Price CalculateShippingMethodPrice(ShippingMethodReadOnly shippingMethod, Guid currencyId, Guid countryId, Guid? regionId, TaxRate taxRate, ShippingCalculatorContext context)
        {
            shippingMethod.MustNotBeNull(nameof(shippingMethod));
            taxRate.MustNotBeNull(nameof(taxRate));
    
            var store = _storeService.GetStore(shippingMethod.StoreId);
    
            if (VendrConstants.ShippingOptions.CollectionFromBermondseyWarehouse.Equals(shippingMethod.Alias))
            {
                return Price.Calculate(shippingMethod.GetPrice(currencyId, countryId, regionId), taxRate, currencyId, store.PricesIncludeTax);
            }
    
            var shippingPrice = GetPrice(context);
    
            return Price.Calculate(shippingPrice, taxRate, currencyId, store.PricesIncludeTax);
        }
    
        private decimal GetPrice(ShippingCalculatorContext context)
        {
            var quantity = CalculateQuantity(context);
    
            var memberTypeService = DependencyResolver
                .Current
                .GetService<IMemberTypeService>();
    
            if (memberTypeService.HasValue())
            {
                if (memberTypeService.IsMemberFriend() || memberTypeService.IsMemberFamily())
                {
                    return quantity <= 5m
                        ? ShippingPriceConfiguration.FamilyAndFriend.UpTo5
                        : ShippingPriceConfiguration.FamilyAndFriend.From6;
                }
    
                if (memberTypeService.IsMemberHospitalityProfessional())
                {
                    switch (quantity)
                    {
                        case decimal n when (n <= 5m):
                            return ShippingPriceConfiguration.HospitalityProfessionals.UpTo5;
                        case decimal n when (n >= 6m && n <= 11):
                            return ShippingPriceConfiguration.HospitalityProfessionals.From6To11;
                        case decimal n when (n >= 12m && n <= 23):
                            return ShippingPriceConfiguration.HospitalityProfessionals.From12To23;
                        case decimal n when (n >= 24m):
                            return ShippingPriceConfiguration.HospitalityProfessionals.From24;
                    }
                }
            }
    
            return quantity <= 11
                ? ShippingPriceConfiguration.Guest.UpTo11
                : ShippingPriceConfiguration.Guest.From12;
        }
    
        private decimal CalculateQuantity(ShippingCalculatorContext context)
        {
            var quantity = 0m;
    
            using (var umbracoContext = _contextFactory.EnsureUmbracoContext())
            {
                var contentCache = umbracoContext.UmbracoContext.Content;
    
                foreach (var orderLine in context.Order.OrderLines)
                {
                    if (!Guid.TryParse(orderLine.ProductReference, out var productKey))
                    {
                        continue;
                    }
    
                    var product = contentCache.GetById(productKey);
    
                    switch (product)
                    {
                        case WineBox wineBox:
                            quantity += orderLine.Quantity * wineBox.Wines.Count();
                            break;
                        case Wine _:
                            quantity += orderLine.Quantity;
                            break;
                    }
                }
            }
    
            return quantity;
        }
    }
    
  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    4 days ago
    Matt Brailsford
    1

    Ok, I think your issue is that your are accessing the current member from the current session. This is fine prior to being redirected to Stripe, but the order is finalized via a webhook from Stripe and so that request won't be authenticated and thus your order gets calculated as full price.

    This is why we have our member based discount use the customer reference on the order to lookup the member, rather than relying on the session as we can't guarantee all requests will be made within the same session.

    If you have assigned the member to the order via it's customer reference property, then I'd suggest updating your logic such that you fetch the member from that key and decide whether to apply the discount, rather than basing on the session.

    Matt

    PS I'm guessing this is the case as I can't see what happens in the member based extension methods, but I think this is likely the culprit

  • Łukasz Koruba 21 posts 121 karma points
    4 days ago
    Łukasz Koruba
    0

    For initial implementation I was using MembershipHelper and method GetCurrentUserRoles() which gets user roles from current Session. But I tested order behaviour on GetUserRoles(string email) or GetAllRoles(string email) from IMemberService and the result is exactly the same.

        private decimal GetPrice(ShippingCalculatorContext context)
        {
            var quantity = CalculateQuantity(context);
    
            var memberService = DependencyResolver
                .Current
                .GetService<IMemberService>();
    
            var userRoles = memberService.GetAllRoles(context.Order.CustomerInfo.Email);
    
            var isFriend = userRoles.Contains(MemberGroupConstants.Friend);
            var isTrader = userRoles.Contains(MemberGroupConstants.HospitalityProfessionals) || userRoles.Contains(MemberGroupConstants.HospitalityOperators);
    
            if (isFriend)
            {
                return quantity <= 5m
                    ? ShippingPriceConfiguration.FamilyAndFriend.UpTo5
                    : ShippingPriceConfiguration.FamilyAndFriend.From6;
            }
    
            if (isTrader)
            {
                switch (quantity)
                {
                    case decimal n when (n <= 5m):
                        return ShippingPriceConfiguration.HospitalityProfessionals.UpTo5;
                    case decimal n when (n >= 6m && n <= 11):
                        return ShippingPriceConfiguration.HospitalityProfessionals.From6To11;
                    case decimal n when (n >= 12m && n <= 23):
                        return ShippingPriceConfiguration.HospitalityProfessionals.From12To23;
                    case decimal n when (n >= 24m):
                        return ShippingPriceConfiguration.HospitalityProfessionals.From24;
                }
            }
    
            return quantity <= 11
                ? ShippingPriceConfiguration.Guest.UpTo11
                : ShippingPriceConfiguration.Guest.From12;
        }
    
  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    4 days ago
    Matt Brailsford
    1

    Have you tested this locally including the webhook integration (docs on how here https://vendr.net/docs/payment-providers/stripe/1-1-0/stripe-checkout/how-to-guides/testing-stripe-webhooks-locally/) and stepped into this code to figure out when in the checkout flow the price goes from correctly being Zero to then being £12 as it definitely is Zero at some point for Stripe to capture the wrong amount, so you should be able to see a breakpoint in your calculator at some point the logic fails and charged them £12.

    It would be good to know during which request the order reverts and whether it is the webhook and session authentication related.

    Matt

  • Łukasz Koruba 21 posts 121 karma points
    3 days ago
    Łukasz Koruba
    0

    Ok, I tested this locally using ngrok. On each step prior payment shipping price on ShippingCalculator is Zero. But after payment debugger is not hitting my breakpotint on ShippingCalculator - should it? It breaks on our CustomStripeProvider but not on ShippingCalculator.

    And not sure but I receive Bad Requests also. Is this related with not having HTTPS?

    enter image description here

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    2 days ago
    Matt Brailsford
    1

    Hey,

    So the shipping calculator should only be hit whilst the order is unfinalized, which I think the order should be until after a successful webhook request. If you are getting a bad request, this is likely coming from the Stripe provider, so the best I could suggest now is to pull the source code of the Stripe provider (https://github.com/vendrhub/vendr-payment-provider-stripe) and debug into that, seeing where the provider is failing. It'll likely be in the GetOrderReference method or the ProcessCallback method.

    Matt

  • Łukasz Koruba 21 posts 121 karma points
    20 hours ago
    Łukasz Koruba
    0

    Matt,

    the problem that I was getting was wrong Webhook Signing Secret which caused Bad Requests.

    Finally I managed to debug the calculating shipping price on Webhook event and you were right that issue was that we used GetCurrentUserRoles() from MembershipHelper. I've change it to GetUserRoles(string email) and used email from CustomerInfo in Order and it's working.

    Which event types we must set on webhook to test all the stuff related with Vendr/Stripe integration?

    Thanks for help!

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    19 hours ago
    Matt Brailsford
    1

    Hey,

    Ahh, that's great that you managed to resolve the issues. I'll try and add the "webhook secret key" to my memory banks incase someone else has a similar issue.

    RE the webhook events, you can find that documented at https://vendr.net/docs/payment-providers/stripe/1-1-0/stripe-checkout/getting-started/configuring-stripe/#webhook

    Matt

  • Matt Brailsford 2852 posts 14824 karma points MVP 7x c-trib
    7 days ago
    Matt Brailsford
    0

    That's pretty odd, as Stripe only captures what it is told to capture, so the order must have known the right price at some point 🤔

    The order status code isn't displayed in the back office as it's purely to help debugging. It's stored in the DB, or you can output it from the order.

    Matt

Please Sign in or register to post replies

Write your reply to:

Draft