Integrazione PayPal Parte 3 Webhook PayPal

Cosa starai creando

Un Webhook è un callback HTTP che si verifica quando succede qualcosa; un semplice sistema di notifica degli eventi tramite HTTP POST che consente agli sviluppatori di accedere facilmente alle notifiche delle attività di pagamento, come l'aggiornamento dello stato dei pagamenti o addebiti ricorrenti. È possibile eseguire azioni sul proprio back-end dopo l'elaborazione di ciascuna notifica, ad esempio:

  • Invia una conferma d'acquisto al tuo cliente.
  • Abilita il download di media digitali.
  • Emetti un rimborso.
  • Tieni traccia di quali abbonamenti sono attivi.

Per creare un Webhook, accedi a PayPal Cruscotto, e fare clic su Le mie app e credenziali. Quindi seleziona l'app in cui desideri configurare i Webhook.

Puoi vedere i dettagli della tua applicazione. Notare in alto a destra che ci sono due pulsanti (Sandbox, Live), che userò sandbox durante questo tutorial, ma è necessario configurare le impostazioni Live prima di andare in diretta. Per configurare Webhooks per questa app, fare clic su Aggiungi Webhook come mostrato nello screenshot:

Seleziona i tipi di eventi che ti interessano per ricevere una notifica e inserisci l'URL a cui verranno inviati i Webhook (deve essere HTTPS). Per gestire le chiamate Webhook, aggiungerò un nuovo metodo di azione a HomeController chiamato "Webhook":

public IActionResult Webhook () // TODO: handle chiamata Webhook

Quindi l'URL Webhook in questo caso sarà: https://pedroalonso.localtunnel.me/home/webhook. Spiegherò la parte "localtunnel" nella prossima sezione.

Quando salvi il Webhook, vedrai questa schermata di conferma:

Ora che il Webhook è configurato, puoi vedere nel menu a sinistra sotto "Webhooks Simulator", qui puoi inviare gli eventi webhook "test" al tuo URL per verificare che il tuo codice funzioni. Inoltre, in "Webhooks Events" è possibile visualizzare tutti gli eventi inviati da PayPal per questa applicazione. Puoi verificare di gestire correttamente gli eventi e inviarli nuovamente se desideri eseguire ulteriori test.

Per vedere come funzionano i Webhook, ho eseguito il progetto che abbiamo creato nel tutorial precedente e ho creato un 'autorizzazione di pagamento e acquisizione in seguito', in modo che PayPal inviasse l'evento. Dopo aver eseguito l'esempio, ho fatto clic su "Webhooks Event" e posso vedere che l'evento è stato inviato:

Come puoi vedere, a destra c'è un inviare di nuovo pulsante se si desidera eseguire il debug del codice e vedere come implementare correttamente il gestore. Inoltre, se fai clic sull'evento, puoi vedere tutti i dettagli:

Questo è il JSON completo per l'evento Webhook:

"id": "WH-9U51749144910293K-8LX80763BC1567402", "create_time": "2016-01-19T17: 50: 30Z", "resource_type": "sale", "event_type": "PAYMENT.SALE.COMPLETED", " riepilogo ":" Pagamento completato per $ 100,0 USD "," risorsa ": " importo ": " totale ":" 100,00 "," valuta ":" USD "," dettagli ": " subtotale ":" 100,00 " , "IVA": "15.00", "spedizione": "10.00", "id": "73G8209522783053E", "parent_payment": "PAY-7MB27930V5981832YK2PHN7Q", "update_time": "2016-01-19T17: 49: 05Z "," create_time ":" 2016-01-19T17: 49: 05Z "," payment_mode ":" INSTANT_TRANSFER "," stato ":" completato "," collegamenti ": [" href ":" https: // api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E "," rel ":" self "," method ":" GET ", " href ":" https: //api.sandbox.paypal. it / v1 / payments / sale / 73G8209522783053E / refund "," rel ":" rimborso "," metodo ":" POST ", " href ":" https://api.sandbox.paypal.com/v1/ pagamenti / pagamento / PAY-7MB27930V5981832YK2PHN7Q "," rel ":" parent_payment "," metodo ":" GET "]," protection_eligibility_type ":" ITEM_NOT_RECEIVED_ELIGIBLE, UNAUTHORIZED_PAYMENT_ELIGIBLE "," transaction_fee ": " value ":" 3.20 "," currency ":" USD "," protection_eligibility ":" ELIGIBLE "," status ":" PENDING "," transmissions ": [" webhook_url ":" https://pedroalonso.localtunnel.me/home/webhook "," response_headers ": " Data ":" Mer, 20 Jan 2016 12:53:51 GMT "," Content-Length ":" 53 " , "HTTP / 1.1 502 Bad Gateway": "", "SERVER_INFO": "", "Connessione": "keep-alive", "Server": "nginx / 1.7.8", "transmission_id": "218dc9c0- bed5-11e5-927f-6b62a8a99ac4 "," status ":" PENDING "," timestamp ":" 2016-01-19T17: 50: 30Z "]," link ": [" href ":" https: // api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402 "," rel ":" self "," metodo ":" GET "," encType ":" application / json ", "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402/resend", "rel": "reinvia", "metodo": "POST" , "encType": "application / json"]

