Integrando Mercadopago en una single page app (SPA)
La documentación es pésima! – Un desarrollador al integrar MercadoPago
Este año hice una implementación de Mercadopago con React. A pesar de haber participado en otras integraciones (Stripe, Paypal y Webpay), me encontré con varias sorpresas y trabas en el camino.
Una de ellas es la documentación. Si bien no es tan mala (hay peores), carece de ejemplos. Me da la impresión de que la hicieron entre varias personas al estilo “cada uno hace su parte”.
Este post es para ayudarte a entender qué es lo que tienes que hacer al integrarte con MercadoPago, para que así puedas aplicarlo a cualquier frontend (React, Angular, Vue, etc) y a cualquier backend.
En este post no encontrarás un paso a paso, ni verás mucho código de ejemplo. No quiero que copies y pegues código. Quiero que entiendas qué es lo que hay que hacer, para que puedas ajustar y aplicarlo en tu contexto.
La forma más rápida de integrarse con Mercadopago
Lo primero que tienes que saber es que existen muchas formas de integrarse con MercadoPago, las cuales aparecen en su página web:
Dentro de las opciones para plataformas web, la más fácil es Checkout Pro. Es la más fácil porque MercadoPago te pasa una librería que incluyes en tu HTML y que tiene listo el frontend de la “pasarela de pago” (donde tu usuario realiza el pago).
Si te ingregaras con Checkout API, tendrías que hacer tu mismo el frontend (como lo hace Sony Chile o PedidosYa).
Y como queremos desarrollar lo más rápido nuestro producto, la opción que te recomiendo es Checkout Pro.
Ahora bien, ¿qué tienes que hacer para integrarte con Checkout Pro?
Flujo de integración con Checkout Pro de MercadoPago
Antes de entrar en el flujo de integración con MercadoPago, quiero hablarte del flujo general de una aplicación web que vende cosas.
El flujo general de venta en plataformas web es así:
- El usuario navega por el sitio y decide comprar un producto.
- El usuario paga el producto.
- El servidor recibe una orden de pago exitosa, y luego “entrega” el producto.
Esto es una simplificación, ya que como has notado:
- Hay aplicaciones donde seleccionar 1 o más productos y los agregas a un “carrito de compra”
- La “entrega” del producto depende mucho de lo que estés vendiendo. Si vendes productos físicos, “entregar” significa coordinar toda la entrega del producto. Si vendes un producto digital como e-book, entregar puede ser enviar el e-book por correo. Si vendes moneda virtual (como en un juego), entregar significa cargarle la moneda a la cuenta del usuario.
Eso tienes que tenerlo en cuenta, porque MercadoPago te ayuda solo en el paso 2, cobrarle al usuario. Si haces carrito de compra, tú tienes que programar toda la lógica del carrito de compra.
Dicho esto, el proceso de pago con Checkout Pro es así:
- Muestras en la página el botón de pago de MP, para lo cual tienes que insertar un script en tu HTML.
- Cuando el usuario pague, MP notificará a tu servidor.
Suena fácil… pero no lo es. El diablo está en los detalles.
A continuación te explicaré lo que tienes que hacer para lograr estas 2 cosas.
Parte 1: ¿cómo mostrar el botón de pago?
Para mostrar el botón de pago, debes leer la sección “Integra Checkout Pro”. Todo se resume a:
- Crea una preferencia en MP
- Pega un código en tu página HTML
Antes de continuar… ¿qué rayos es una preferencia? En el Glosario dice que una preferencia es *la información del producto o servicio que se quiere ofrecer. *Mi modelo mental de la preferencia es una orden de compra, que tiene información de todos los productos que estoy comprando.
Ahora sí. ¿Cómo implementamos los 2 pasos en una SPA (React) con un backend propio? ¿Dónde va cada cosa?
Te voy a explicar con palabras el flujo exacto que debes implementar para mostrar el botón de pago. Son 5 pasos:
- Antes de querer mostrar el botón de pago (por ejemplo, al mostrar el detalle de producto), tu SPA (React, Vue, etc) debe decirle a tu backend: “Hey, un usuario quiere comprar este producto”
- Tu backend, procesa este pedido y luego le dice a MercadoPago: “Hey, alguien quiere comprar este producto. Te mando los detalles”
- MP le responde a tu backend: “Listo. Toma este ID, con eso tu cliente podrá pagar”
- Luego tu backend le responde a tu frontend: “Todo ok. Toma este ID para que el usuario pague”
- Ahora tu frontend toma el ID, e inserta un código en la página que hará que aparezca un botón de pago.
En otras palabras, tu frontend hace un request al backend solicitando el ID de la preferencia (requerido para mostrar el botón de pago de MP), y tu backend hace un request a MercadoPago para crear la preferencia, y así responder el request con el ID.
Al comienzo dije que no mostraría código, pero si quieres inspiración:
- Puedes ver un ejemplo en React del punto 1 y 5 aquí (es parecido a lo que hice en mi proyecto)
- Un ejemplo en node.js para el punto 2 al 4 aquí (basado en “Genera tu preferencia” de la documentación de MP)
Nota: puede que el código de ejemplo contenga errores, ya que los hice a pulso sin verificarlos. Lo importante es la idea.
Con todo lo anterior ya puedes mostrar el botón de pago. Por ejemplo, en la app donde lo integré se terminó viendo así:
Parte 2: ¿cómo procesar el pago?
La parte anterior te dije cómo mostrar la pasarela de pago para poder recibir pagos.
Como mencioné al comienzo, luego de que te paguen, querrás entregar el producto de alguna forma (sea lo que sea que “entregar” signifique en tu contexto).
Para esto, MercadoPago puede notificarle a tu servidor cuando hay cambios en el estado de los pagos. Es decir, MercadoPago le dirá a tu backend “hey!, un pibe pagó esto”
La documentación de esto se encuentra en “Integración Avanzada” (no apesta tanto como otras secciones).
Lo que te dice esa página es que tienes que agregar información adicional cuando creas tu preferencia (punto 2 de la sección anterior). Debes agregar al menos lo siguiente:
- Enviar el parámetro
notification_url
, el cual debe ser un endpoint de tu backend para recibir notificaciones de MercadoPago. - Enviar el parámetro
external_reference
cuyo valor sea un ID de tu sistema que represente la orden de compra. Esto será útil para cruzar información entre tu sistema y MercadoPago.
El código actualizado (con IPN) de ejemplo del backend lo puedes ver aquí.
Nota: El listado completo de parámetros de una preferencia lo puedes ver aquí.
Hasta aquí ya deberías tener una integración funcional:
- Puedes mostrar el botón de pago en tu app en React gracias al
preferenceId
obtenido del backend. - El backend le informó a MercadoPago el producto que está incluido en la orden, una URL de notificación para saber que pasa con el pago y además le indicó un ID que representa a la orden en tu BD.
- Cuando el usuario pague, MercadoPago te enviará un request al endpoint que le dijiste. Tu backend procesará la información, verá que todo esté bien (el pago fue por el monto que debía ser, el pago fue aprobado, etc). Y finalmente ejecutará la entrega del producto.
Últimos detalles
La preferencia recibe un parámetro llamado back_urls
donde puedes indicar URL de tu frontend para mostrar cuando el pago sea un éxito, fracaso o esté pendiente.
Otra forma de redireccionar luego del pago es mediante del formulario donde inyectas el botón de pago. Por ejemplo, lo que yo hago es en el action
de ese form me redirija a /orders/:id
(del frontend) donde tengo más control para mostrar el estado de una orden particular. El código exacto de mi implementación en React lo puedes ver aquí.
Links de interés
- Documentación de Checkout Pro: https://www.mercadopago.cl/developers/es/guides/online-payments/checkout-pro/integration
- Crear preferencia (MercadoPago API): https://www.mercadopago.cl/developers/es/reference/preferences/_checkout_preferences/post/
- Integración avanzada: https://www.mercadopago.cl/developers/es/guides/online-payments/checkout-pro/advanced-integration
- Documentación del SDK de Node: https://www.mercadopago.cl/developers/es/guides/sdks/official/nodejs/
- Código de ejemplo de botón de pago en React: https://gist.github.com/muZk/e11931b3df6aab7c7dd6dd53058c3e41
- Código de ejemplo de creación de preferencia en node.js: https://gist.github.com/muZk/717ff8ec882dd701f1bec2e9ac2c6b62
- Código de ejemplo de integración avanzada en node.js: https://gist.github.com/muZk/2453663c05e15884ac08cba39747e8ab