Выдача суммы заказа на исправление с разбивкой — Paypal Checkout NET SDK

#paypal #sdk #patch #checkout #orders

Вопрос:

Я столкнулся с проблемой, пытаясь исправить заказ PayPal с обновленными итогами. Я использую PayPal Checkout-NET-SDK, который они предоставляют на GitHub, но образец документации, который у них есть для образца заказа на исправление, немного слишком упрощен: https://github.com/paypal/Checkout-NET-SDK/blob/develop/Samples/PatchOrderSample.cs

Я пытаюсь обновить следующий путь: /purchase_units/@reference_id==»по умолчанию » /сумма»

Я попытался использовать комбинацию установки значения как:

  • Строка JSON, представляющая объект AmountWithBreakdown
  • Объект AmountWithBreakdown

При вызове API с объектом AmountWithBreakdown, назначенным в качестве значения, меня встречает исключение .NET:

Введите » PayPalCheckoutSdk.Заказы.Сумма ущерба» с именем контракта на передачу данных » Сумма ущерба:http://schemas.datacontract.org/2004/07/PayPalCheckoutSdk.Заказов « не ожидается. Рассмотрите возможность использования DataContractResolver, если вы используете DataContractSerializer, или добавьте в список известных типов любые типы, не известные статически, например, с помощью атрибута KnownTypeAttribute или добавив их в список известных типов, переданных сериализатору.

Пример функции, которая создает запрос на ИСПРАВЛЕНИЕ:

  Private Function BuildPatchRequest() As List(Of Patch(Of Object))

        Dim patches = New List(Of Patch(Of Object)) From {
            New Patch(Of Object) With {
                .Op = "replace",
                .Path = "/intent",
                .Value = "CAPTURE"
            },
            New Patch(Of Object) With {
                .Op = "replace",
                .Path = "/purchase_units/@reference_id=='default'/amount",
                .Value = New AmountWithBreakdown With {
                            .CurrencyCode = Me.Order.CurrencyCode,
                            .Value = Me.Order.Total.ToString("N2"),
                            .AmountBreakdown = New AmountBreakdown With {
                                .ItemTotal = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = Me.Order.SubTotal.ToString("N2")},
                                .TaxTotal = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = Me.Order.TaxTotal.ToString("N2")},
                                .Shipping = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = Me.Order.ShippingTotal.ToString("N2")},
                                .Discount = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = Me.Order.DiscountTotal.ToString("N2")},
                                .Handling = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = Me.Order.HandlingFeeTotal.ToString("N2")},
                                .Insurance = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = "0.00"},
                                .ShippingDiscount = New PayPalCheckoutSdk.Orders.Money With {.CurrencyCode = Me.Order.CurrencyCode, .Value = "0.00"}
                            }
                        }
            }
        }
        Return patches

End Function
 

Все попытки создать JSON вручную в виде строки и присвоить ей значение встречают общий ответ об ошибке INVALID_PARAMETER_SYNTAX, несмотря на то, что выходные данные передают инструменты проверки JSON.

Кому-нибудь удалось обновить эту точку данных с помощью PayPal с помощью этого SDK? Моя реализация находится в VB, но я понял суть реализации всех других функций с помощью SDK, созданного на C#.

Комментарии:

1. «Все попытки создать JSON вручную в виде строки и присвоить ему значение встречают общий ответ на ошибку INVALID_PARAMETER_SYNTAX, несмотря на то, что выходные данные проходят средства проверки JSON». Зарегистрируйте тело необработанного запроса ответа для этих попыток, чтобы мы могли увидеть, что в них неправильно.

2. Престон ПХХ, я попытался исправить отдельные моменты в вашем первоначальном комментарии, и в ответе был встречен НЕУБЕДИТЕЛЬНЫМИ замечаниями. Мне нужно будет удалить полный исходный код проекта и интегрироваться с моим проектом, чтобы я мог записать необработанный запрос-в данный момент я просто возвращаю объект, используя классы, предоставленные в SDK.

3. Поэтому я заглянул под капот зависимости PayPalHttp-DotNet, которая реализует метод выполнения создаваемого объекта HttpRequest, и похоже, что он сериализует объект-поэтому я предполагаю, что передаваемая мной строка JSON просто анализируется как обычная строка в качестве парметра значений в объекте запроса на исправление. Ссылка: github.com/paypal/paypalhttp_dotnet/blob/master/…

4. Это имело бы смысл, но нам нужно увидеть полный запрос и ответ на ваш лучший тест, чтобы сообщить, что с ним может быть не так

Ответ №1:

Я сталкиваюсь с той же проблемой.

Система.Время выполнения.Сериализация.Исключение сериализации: Введите «PayPalCheckoutSdk.Заказы.Сумма ущерба» с именем контракта на передачу данных » Сумма ущерба:http://schemas.datacontract.org/2004/07/PayPalCheckoutSdk.Заказов « не ожидается. Рассмотрите возможность использования DataContractResolver, если вы используете DataContractSerializer, или добавьте в список известных типов любые типы, не известные статически, например, с помощью атрибута KnownTypeAttribute или добавив их в список известных типов, переданных сериализатору.

