#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());
}