Hace un tiempo ya había escrito un blog sobre Mercado Pago, pero la lucha continúa y nuevos problemas se presentan. Es por eso que hoy, les traigo este hermoso blog, donde te voy a enseñar a crear un link de pago para generar suscripciones.

El propósito de esto es que prácticamente cualquier persona pueda seguir y entender su contenido, por lo que las explicaciones intentan ser lo mas abarcativas posibles


Requisitos

Para poder seguir con facilidad este tutorial, van a necesitar lo siguiente:

  • Conocimientos de Javascript y Node
  • Tener instalado node
  • Saber usar el comando cd de la terminal
  • Ganas de sufrir
  • Las API keys/tokens de Mercado Pago, que las pueden encontrar acá:

menu


Lo que vamos a hacer

  • Vamos a crear una API en Node, más puntualmente express.
  • En dicha API, vamos a crear una ruta para generar el link de pago de la suscripción
  • Esa ruta va a utilizar un controller y un service, que nos van a permitir conectarnos con la api de mercadopago.

Set Up

  1. Lo primero que vamos a hacer es generar una aplicación de express, para eso ejecutamos el siguiente comando en nuestra terminal:

    npx express-generator MercadoPagoSubscriptions --view=none

    Con esto lo que estamos haciendo es generar una aplicación de express que se va a llamar MercadoPagoSubscriptions

    Es importante saber que para poder utilizar el comando npx express-generator, se necesita tener una versión de node mayor o igual a 8.2.0.

    Para saber qué versión de node tienen pueden ejecutar el comando node -v en la terminal.

  2. Una vez que estemos en la carpeta MercadoPagoSubscriptions (que se acaba de crear) ejecutamos:

    npm install

    Esto va a instalar los node_modules. Dependiendo de su computadora, puede tardar poco o mucho, asi que tengan paciencia.

  3. También tenemos que instalar el sdk de Mercado Pago para node, que lo vamos a utilizar para hacer los request a la API de Mercado Pago

    npm install mercadopago


Service

Una vez que tengamos todo instalado, tenemos que abrir nuestro proyecto en nuestro editor de código preferido.

Lo primero que vamos a hacer es crear el Service.

Para crear el service, vamos a crear dentro de la carpeta raiz de nuestro proyecto, una carpeta que se llame services.

Dentro de esa carpeta vamos a crear un archivo que se llame: SubscriptionService.js

Dentro de dicho archivo vamos a ingresar lo siguiente:

const MercadoPago = require("mercadopago");
//importamos el sdk de mercadopago

class SubscriptionService {
  constructor() {
    MercadoPago.configure({
      client_id: "client_id",
      client_secret: "client_secret"
    });
    
    //configuramos el sdk, dándole nuestro client_id, y client_secret
  }

  async getSubscriptionLink() {
  //creamos el objeto de preferencias
  
    const preference = {
      payer_email: "test@gmail.com",
      //email del usuario comprador
      reason: "prueba de subscripción",
      external_reference: "",
      back_url: "https://www.mipaginaweb.com/gracias",
      //si se completa el pago
      auto_recurring: {
        //objeto para crear la subscripción
        frequency: 1,
        // frecuencia de cobro
        frequency_type: "months",
        //tipo de frecuencia
        //en este ejemplo es 1 vez al mes
        transaction_amount: 100,
        //precio de la suscripción
        currency_id: "ARS"
        //moneda a cobrar
      }
    };

    try {
      const mp = await MercadoPago.preapproval.create(preference);
      //creamos un preapproval (link de pago) con nuestra preferencia
      
      const linkCheckout = mp && mp.response && mp.response.init_point;
      //obtenemos el link de la respuesta

      return linkCheckout;
      //le devolvemos el link al controller
    } catch (err) {
      //en caso de que algo malga sal
      console.log(err);
      return false;
    }
  }
}

module.exports = SubscriptionService;


El service es una clase que todavía no tiene una instancia creada, y que tiene la función getSubscriptionLink(). Esta función lo que hace es crear de acuerdo a los parámetros que nosotros queramos, un link de mercado pago, y como dentro del objeto preference tiene el auto_recurring, va a crear una suscripción.

Hay mil parámetros que le podemos meter adentro de preference, en el pie del blog dejo el link a la documentación.