Вызов никогда не поступает в PayPal для ответа, потому что ему не удается сериализовать запрос. Единственный способ, которым я смог заставить его работать, — это создать свой собственный запрос без SDK. Это не готовый к производству код. Я просто проверял, сработает ли это, если я сам создам запрос, и это так.

 var ppe = PayPalClient.environment(productLine);

        var accessTokenClient = new HttpClient(ppe);
        var accessTokenRequest = new AccessTokenRequest(ppe, null);

        var accessTokenResponse = Task.Run(async () =>
        {
            var httpResponse = await accessTokenClient.Execute(accessTokenRequest);
            return httpResponse;
        }).Resu<

        if (accessTokenResponse.StatusCode != HttpStatusCode.OK)
        {
            Logger.Error("[PayPalRestService] Unable to get access token.");
            return null;
        }
        
        var accessToken = accessTokenResponse.Result<AccessToken>();

        var client = new RestClient(ppe.BaseUrl());
        client.AddDefaultHeader("Authorization", $"Bearer {accessToken.Token}");


        var body = BuildUpdateTaxPatchRequest(cart, paypalOrder);
        var request = new RestRequest($"/v2/checkout/orders/{paypalOrder.Id}")
            .AddJsonBody(JsonConvert.SerializeObject(body));

        var response = client.Patch(request);

        if (response.StatusCode == HttpStatusCode.NoContent)
        {
            return GetOrder(paypalOrder.Id, productLine);
        }




private static List<Patch<object>> BuildUpdateTaxPatchRequest(ICart cart, Order paypalOrder)
    {
        //Doc: https://developer.paypal.com/docs/api/orders/v2/#orders_patch

        var subtotal = $"{cart.GetSubTotal():N2}";
        var shipping = $"{cart.GetShippingTotal():N2}";
        var discount = $"{cart.GetOrderDiscountTotal():N2}";
        var tax = $"{cart.GetTaxTotal():N2}";
        var total = double.Parse(tax, CultureInfo.GetCultureInfo("en-US"))   double.Parse(shipping, CultureInfo.GetCultureInfo("en-US"))   double.Parse(subtotal, CultureInfo.GetCultureInfo("en-US")) - double.Parse(discount, CultureInfo.GetCultureInfo("en-US"));
        var strTotal = total.ToString("0.00", CultureInfo.GetCultureInfo("en-US"));


        var updates = new AmountWithBreakdown()
        {
            CurrencyCode = paypalOrder.PurchaseUnits.First().AmountWithBreakdown.CurrencyCode,
            Value = strTotal,
            AmountBreakdown = new AmountBreakdown
            {
                ItemTotal = new Money
                {
                    CurrencyCode = cart.Currency.CurrencyCode,
                    Value = subtotal
                },
                Shipping = new Money
                {
                    CurrencyCode = cart.Currency.CurrencyCode,
                    Value = shipping
                },
                TaxTotal = new Money
                {
                    CurrencyCode = cart.Currency.CurrencyCode,
                    Value = tax
                },
            }
        };

        var patches = new List<Patch<object>>
        {
            new Patch<object>
            {
                Op= "replace",
                Path= "/purchase_units/@reference_id=='default'/amount",
                Value = updates
            }
        };

        return patches;
    }
}
 

Комментарии:

1. Скотт, спасибо за это-в качестве абсолютного запасного варианта мне, возможно, придется пойти этим путем. У меня есть открытое обращение в службу поддержки PayPal, чтобы узнать, не могут ли они заставить одного из разработчиков из проекта SDK разобраться в этом или нет. На их странице GitHub нет раздела «Проблемы», и они направляют вас в службу поддержки PayPal, поэтому я надеюсь, что смогу получить там некоторые ответы.

2. Я попросил в случае поддержки PayPal передать это их команде разработчиков SDK и сослался на URL-адрес этого вопроса. Скотт, отметив ваш ответ как правильный, поскольку я смог реализовать аналогичный подход, используя объект HttpWebRequest .NET и самосериализацию объекта, возвращенного BuildPatchRequest для тела запроса. Я обновлю это снова, если когда-нибудь услышу, что они решили проблему или решили, как это сделать, просто используя свой SDK.

Ответ №2:

У меня тоже была эта проблема, и я посмотрел исходный код PayPalHttp.HttpClient и нашел решение, которое работает для меня. Может быть, это было бы полезно для вас.

 public async Task<UpdatePayPalV2CheckoutPaymentResponse> UpdatePayment(string orderId, decimal amount)
{
    try
    {
        var request = new OrdersPatchRequest<object>(orderId);

        // This doesn't work bacause DataContractSerializer.
        // request.RequestBody(BuildPatchRequest(amount));

        var json = JsonConvert.SerializeObject(BuildPatchRequest(amount));
        request.Content = new StringContent(json, Encoding.UTF8, "application/json");

        await CreatePayPalClient().Execute(request);
    }
    catch (Exception e)
    {
        return new UpdatePayPalV2CheckoutPaymentResponse
        {
            Success = false,
            Message = e.Message
        };
    }

    return new UpdatePayPalV2CheckoutPaymentResponse
    {
        Success = true
    };
}

private static List<Patch<object>> BuildPatchRequest(decimal amount)
{
    var patches = new List<Patch<object>>
    {
        new Patch<object>
        {
            Op = "replace",
            Path = "/purchase_units/@reference_id=='default'/amount",
            Value = new AmountWithBreakdown
            {
                CurrencyCode = "USD",
                Value = amount.ToString("F")
            }
        }
    };

    return patches;
}

private PayPalEnvironment CreatePayPalEnvironment()
{
    PayPalEnvironment environment;
    if (_orderProcessingConfiguration.PayPalCheckoutConfiguration.Sandbox)
    {
        environment = new SandboxEnvironment(
            _orderProcessingConfiguration.PayPalCheckoutConfiguration.ClientId,
            _orderProcessingConfiguration.PayPalCheckoutConfiguration.ClientSecret
            );
    }
    else
    {
        environment = new LiveEnvironment(
            _orderProcessingConfiguration.PayPalCheckoutConfiguration.ClientId,
            _orderProcessingConfiguration.PayPalCheckoutConfiguration.ClientSecret
            );
    }

    return environment;
}

private PayPalHttp.HttpClient CreatePayPalClient()
{
    return new PayPalHttpClient(CreatePayPalEnvironment());
}