2013-03-22 36 views
12

Sto lavorando nella sandbox e utilizzo il metodo REST .net SDK di PayPal Payment.Creare con un oggetto CreditCard. Quando tutti i parametri sono validi e si utilizza il numero CC di prova da https://developer.paypal.com/webapps/developer/docs/integration/direct/accept-credit-cards/, l'oggetto Pagamento viene restituito da tale metodo e tutto va bene.API REST di PayPal .net SDK - 400 richieste errate

Tuttavia, quando un parametro non è valido, ad esempio una data di scadenza passata o un numero CC non riconosciuto dalla sandbox, l'oggetto Pagamento non viene restituito. Invece il metodo genera un'eccezione: "Eccezione in HttpConnection Execute: risposta HTTP non valida Il server remoto ha restituito un errore: (400) Richiesta errata", ma senza ulteriori spiegazioni.

Quando eseguo la stessa richiesta in cURL, oltre alla "400 Richiesta non valida", ottengo una risposta JSON. Ciò include più messaggi utili come "VALIDATION_ERROR" e "Scadenza non valida (non può essere nel passato)".

La mia domanda: c'è un modo per recuperare questi messaggi dall'SDK?

Quello che ho provato:

  • PayPal docs: https://developer.paypal.com/webapps/developer/docs/api/#errors Questo documento afferma che, nel caso di un errore, tornano i dettagli nel corpo della risposta. Sfortunatamente, non ha la minima idea se questi siano accessibili dall'SDK.
  • Varie ricerche Google e SO.
  • Il codice di esempio PizzaApp fornito con SDK non ha nulla a che fare con la gestione delle eccezioni o ulteriori informazioni su questo problema.
  • Vedo un oggetto PayPalException nell'SDK, ma non ho trovato nulla che indichi come dovrebbe essere usato o se è anche rilevante per questo problema.

Tutto l'aiuto è molto apprezzato.

risposta

6

Poiché nessuno sembra conoscere la risposta a questo, ho scavato nel codice sorgente di .NET SDK di PayPal per REST API. Da questa recensione, sembra che, a partire dalla versione corrente, non sia prevista la restituzione dei messaggi di errore quando il server restituisce un codice di stato HTTP 4xx o 5xx. Ho fatto riferimento alle risposte a this question e ho modificato l'SDK per consentire di restituire la risposta all'errore quando applicabile. Ecco la parte rilevante di 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); 
    }      
} 

Ovviamente, ciò richiede modifiche alla funzione di chiamata per interpretare correttamente la risposta all'errore. Dal momento che sto utilizzando solo l'API di pagamento creato, ho preso alcune scorciatoie che non avrebbero funzionato per uso generale. Tuttavia, l'idea di base è che ho creato le classi PaymentError e Detail, quindi ho modificato i metodi Payment.Create e PayPalResource.ConfigureAndExecute per popolare e restituire un oggetto PaymentError.


Tre anni più tardi e c'è un miglioramento nella gestione della risposta all'errore API di PayPal. A causa di altri problemi, ho dovuto rielaborare la mia applicazione e strappare il codice precedente. Ho scoperto che ora puoi intercettare PayPal.Exception.PaymentsException, quindi deserializzare la stringa di risposta JSON in un oggetto PayPal.Exception.PaymentsError.

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

Grazie a @lance nell'altra risposta per l'heads-up per esaminare le eccezioni più da vicino. Ho tentato di utilizzare questa soluzione, ma non riuscivo a farlo funzionare.

1

@Jonathan, l'API REST ha integrato log4net e restituirà l'intera risposta di errore a un file di registro se lo si imposta. È necessario aggiungere questa sezione di configurazione al vostro web.config:

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

e anche impostare le opzioni:

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

aprire il tuo global.asax e aggiungere questo nella Application_Start:

Ora, finché ci sono i permessi di scrittura impostati sulla cartella del registro, quindi il PayPal REST S DK sputerà i messaggi di errore nel file di registro.

+0

Grazie per la risposta. Lo terrò a mente per le applicazioni future. Sfortunatamente, questo non avrebbe aiutato in questa situazione, poiché avevo bisogno che la risposta all'errore tornasse nell'ambito dell'applicazione. Inoltre, l'applicazione era Windows Form, ma presumo che potrebbero essere apportate modifiche simili a app.config per abilitare la stessa registrazione. –

+0

Stavo correndo questo problema mentre cercavo di creare un pezzo che si collegasse all'API di PP e mi chiedo se c'è un modo per ottenere anche ciò che è registrato per essere restituito? Altrimenti quando una carta viene rifiutata (come un numero non valido, una carta scaduta, ecc.) La 400/Richiesta non ci dice nulla sul motivo per cui non ha funzionato, solo che non lo ha fatto. – RubyHaus

+0

@digitall, esattamente! Ecco perché ho dovuto usare gli hack menzionati nella prima risposta. Non ho mai trovato il modo di farlo con l'API di riserva e, come hai detto, il logging non aiuta molto dall'interno dell'app. –

21

Ho iniziato a utilizzare l'SDK e l'API solo oggi e ho riscontrato subito questo problema. Voglio dire, se ho intenzione di creare il mio modulo per gestire i pagamenti, vorrei dare il feedback dei miei utenti se qualcosa è andato storto.

In ogni caso, ho trovato alcune informazioni nascoste nell'eccezione interna. Forse questo aiuterà.

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

La risposta risultante:

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

come analizzare questo json per mostrare il messaggio di fronte all'utente. –

+0

Purtroppo, questo non sembra funzionare ora. A partire dall'ultima versione dell'API, "Risposta" non è un elemento di ConnectionException. Tuttavia, nel tentativo di provare questo, ho scoperto che funziona solo se intrappoli direttamente PaymentsException, non come InnerException. Ho modificato la mia risposta con una soluzione alternativa. –

0

Il mio problema era che la mia total, detail.subtotal, e items.price passavano in valori come $ 1.000,00 e ha bisogno decimale in modo da usare qualcosa come:

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

Se si utilizza una globalizzazione al di fuori degli Stati Uniti, è necessario convertire i decimali in InvariantCulture:

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

Migliorare la soluzione qui è ... Semplicemente (Importazioni 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

tutta la soluzione al di sopra di davvero non cogliere il problema ..

mi sono imbattuto in una simile problema un po 'indietro .. dopo il debug del mio codice ho scoperto che la transazione che stavo facendo era logicamente sbagliata .. il subtotale era spento da $ 0,25 e il server paypal l'ha visto e si è rifiutato di elaborarlo, e mi ha dato 400 cattiva richiesta

0

Questo sembra essere cambiato, e mentre molte di queste risposte puntano nella giusta direzione, nessuna ha funzionato esattamente per me. Questo è il mio equivalente della risposta attualmente più upvoted:

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

con la risposta:

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

Attenzione: da quello che ho visto di recente, sembra che PayPal stia abbandonando la propria API REST, almeno per l'elaborazione CC. I miei clienti sembrano ricevere segnali contrastanti a questo punto. Sto spostando il mio sviluppo altrove. –

Problemi correlati