Come puoi vedere nell'immagine, i dettagli dell'evento sono codificati in JSON e vengono inviati come corpo della richiesta al tuo gestore di URL Webhook. Inoltre, ci sono diverse proprietà importanti che dobbiamo usare nel nostro gestore:

  • id: Questo è l'id dell'evento webhook e dobbiamo inviare questo parametro a PayPal se vogliamo recuperare uno specifico evento webhook.
  • Tipo di evento: Questo è usato per conoscere il tipo di evento che stiamo ricevendo poiché probabilmente abbiamo bisogno di elaborare diversi tipi di eventi in modi diversi.
  • resource.parent_payment: Questo è l'ID del pagamento a cui questo evento è correlato. Probabilmente abbiamo questo ID memorizzato in un database, e possiamo inviare una email al nostro cliente o spedire la merce acquistata dal cliente.

Sulla base della spiegazione precedente, questo è il codice del controller di azioni per elaborare il Webhook:

public IActionResult Webhook () // L'oggetto APIContext può contenere un override facoltativo per il certificato attendibile. var apiContext = PayPalConfiguration.GetAPIContext (); // Ottieni le intestazioni della richiesta ricevuta var requestheaders = HttpContext.Request.Headers; // Ottieni il corpo var della richiesta ricevuta requestBody = string.Empty; using (var reader = new System.IO.StreamReader (HttpContext.Request.Body)) requestBody = reader.ReadToEnd ();  dynamic jsonBody = JObject.Parse (requestBody); string webhookId = jsonBody.id; var ev = WebhookEvent.Get (apiContext, webhookId); // Abbiamo tutte le informazioni necessarie per l'SDK, quindi esegui la convalida. // Nota: almeno sull'ambiente Sandbox restituisce false. // var isValid = WebhookEvent.ValidateReceivedEvent (apiContext, ToNameValueCollection (requestheaders), requestBody, webhookId); switch (ev.event_type) case "PAYMENT.CAPTURE.COMPLETED": // Gestisce l'interruzione del pagamento completata; caso "PAYMENT.CAPTURE.DENIED": // Gestire l'interruzione del pagamento negata; // Gestire altri webhook predefiniti: break;  restituisce nuovo HttpStatusCodeResult (200); 

Alcune cose da spiegare dalla funzione precedente. Dalle righe 10-16, sto solo leggendo il corpo della richiesta e analizzando l'oggetto JSON in un oggetto C # dinamico. Alla riga 18, che è facoltativa, sto chiamando l'API di PayPal con l'ID evento per ottenere i dettagli completi dell'evento. Questo è fatto per sicurezza per verificare che sto usando un oggetto PayPal valido. Sulla linea 24 ho creato un interruttore per valutare i tipi di Webhook che voglio elaborare e scrivere il codice personalizzato secondo necessità. 

Come puoi anche vedere, la riga 22 è commentata. Apparentemente quel metodo convalida che il certificato SSL della Richiesta è valido e appartiene a PayPal, ma non funziona in modalità Sandbox. Potrebbe funzionare in Live, ma non mi piace avere il codice in Live che non è testato, specialmente se si tratta di un Payment Gateway, quindi ho optato per rimuoverlo e utilizzare un approccio diverso. Se si utilizza la versione PHP della libreria dell'SDK PayPal, tenere presente che la funzione 'ValidateReceivedEvent' non esiste nemmeno.

Test di Webhook: Tunnel sicuro

Come hai visto in precedenza, per testare Webhooks, dobbiamo configurare un URL pubblico che PayPal possa utilizzare per inviare gli eventi. Se stiamo lavorando localmente, normalmente sviluppiamo usando 'localhost', quindi sarebbe un piccolo problema. Per risolvere ciò, dobbiamo configurare un tunnel sicuro sul nostro computer locale. 

Localtunnel è un piccolo software che crea un tunnel sicuro tra la tua macchina locale e un dominio accessibile pubblicamente. È utile per testare Webhooks, ma puoi anche usarlo per condividere URL live per le applicazioni Web in esecuzione sul tuo computer di sviluppo ai fini di test, feedback o altre attività.

Devi avere Node.js per poter installare localtunnel. Quindi apri semplicemente una console o un terminale ed esegui:

$ npm install -g localtunnel

Per creare un tunnel, esegui:

$ lt --port 5000 - pedroalonso sottomondo

Questo mapperà l'URL "https://pedroalonso.localtunnel.me" a "localhost: 5000". Se esegui il tuo progetto su IIS Express, probabilmente utilizzerai una porta diversa, quindi dovrai tenerne conto nel comando.

Dopo aver configurato localtunnel e avviato il nostro progetto, ho aggiunto un punto di interruzione in Visual Studio per valutare i dati che sto ottenendo. Come puoi vedere in questo screenshot, ho mappato l'oggetto evento JSON a un oggetto dinamico C #.

Recuperando l'evento dall'API di PayPal utilizzando l'ID dell'evento, riceviamo anche i dettagli dell'evento, come puoi vedere qui:

Conclusione

I Webhook stanno diventando un modo standard per l'API REST per notificare le applicazioni sugli eventi. Come puoi vedere, sono abbastanza facili da gestire e vengono utilizzati da molte aziende come Stripe, SendGrid, MailChimp, ecc. PayPal utilizzava la Notifica immediata dei pagamenti, ed è ancora in uso, ma consigliano di implementare Webhook ogni volta che è possibile..  

Penso che sarebbe davvero interessante se anche altre applicazioni consumer offrissero Webhooks. La possibilità di avviare un processo basato su un evento in un'applicazione separata è estremamente utile e offre uno sguardo al futuro del web in tempo reale.