PayPal REST API.net SDK - 400 Bad Requests
Я работаю в песочнице и использую метод PayPal REST.net SDK Payment.Create с объектом CreditCard. Когда все параметры действительны и используя номер тестового CC из https://developer.paypal.com/webapps/developer/docs/integration/direct/accept-credit-cards/, объект Payment возвращается из этого метода, и все хорошо.
Однако, когда параметр недействителен, например, прошлая дата истечения срока действия или номер CC, не распознанный песочницей, объект Payment не возвращается. Вместо этого метод генерирует исключение: "Исключение в HttpConnection Execute: Неверный ответ HTTP. Удаленный сервер возвратил ошибку: (400)" Плохой запрос ", но без дополнительных объяснений.
Когда я выполняю тот же запрос в cURL, в дополнение к "400 Bad Request", я получаю ответ JSON. Это включает в себя более полезные сообщения, такие как "VALIDATION_ERROR" и "Invalid expiration (не может быть в прошлом)".
Мой вопрос: есть ли способ вернуть эти сообщения из SDK?
Что я пробовал:
- Документы PayPal: https://developer.paypal.com/webapps/developer/docs/api/#errors
В этом документе упоминается, что в случае ошибки они возвращают детали в тексте ответа. К сожалению, он не дает понять, доступны ли они SDK.
- Различные поисковые запросы Google и SO.
- Пример кода PizzaApp, поставляемый с SDK, не имеет ничего общего с обработкой исключений или дальнейшим пониманием этой проблемы.
- Я вижу объект PayPalException в SDK, но не нашел ничего, что указывало бы, как оно должно использоваться или если оно даже имеет отношение к этой проблеме.
Вся помощь очень ценится.
Ответы
Ответ 1
Поскольку никто, кажется, не знает ответа на этот вопрос, я впился в исходный код SDK PayPal.NET для REST API. Из этого обзора видно, что с текущей версией нет никаких условий для возврата сообщений об ошибках, когда серверный код кода HTTP-кода 4xx или 5xx возвращается. Я ссылался на ответы на этот вопрос и изменил SDK, чтобы разрешить возвращать ответ об ошибке, когда это применимо. Здесь соответствующая часть HttpConnection.cs.
catch (WebException ex)
{
if (ex.Response is HttpWebResponse)
{
HttpStatusCode statusCode = ((HttpWebResponse)ex.Response).StatusCode;
logger.Info("Got " + statusCode.ToString() + " response from server");
using (WebResponse wResponse = (HttpWebResponse)ex.Response)
{
using (Stream data = wResponse.GetResponseStream ())
{
string text = new StreamReader (data).ReadToEnd ();
return text;
}
}
}
if (!RequiresRetry(ex))
{
// Server responses in the range of 4xx and 5xx throw a WebException
throw new ConnectionException("Invalid HTTP response " + ex.Message);
}
}
Разумеется, для правильной интерпретации ответа на ошибку требуется изменение функции вызова. Поскольку я использую только API создания платежей, я взял несколько ярлыков, которые не будут работать для общего использования. Однако основная идея заключается в том, что я создал классы PaymentError и Detail, а затем изменил методы Payment.Create и PayPalResource.ConfigureAndExecute для заполнения и передачи объекта PaymentError.
Спустя три года, и есть некоторые улучшения в обработке ответов на ошибки PayPal API. Из-за некоторых других проблем мне пришлось переделать мое приложение и вырвать предыдущий код. Я обнаружил, что теперь вы можете ловушку для PayPal.Exception.PaymentsException, а затем десериализовать строку ответа JSON в объект PayPal.Exception.PaymentsError.
Catch ex As PayPal.Exception.PaymentsException
Dim tmpPmtErr As PayPal.Exception.PaymentsError = _
JsonConvert.DeserializeObject(Of PayPal.Exception.PaymentsError)(ex.Response)
Спасибо @lance в другом ответе за хедз-ап, чтобы более внимательно изучить исключения. Я попытался использовать это решение, но не смог заставить его работать.
Ответ 2
Я только начал общаться с SDK и API сегодня и сразу столкнулся с этой проблемой. Я имею в виду, если я собираюсь создать свою собственную форму для обработки платежей, я бы хотел дать отзыв для пользователей, если что-то пошло не так.
В любом случае, я нашел скрытую информацию во внутреннем исключении. Возможно, это поможет.
catch (PayPal.Exception.PayPalException ex)
{
if (ex.InnerException is PayPal.Exception.ConnectionException)
{
context.Response.Write(((PayPal.Exception.ConnectionException)ex.InnerException).Response);
}
else
{
context.Response.Write(ex.Message);
}
}
Полученный ответ:
{"name":"VALIDATION_ERROR","details":[{"field":"payer.funding_instruments[0].credit_card.number","issue":"Must be numeric"}],"message":"Invalid request - see details","information_link":"https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR","debug_id":"0548e52ef9d95"}
Ответ 3
@Jonathan, REST API интегрирован в log4net и выдает полный ответ об ошибке в файл журнала, если вы его настроили. Вы должны добавить этот раздел конфигурации в свой web.config:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
а также установите параметры:
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="rest-api.log"/>
<appendToFile value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] %message%newline"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="FileAppender"/>
</root>
Откройте ваш global.asax и добавьте его в Application_Start:
log4net.Config.XmlConfigurator.Configure();
Теперь, если в папке журнала установлены разрешения на запись, тогда SDK PayPal REST вытолкнет сообщения об ошибках в файл журнала.
Ответ 4
Моя проблема заключалась в том, что мои total
, detail.subtotal
и items.price
передавали значения, такие как $1,000.00, и ему нужно десятичное значение, поэтому используйте что-то вроде:
total = Regex.Replace(model.OrderTotal, "[^0-9.]", "")
Ответ 5
Улучшение решения здесь... Просто
(Импорт PayPal)
Try
Catch ex As PaymentsException
For Each i In ex.Details.details
Response.Write(i.field) 'Name of Field
Response.Write(i.code) 'Code If Any
Response.Write(i.issue) 'Validation Issue
Next
End Try
Ответ 6
Все вышеприведенное решение действительно не понимает проблему.
Я столкнулся с подобной проблемой некоторое время назад. После отладки моего кода я узнал, что транзакция, которую я делал, была логически неправильной. промежуточный итог был равен 0,25 доллара, а сервер PayPal увидел его и отказался обрабатывать его, и дал мне 400 плохих запросов
Ответ 7
Это, похоже, изменилось, и хотя многие из этих ответов указывают в правильном направлении, никто из них не работал точно для меня. Это мой эквивалент в настоящее время наиболее ответного ответа:
catch (PayPal.PaymentsException ex)
{
context.Response.Write(ex.Response);
}
с ответом:
{"name":"VALIDATION_ERROR","details":[{"field":"start_date","issue":"Agreement start date is required, should be valid and greater than the current date. Should be consistent with ISO 8601 Format"}],"message":"Invalid request. See details.","information_link":"https://developer.paypal.com/docs/api/payments.billing-agreements#errors","debug_id":"8c56c13fccd49"}
Ответ 8
Если вы используете глобализацию за пределами США, вам нужно преобразовать десятичные знаки в InvariantCulture:
order.GetTotal().ToString("N2", CultureInfo.InvariantCulture)