2013-03-22 10 views
12

Ich arbeite in der Sandbox und mit der PayPal REST. NET SDK-Methode Payment.Create mit einem CreditCard-Objekt. Wenn alle Parameter gültig sind und die Test-CC-Nummer von https://developer.paypal.com/webapps/developer/docs/integration/direct/accept-credit-cards/ verwendet wird, wird das Zahlungsobjekt von dieser Methode zurückgegeben und alles ist in Ordnung.PayPal REST API. NET SDK - 400 ungültige Anfragen

Wenn ein Parameter nicht gültig ist, z. B. ein vergangenes Ablaufdatum oder eine CC-Nummer, die von der Sandbox nicht erkannt wird, wird das Zahlungsobjekt nicht zurückgegeben. Stattdessen löst die Methode eine Ausnahme aus: "Ausnahme in HttpConnection Execute: Ungültige HTTP-Antwort Der Remote-Server hat einen Fehler zurückgegeben: (400) Bad Request", aber ohne weitere Erklärung.

Wenn ich die gleiche Anfrage in cURL, zusätzlich zu der "400 Bad Request", bekomme ich eine JSON-Antwort. Dies beinhaltet hilfreichere Nachrichten wie "VALIDATION_ERROR" und "Ungültiger Ablauf (kann nicht in der Vergangenheit sein)".

Meine Frage: Gibt es eine Möglichkeit, diese Nachrichten vom SDK zurück zu bekommen?

Was ich versucht habe:

  • PayPal docs: https://developer.paypal.com/webapps/developer/docs/api/#errors Dieses Dokument erwähnt, dass im Fall eines Fehlers sie die Details in dem Körper der Antwort zurück. Leider gibt es keinen Hinweis darauf, ob diese über das SDK zugänglich sind.
  • Verschiedene Google und SO-Suchanfragen.
  • Der PizzaApp-Beispielcode, der mit dem SDK bereitgestellt wird, hat keine Ausnahmebehandlung oder weitere Einblicke in dieses Problem.
  • Ich sehe ein PayPalException-Objekt im SDK, aber nichts gefunden, das angibt, wie es verwendet werden sollte oder ob es sogar für dieses Problem relevant ist.

Alle Hilfe wird sehr geschätzt.

Antwort

6

Da niemand die Antwort darauf zu wissen scheint, habe ich den Quellcode von PayPal .NET SDK für REST API gegraben. Aufgrund dieser Überprüfung scheint es, dass ab der aktuellen Version keine Rückmeldung der Fehlermeldungen möglich ist, wenn vom Server ein 4xx- oder 5xx-HTTP-Statuscode zurückgegeben wird. Ich habe die Antworten auf this question referenziert und das SDK so geändert, dass die Fehlermeldung ggf. zurückgegeben werden kann. Hier ist der relevante Teil von 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); 
    }      
} 

Natürlich erfordert dies Änderungen an der aufrufenden Funktion, um die Fehlerreaktion richtig zu interpretieren. Da ich nur die Payment Create-API verwende, habe ich einige Verknüpfungen verwendet, die für die allgemeine Verwendung nicht funktionieren. Die Grundidee ist jedoch, dass ich PaymentError- und Detail-Klassen erstellt und dann die Methoden Payment.Create und PayPalResource.ConfigureAndExecute geändert haben, um ein PaymentError-Objekt aufzufüllen und zurückzugeben.


Drei Jahre später und es gibt einige Verbesserungen in der API-Fehlerbehandlung von PayPal. Wegen einiger anderer Probleme musste ich meine Anwendung neu arbeiten und den vorherigen Code herausreißen. Ich habe festgestellt, dass Sie jetzt nach einer PayPal.Exception.PaymentsException suchen und dann die JSON Response-Zeichenfolge in ein PayPal.Exception.PaymentsError-Objekt deserialisieren können.

Catch ex As PayPal.Exception.PaymentsException 
    Dim tmpPmtErr As PayPal.Exception.PaymentsError = _ 
     JsonConvert.DeserializeObject(Of PayPal.Exception.PaymentsError)(ex.Response) 

Dank @Lance in der anderen Antwort für den Heads-up, um die Ausnahmen näher zu untersuchen. Ich habe versucht, diese Lösung zu verwenden, konnte sie aber nicht funktionieren lassen.

1

@ Jonathan, Die REST-API hat log4net integriert und gibt die vollständige Fehlerantwort in einer Protokolldatei aus, wenn Sie sie eingerichtet haben. Sie müssen diese Konfigurations Abschnitt Ihrer web.config hinzufügen:

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 

