Integración de PayPal Parte 3 Webhooks de PayPal

Lo que vas a crear

Un Webhook es una devolución de llamada HTTP que ocurre cuando algo sucede; un simple sistema de notificación de eventos a través de HTTP POST que permite a los desarrolladores acceder fácilmente a notificaciones de actividades de pago, como la actualización del estado de pago o cargos recurrentes. Puede realizar acciones en su back-end después de procesar cada notificación, como:

  • Envíe por correo electrónico una confirmación de compra a su cliente.
  • Habilitar la descarga de medios digitales.
  • Emitir un reembolso.
  • Mantenga un registro de qué suscripciones están activas.

Para crear un webhook, navegue hasta PayPal. Tablero, y haga clic en Mis aplicaciones y credenciales. A continuación, seleccione la aplicación en la que desea configurar Webhooks.

Puedes ver los detalles de tu aplicación. Observe en la parte superior derecha que hay dos botones (Sandbox, Live), usaré Salvadera durante este tutorial, pero necesita configurar sus ajustes de Live antes de ir a Live. Para configurar Webhooks para esta aplicación, haga clic en Añadir Webhook como se muestra en la captura de pantalla:

Seleccione los tipos de evento en los que está interesado recibir notificaciones e ingrese la URL a la que se enviarán los Webhooks (tiene que ser HTTPS). Para manejar las llamadas de Webhook, agregaré un nuevo método de acción al HomeController llamado 'Webhook':

IActionResult Webhook público () // TODO: Manejar llamada Webhook

Entonces, la URL del webhook en este caso será: https://pedroalonso.localtunnel.me/home/webhook. Explicaré la parte de 'túnel local' en la siguiente sección.

Cuando guarde el Webhook, verá esta pantalla de confirmación:

Ahora que el Webhook está configurado, puede ver en el menú de la izquierda debajo de 'Webhooks Simulator', aquí puede enviar eventos de 'prueba' webhook a su URL para comprobar que su código funciona. Además, en "Eventos de Webhooks" puede ver todos los eventos que PayPal envió para esta aplicación. Puede verificar que está manejando los eventos correctamente y reenviarlos si desea realizar más pruebas.

Para ver cómo funcionan los Webhooks, ejecuté el proyecto que creamos en el tutorial anterior y creé 'Autorizar el pago y la captura más tarde', para que PayPal enviara el evento. Después de ejecutar el ejemplo, hice clic en 'Evento de Webhooks' y puedo ver que el evento ha sido enviado:

Como puedes ver, a la derecha hay una Reenviar abotone si desea depurar su código y ver cómo implementar correctamente el controlador. Además, si haces clic en el evento, puedes ver todos los detalles:

Este es el JSON completo para el evento Webhook:

"id": "WH-9U51749144910293K-8LX80763BC1567402", "create_time": "2016-01-19T17: 50: 30Z", "resource_type": "sale", "event_type": "PAYMENT.SPLE.COMPLETED", " resumen ":" Pago realizado por $ 100.0 USD "," recurso ": " monto ": " total ":" 100.00 "," moneda ":" USD "," detalles ": " subtotal ":" 100.00 " , "tax": "15.00", "shipping": "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 "," state ":" completed "," links ": [" href ":" https: // api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E "," rel ":" self "," method ":" GET ", " href ":" https: //api.sandbox.paypal. com / v1 / payment / sale / 73G8209522783053E / refund "," rel ":" refund "," method ":" POST ", " href ":" https://api.sandbox.paypal.com/v1/ pagos / pago / PAY-7MB27930V5981832YK2PHN7Q "," rel ":" parent_payment "," method ":" 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 ": " Date ":" Wed, 20 Jan 2016 12:53:51 GMT "," Content-Length ":" 53 " , "HTTP / 1.1 502 Bad Gateway": "," SERVER_INFO ":" "," Connection ":" keep-alive "," Server ":" nginx / 1.7.8 "," transmission_id ":" 218dc9c0- bed5-11e5-927f-6b62a8a99ac4 "," status ":" PENDING "," timestamp ":" 2016-01-19T17: 50: 30Z "]," links ": [" href ":" https: // api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402 "," rel ":" self "," method ":" GET "," encType ":" application / json ", "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402/resend", "rel": "reenviar", "method": "POST" , "encType": "application / json"]

Como puede ver en la imagen, los detalles del evento están codificados en JSON y se envían como el cuerpo de la solicitud a su controlador de URL Webhook. Además, hay varias propiedades importantes que debemos usar en nuestro controlador:

  • carné de identidad: Este es el id del evento webhook, y debemos enviar este parámetro a PayPal si queremos recuperar un evento específico de webhook.
  • tipo de evento: Esto se utiliza para conocer el tipo de evento que estamos recibiendo, ya que probablemente necesitamos procesar diferentes tipos de eventos de diferentes maneras.
  • resource.parent_payment: Este es el id del pago con el que está relacionado este evento. Posiblemente tengamos esta identificación almacenada en una base de datos, y podemos enviar un correo electrónico a nuestro cliente o enviar los bienes comprados por el cliente.

De acuerdo con la explicación anterior, este es el código del controlador de acción para procesar el Webhook:

public IActionResult Webhook () // El objeto APIContext puede contener una anulación opcional para el certificado de confianza. var apiContext = PayPalConfiguration.GetAPIContext (); // Obtenga los encabezados de la solicitud recibida var requestheaders = HttpContext.Request.Headers; // Obtener el cuerpo de la solicitud recibida var requestBody = string.Empty; utilizando (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); // Tenemos toda la información que necesita el SDK, así que realice la validación. // Nota: al menos en el entorno de Sandbox esto devuelve falso. // var isValid = WebhookEvent.ValidateReceivedEvent (apiContext, ToNameValueCollection (requestheaders), requestBody, webhookId); switch (ev.event_type) case "PAYMENT.CAPTURE.COMPLETED": // Manejar el pago completado; caso "PAYMENT.CAPTURE.DENIED": // Manejar el pago rechazado; // Manejar otros webhooks por defecto: break;  devolver nuevo HttpStatusCodeResult (200); 

Algunas cosas para explicar de la función anterior. Desde las líneas 10-16, solo estoy leyendo el cuerpo de la solicitud y analizando el objeto JSON a un objeto C # dinámico. En la línea 18, que es opcional, estoy llamando a la API de PayPal con el Id. Del evento para obtener todos los detalles del evento. Esto se hace por seguridad para verificar que estoy usando un objeto de PayPal válido. En la línea 24, he creado un interruptor para evaluar los tipos de Webhooks que quiero procesar y escribir el código personalizado según sea necesario. 

Como también se puede ver, la línea 22 está comentada. Aparentemente ese método valida que el certificado SSL de la Solicitud sea válido y pertenezca a PayPal, pero no funciona en el modo Sandbox. Puede funcionar en Live, pero no me gusta tener un código en Live que no se haya probado, especialmente si se trata de una pasarela de pago, por lo que opté por eliminar eso y utilizar un enfoque diferente. Si usa la versión PHP de la biblioteca de PayPal SDK, tenga en cuenta que la función 'ValidateReceivedEvent' ni siquiera existe.

Prueba de webhooks: túnel seguro

Como ha visto anteriormente, para probar Webhooks, necesitamos configurar una URL pública que PayPal pueda usar para enviar los eventos. Si estamos trabajando localmente, normalmente desarrollamos el uso de 'localhost', por lo que sería un pequeño problema. Para resolverlo, necesitamos configurar un túnel seguro para nuestra computadora local. 

Localtunnel es una pequeña pieza de software que crea un túnel seguro entre su máquina local y un dominio de acceso público. Es útil para probar Webhooks, pero también puede usarlo para compartir URL en vivo a aplicaciones web que se ejecutan en su máquina de desarrollo con el fin de realizar pruebas, comentarios u otras tareas..

Necesitas tener Node.js para poder instalar localtunnel. Luego simplemente abra una consola o terminal, y ejecute:

$ npm install -g localtunnel

Para crear un túnel, ejecute:

$ lt --port 5000 --subdominio pedroalonso

Eso asignará la URL 'https://pedroalonso.localtunnel.me' a 'localhost: 5000'. Si ejecuta su proyecto en IIS Express, probablemente use un puerto diferente, por lo que deberá reflejarlo en su comando.

Después de configurar localtunnel y nuestro proyecto se está ejecutando, he agregado un punto de interrupción en Visual Studio para evaluar los datos que estoy obteniendo. Como puede ver en esta captura de pantalla, asigné el objeto de evento JSON a un objeto dinámico de C #.

Al recuperar el evento de la API de PayPal utilizando el ID del evento, también obtenemos los detalles del evento, como puede ver aquí:

Conclusión

Los webhooks se están convirtiendo en una forma estándar para que la API REST notifique a las aplicaciones sobre los eventos. Como puede ver, son bastante fáciles de manejar y son utilizadas por muchas compañías como Stripe, SendGrid, MailChimp, etc. PayPal solía tener una Notificación de pago instantánea, y todavía está en uso, pero recomiendan la implementación de Webhooks siempre que sea posible.  

Creo que sería realmente interesante si más aplicaciones para el consumidor también ofrecieran Webhooks. La capacidad de iniciar un proceso basado en un evento en una aplicación separada es extremadamente útil y ofrece una visión del futuro de la web en tiempo real..