Ahora bien, este service todavía no hace nada, porque no lo estamos usando en ningún lado. Pasemos a ver el controller para seguir con el tutorial.


Controller

Para crear el controller primero vamos a crear una carpeta en la raiz de nuestro proyecto que se llame controllers.

Dentro de esa carpeta vamos a crear un archivo que se llame SubscriptionController.js

Dentro de dicho archivo vamos a ingresar lo siguiente:

class SubscriptionController {
  constructor(subscriptionService) {
    this.subscriptionService = subscriptionService;
  }

  async getMercadoPagoSubscriptionLink(req, res) {
    //acá hay que realizar las validaciones
    const getLink = await this.subscriptionService.getSubscriptionLink();

    if (getLink) {
      //si existe el link
      res.status(200).json({
        msg: "Link creado correctamente",
        link: getLink
      });
    } else {
      res.status(500).json({
        error: true,
        msg: "Hubo un error al crear el link"
      });
    }
  }
}
module.exports = SubscriptionController;

Lo importante es que el controller recibe como prop en el constructor el service que creamos en el paso anterior, y esto nos va a dejar ejecutar la función getSubscriptionLink() que se encuentra dentro del service.

Ahora bien, este controller, hasta ahora, no hace nada porque no lo estamos ejecutando en ningún lado. Por eso vamos a crear la ruta y crear una instancia de las clases.


Creación de Rutas

Dentro de los archivos de nuestro proyecto, nos vamos a encontrar con uno que se llama app.js, que contiene lo siguiente:

var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");

var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");

var app = express();

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

app.use("/", indexRouter);
app.use("/users", usersRouter);

module.exports = app;

Recomiendo que cambien todo lo que dice var a const.

Ahora bien, estuve todo el tiempo diciendo que ibamos a crear una instancia de nuestro controller y service. Bueno así lo hacemos:

const SubscriptionController = require("./controllers/SubscriptionController");
 //importamos el controller

const SubscriptionService = require("./services/SubscriptionService"); 
//importamos el service

const SubscriptionInstance = new SubscriptionController(new SubscriptionService()); 
// creamos la instancia del controller, y le pasamos una instancia del service 
// como prop para que el controller pueda ejecutar las funciones del service

Lo último que queda por hacer, es crear la ruta, o en otras palabras, el endpoint de nuestra api que va a devolver un json con el link de pago de Mercado Pago

Lo que hacemos es desde nuestro servidor de express(que está declarado por defecto como app), extender un metodo post, para que desde nuestro frontend podamos hacer un request con el método post, mandando información del usuario.

app.post("/subscription/new", (req, res) => 
  SubscriptionInstance.getMercadoPagoSubscription(req, res) 
);

En síntesis nuestro archivo app.js (después de limpiarlo un poco) debería quedar:

const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");

const app = express();

const SubscriptionController = require("./controllers/SubscriptionController");
//importamos el controller

const SubscriptionService = require("./services/SubscriptionService");

const SubscriptionInstance = new SubscriptionController(
  new SubscriptionService()
);

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

app.post("/subscription/new", (req, res) =>
  SubscriptionInstance.getMercadoPagoSubscriptionLink(req, res)
);

module.exports = app;



Últimos pasos

Con esto, terminamos todo el tutorial. Lo que quedaría pendiente es:

  • Mandar información desde un frontend con información customizada del usuario
  • En el controller, en la funcion getMercadoPagoSubscriptionLink(), hacer las validaciones pertinentes
  • Crear un frontend que ejecute un request POST hacia esta API y redirija a el link que generamos nosotros

Cosas que se pueden mejorar

  • Ponerle una fecha de finalización a la suscripción
  • Hacer que la suscripción tome validez a partir de una fecha determinada
  • La interfaz de pago de este flujo, que parece del año 2000

Recursos


Agradecimientos

  • Primero que nada a CourseIt (vengan a hacer mi cursito de git que está bueno) por darme el mejor entorno de aprendizaje.

  • A Mercado Pago, por no facilitar el acceso a su documentación, y tener que buscar soluciones en la deep web.

  • Y por sobre todo, a todes les que se tomaron el tiempo de leer esto!

Si te quedaron dudas escribime a mi twitter

Si te gustó, comprame un cafecito (aunque siendo sincero lo gaste en cerveza)


TL;DR