und setzen auch die Optionen:

<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> 

Ihr global.asax öffnen und fügen Sie diese in den Application_Start:

log4net.Config.XmlConfigurator.Configure(); 

Jetzt, solange es Schreibrechte auf Ihrem Protokollordner gesetzt sind, dann die PayPal REST S DK wird Fehlermeldungen an die Protokolldatei ausgeben.

+0

Vielen Dank für die Antwort. Das werde ich für zukünftige Anwendungen berücksichtigen. Leider hätte dies in dieser Situation nicht geholfen, da ich im Rahmen der Anwendung die Fehlerantwort zurück brauchte. Die Anwendung war auch Windows Forms, aber ich nehme an, dass ähnliche Änderungen an der app.config vorgenommen werden können, um die gleiche Protokollierung zu ermöglichen. –

+0

Ich stieß auf dieses Problem, als ich versuchte, ein Stück aufzubauen, das mit der PP-API verbunden war, und ich frage mich, ob es eine Möglichkeit gibt, zu bekommen, was gerade eingeloggt ist. Andernfalls, wenn eine Karte abgelehnt wird (z. B. eine ungültige Nummer, eine abgelaufene Karte usw.), sagt uns die 400/Bad-Anfrage nichts darüber, warum sie nicht funktioniert hat, nur, dass sie nicht funktioniert hat. – RubyHaus

+0

@digitall, genau! Deshalb musste ich die Hacks verwenden, die in der ersten Antwort erwähnt wurden. Ich habe nie einen Weg gefunden, dies mit der Stock-API zu tun, und wie Sie erwähnt haben, hilft die Protokollierung nicht viel in der App. –

21

Ich habe heute nur angefangen, mit SDK und API zu spielen und bin sofort auf dieses Problem gestoßen. Ich meine, wenn ich mein eigenes Formular für Zahlungen erstellen möchte, möchte ich das Feedback meiner Benutzer geben, wenn etwas schief gelaufen ist.

In jedem Fall habe ich einige versteckte Informationen in der inneren Ausnahme gefunden. Vielleicht wird das helfen.

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

Die resultierende Antwort:

{"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"} 
+0

wie Sie diesen JSON parsen, um die Nachricht vor dem Benutzer anzuzeigen. –

+0

Leider scheint dies jetzt nicht zu funktionieren. Ab der neuesten Version der API ist "Response" kein Element von ConnectionException. Bei dem Versuch, dieses Problem zu lösen, habe ich jedoch festgestellt, dass es funktioniert, wenn Sie die Pay- mentsException nur direkt abfangen, nicht als InnerException. Ich habe meine Antwort mit einer alternativen Lösung bearbeitet. –

0

Mein Problem war, dass meine total, detail.subtotal und items.price wurden in Werte wie $ 1,000.00 vorbei und es so etwas wie verwenden dezimal so braucht:

total = Regex.Replace(model.OrderTotal, "[^0-9.]", "") 
-1

Wenn Sie eine Globalisierung außerhalb der USA verwenden, müssen Sie Ihre Dezimalstellen in eine InvariantCulture konvertieren:

order.GetTotal().ToString("N2", CultureInfo.InvariantCulture) 
0

die Lösung hier ist die Verbesserung der ... Simply (Importe 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 
0

Alle der oben genannten Lösung nicht wirklich das Problem erfassen ..

Ich lief in einem ähnlichen Problem eine Weile zurück ... nach dem Debuggen meines Codes fand ich heraus, dass die Transaktion, die ich machte, logisch falsch war .. die Zwischensumme war aus $ 0.25 und Paypal-Server sah es und weigerte sich, es zu verarbeiten, und gab mir 400 schlechte Anfrage

0

Das scheint sich geändert zu haben, und während viele dieser Antworten in die richtige Richtung zeigen, hat keiner von ihnen genau für mich funktioniert. Das ist mein Äquivalent der momentan am meisten upvoted Antwort:

catch (PayPal.PaymentsException ex) 
{ 
    context.Response.Write(ex.Response); 
} 

mit der Antwort:

{"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"} 
+0

Vorsicht: Nach dem, was ich kürzlich gesehen habe, scheint es, dass PayPal sich von seiner REST-API entfernt, zumindest für die CC-Verarbeitung. Meine Kunden scheinen an dieser Stelle gemischte Signale zu bekommen. Ich bewege meine Entwicklung woanders hin. –