¿Cómo integrar Mercado Pago 与您的网络吗?需要注意的事项 建立规则 创建控制器 创建服务创建

2025-05-25

¿Cómo integrar Mercado Pago 与您的网络吗?

必要的知识

我们很努力

我们采用设置

道路的创造

创建控制器

服务创造

本周,我将提交一份与Mercado Pago 网上结帐相结合的认证“考试” (de acá en más MP,请让我通过 cansar de escribirlo)。

最后,您可以在CourseIt上集成 MP (更多返工),以获得更多体验。

我遇到了这样的问题,遇到了各种各样的问题,在市场文件中,我发现很多问题都没有解决。 (这是使用 MP avisen 沙箱的问题!)

因此,该文章的目的是与类似的角色的意图

这篇文章的主题是实践中的角色,以确保内容和内容,以解释可能的阿巴卡蒂瓦意图


必要的知识

想要了解简单的教程,需要注意以下几点:

  1. Javascript 知识
  2. 已安装节点
  3. cd终端突击队使用军刀
  4. 学会了!
  5. MP 的 API 密钥/令牌,与此相关

菜单


我们很努力

  1. Vamos 可以在 Node 上创建API,更快捷
  2. 在 API 中,您可以创建一个通用的 pago 链接,也可以通过 MP nos mande ( webhooks ) 接收 pago 的通知。
  3. Esas rut​​as van 使用控制器和服务。 En los que vamos a tener que conectarnos con la API de MP.

我们采用设置

  1. 首先需要安装Express-Generator,然后才能使用 Express 的通用应用程序:

    $ npm install express-generator -g

  2. 第二步创建 Express 应用程序

    $ express --view=none MercadoPagoCheckout

    Con este comando lo que estamos haciendo es crear una API, que se llama MercadoPagoCheckout

  3. 您可以在 MercadoPagoCheckout 上查看 (que se acaba de crear) ejecutamos:

    $ npm install

    可以安装node_modules。
    依赖于计算机,如果您想了解更多信息,请联系我们。

  4. 安装 axios 时,请使用MP API 请求

    $ npm install axios --save

您可以进行 API 基础设置!


道路的创造

如果要安装的话,我们需要先进行项目编辑,然后再进行编辑。

Dentro de los archivos, 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;
Enter fullscreen mode Exit fullscreen mode

Lo que tenemos que hacer a continuación es crear las rut​​as.

创建 2 个规则:一般链接 MP 和其他 MP 通知 (webhook)

Vamos a eliminar algunas rut​​as que NO vamos a usar como:

app.use('/', indexRouter);
app.use('/users', usersRouter);
Enter fullscreen mode Exit fullscreen mode

Y agregar las rut​​as que SI vamos a usar que son:

app.post("/payment/new", (req, res) => 
  PaymentInstance.getMercadoPagoLink(req, res) 
);
Enter fullscreen mode Exit fullscreen mode

请使用 llamar 功能,getMercadoPagoLink()使用 estar 和控制器,然后使用 cear más adelante。

此功能可以通过请求POST网址来执行实际操作localhost:3000/payment/new

app.post("/webhook", (req, res) => PaymentInstance.webhook(req, res));
Enter fullscreen mode Exit fullscreen mode

Esta linea lo que hace es muy 类似于 la linea anterior。

Cuando se reciba un request POSTen la url localhost:3000/webhookse va a ejecutar la función webhook()que está dentro delcontroller (que todavía no Creamos)

最后,导入控制器和服务,并按照以下步骤进行操作:

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

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

const PaymentInstance = new PaymentController(new PaymentService()); 
// Permitimos que el controller pueda usar el service
Enter fullscreen mode Exit fullscreen mode

Entonces, nos tentría que quedar así:

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

var app = express();

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

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

const PaymentInstance = new PaymentController(new PaymentService()); 
// Permitimos que el controller pueda usar el service

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("/payment/new", (req, res) => 
  PaymentInstance.getMercadoPagoLink(req, res) 
);

app.post("/webhook", (req, res) => PaymentInstance.webhook(req, res)); 

module.exports = app;
Enter fullscreen mode Exit fullscreen mode

创建控制器

作为控制器,它是一个功能或与其他功能相结合的功能,允许获取有关数据基础的信息,或者我们可以使用外部 API 的数据。

首先,我们要创建一个新的文件夹,然后controllers创建一个新的归档文件PaymentController.js,然后再创建一个新的文件夹PaymentController

Dentro de esa clase vamos a crear dos funciones, una que se llame getMercadoPagoLink(), y otra que se llame webhook().

class PaymentController {
  constructor(paymentService) {
    this.paymentService = paymentService; 
  }

  async getMercadoPagoLink(req, res) {

  }

  webhook(req, res) { 

  }
}

module.exports = PaymentController;
Enter fullscreen mode Exit fullscreen mode

La función getMercadoPagoLink(), va a llamar al service (que estamos importando desde el constructor) y ejecutar la función createPaymentMercadoPago()que va a recibi información del Producto o servicio que queramos Vender, como por ejemplo:
nombre, precio, cantidad

async getMercadoPagoLink(req, res) {
    const { name, price, unit, img } = req.body; 
    try {
      const checkout = await this.paymentService.createPaymentMercadoPago(
        name, // nombre del producto o servicio
        price, //precio del producto o servicio
        unit,  //cantidad que estamos vendiendo
        img  // imagen de referencia del producto o servicio
      );

      return res.redirect(checkout.init_point); 
     //si es exitoso los llevamos a la url de Mercado Pago

      return res.json({url: checkout.init_point})
     // o si queres devolver la url al front 


    } catch (err) { 
// si falla devolvemos un status 500

      return res.status(500).json({
        error: true,
        msg: "Hubo un error con Mercado Pago"
      });
    }
  }
Enter fullscreen mode Exit fullscreen mode

La función tiene que ser declarada con un async,ya que vamos a estar haciendo un awaita la función del service.

请注意,请求正文、前端信息name、、、、priceunitimg

Una vez resuelta PaymentService.createPaymentMercadoPago(),vamos a tener la url de pago que nos da MP。

La función webhook(), en cambio, debería verse así:

webhook(req, res) { 
    if (req.method === "POST") { 
      let body = ""; 
      req.on("data", chunk => {  
        body += chunk.toString();
      });
      req.on("end", () => {  
        console.log(body, "webhook response"); 
        res.end("ok");
      });
    }
    return res.status(200); 
  }
Enter fullscreen mode Exit fullscreen mode

在功能上webhook(),请验证海洋请求的方法POST,这是向曼达尔议员提供所需信息的必要条件。

Luego,声明变量是美洲驼,需要清楚地body写出需要解决的医疗问题,因为需要大块的信息,所以需要使用清晰的算法(字符串)。

En síntesis, nuestro PaymentController, debería quedar:

class PaymentController {
  constructor(paymentService) {
    this.paymentService = paymentService; 
  }

  async getMercadoPagoLink(req, res) {
    const { name, price, unit, img } = req.query; 
    try {
      const checkout = await this.paymentService.createPaymentMercadoPago(
        name, 
        price,
        unit, 
        img 
      );

      return res.redirect(checkout.init_point);  

    } catch (err) { 

      return res.status(500).json({
        error: true,
        msg: "Hubo un error con Mercado Pago"
      });
    }
  }

 webhook(req, res) { 
    if (req.method === "POST") { 
      let body = ""; 
      req.on("data", chunk => {  
        body += chunk.toString();
      });
      req.on("end", () => {  
        console.log(body, "webhook response"); 
        res.end("ok");
      });
    }
    return res.status(200); 
  }
}

module.exports = PaymentController;

Enter fullscreen mode Exit fullscreen mode

服务创造

该服务是一种功能或功能的结合,不允许query在数据基础上执行,或与外部 API 连接。

最初,我们创建了services一个新的创建对象,创建了地毯(创建了一个不存在的对象),并在新的归档中创建了一个新的归档对象PaymentService.js,然后创建了一个新的分类对象PaymentService

需要保护constructorMP 钥匙/代币。

无论如何,重要的是axios,您可以使用 API de MP 连接器。

const axios = require("axios"); 

class PaymentService {
  constructor() {
    this.tokensMercadoPago = {
      prod: {},
      test: {
        access_token:
          "APP_USR-6317427424180639-042414-47e969706991d3a442922b0702a0da44-469485398" 
     // el access_token de MP
      }
    }; 
// declaramos de la siguiente manera el token
// para que sea más fácil cambiarlo dependiendo del ambiente
    this.mercadoPagoUrl = "https://api.mercadopago.com/checkout"; 
 // declaramos la url en el constructor para poder accederla a lo largo de toda la class
  }
}
Enter fullscreen mode Exit fullscreen mode

Dentro de esa clase,vamos a crear una sola función llamada CreatePaymentMercadoPago()

在该功能中,您可以使用async功能中的变量来调节环境getMercadoPagoLink()PaymentController.js

También,vamos 声明变量 llamada urlque es la dirección de MP a donde vamos a pedir la information midte el método POST。使用constructor公式中声明的变量。

  async createPaymentMercadoPago(name, price, unit, img) {  

    const url = `${this.mercadoPagoUrl}/preferences?access_token=${this.tokensMercadoPago.test.access_token}`; 

  }

Enter fullscreen mode Exit fullscreen mode

接下来,我们将继续创建骆驼createPaymentMercadoPago()物件阵列的功能[{}]items

Este Array,是一个关于销售产品或服务信息的内容。

可以使用变量、、nameunit函数pricegetMercadoPagoLink()实现PaymentController.js


   const items = [
      {
        id: "1234", 
// id interno (del negocio) del item
        title: name, 
// nombre que viene de la prop que recibe del controller
        description: "Descripción del producto o servicio", 
// descripción del producto
        picture_url: "https://localhost:3000/static/product.png", 
// url de la imágen del producto, tiene que ser una url válida
        category_id: "1234", 
 // categoría interna del producto (del negocio)
        quantity: parseInt(unit), 
// cantidad que estamos vendiendo, que tiene que ser un intiger
        currency_id: "ARS",
 // id de la moneda, que tiene que ser en ISO 4217
        unit_price: parseFloat(price) 
// el precio, que por su complejidad tiene que ser tipo FLOAT
      }, {
// si queremos agregar otro item, pasamos la misma información acá
}
    ];  

Enter fullscreen mode Exit fullscreen mode

Ahora,vamos 声明一个目标 llamado preferences,que contiene las preencias de pago de nuestro array items

Todo esto lo estamos haciendo de acuerdo a la documentación de la API de MP que pueden encontrar acá

  const preferences = { 
      items, 
// el array de objetos, items que declaramos más arriba
      external_reference: "referencia del negocio", 
// referencia para identificar la preferenciaç
      payer: { 
// información del comprador, si estan en producción tienen que traerlos del request
//(al igual que hicimos con el precio del item) 
        name: "Lalo",
        surname: "Landa",
        email: "test_user_63274575@testuser.com", 
// si estan en sandbox, aca tienen que poner el email de SU usuario de prueba si estan 
//en producción, deberian completar esta información 
//de la misma manera que lo hicimos con items, units, y price

        phone: {
          area_code: "11",
          number: "22223333"
        },
        address: {
          zip_code: "1111",
          street_name: "False",
          street_number: "123"
        }
      }, 
      payment_methods: {
 // declaramos el método de pago y sus restricciones
        excluded_payment_methods: [
// aca podemos excluir metodos de pagos, tengan en cuenta que es un array de objetos
// donde el id de cada objeto es la exclusión
          {
            id: "amex"
// acá estamos excluyendo el uso de la tarjeta American Express
          }
        ],
        excluded_payment_types: [{ id: "atm" }],
 // aca podemos excluir TIPOS de pagos, es un array de objetos
// Por ejemplo, aca estamos excluyendo pago por cajero
        installments: 6, 
// mayor cantidad de cuotas permitidas
        default_installments: 6 
// la cantidad de cuotas que van a aparecer por defecto
      }, 
      back_urls: {
// declaramos las urls de redireccionamiento
        success: "https://localhost:3000/success", 
// url a la que va a redireccionar si sale todo bien
        pending: "https://localhost:3000.com/pending",
// url a la que va a redireccionar si decide pagar en efectivo por ejemplo
        failure: "https://localhost:3000.com/error"
 // url a la que va a redireccionar si falla el pago
      }, 
      notification_url: "https://localhost:3000/webhook", 
// declaramos nuestra url donde recibiremos las notificaciones
// es la misma ruta que declaramos en app.js
      auto_return: "approved" 
// si la compra es exitosa automaticamente redirige a "success" de back_urls
    };

//NOTA: TODAS las URLS que usemos tienen que ser reales,
// si prueban con localhost, va a fallar

Enter fullscreen mode Exit fullscreen mode

最后,我们无法实现POSTaxios:


      const request = await axios.post(url, preferences, { 
// hacemos el POST a la url que declaramos arriba, con las preferencias
        headers: { 
// y el header, que contiene content-Type
          "Content-Type": "application/json"
        }
      });

Enter fullscreen mode Exit fullscreen mode

El PaymentService.jsles debería haber quedado:

const axios = require("axios"); 

class PaymentService {
  constructor() {
    this.tokensMercadoPago = {
      prod: {},
      test: {
        access_token:
          "APP_USR-6317427424180639-042414-47e969706991d3a442922b0702a0da44-469485398" 
// el access_token de MP
      }
    }; 
// declaramos de la siguiente manera el token, para que sea más fácil cambiarlo dependiendo del ambiente
    this.mercadoPagoUrl = "https://api.mercadopago.com/checkout"; 
 // declaramos la url en el constructor para poder accederla a lo largo de toda la clase
  }

  async createPaymentMercadoPago(name, price, unit, img) {  
// recibimos las props que le mandamos desde el PaymentController
    const url = `${this.mercadoPagoUrl}/preferences?access_token=${this.tokensMercadoPago.test.access_token}`; 
// url a la que vamos a hacer los requests

    const items = [
      {
        id: "1234", 
// id interno (del negocio) del item
        title: name, 
// nombre que viene de la prop que recibe del controller
        description: "Dispositivo movil de Tienda e-commerce",
 // descripción del producto
        picture_url: "https://courseit.com.ar/static/logo.png", 
// url de la imágen del producto
        category_id: "1234",  
// categoría interna del producto (del negocio)
        quantity: parseInt(unit), 
// cantidad, que tiene que ser un intiger
        currency_id: "ARS", 
// id de la moneda, que tiene que ser en ISO 4217
        unit_price: parseFloat(price)
 // el precio, que por su complejidad tiene que ser tipo FLOAT
      }
    ];  

    const preferences = { 
// declaramos las preferencias de pago
      items, 
// el array de objetos, items que declaramos más arriba
      external_reference: "referencia del negocio", 
// referencia para identificar la preferencia, puede ser practicamente cualquier valor
      payer: { 
// información del comprador, si estan en producción tienen que //traerlos del request
//(al igual que hicimos con el precio del item) 
        name: "Lalo",
        surname: "Landa",
        email: "test_user_63274575@testuser.com",
 // si estan en sandbox, aca tienen que poner el email de SU usuario de prueba
        phone: {
          area_code: "11",
          number: "22223333"
        },
        address: {
          zip_code: "1111",
          street_name: "False",
          street_number: "123"
        }
      }, 
      payment_methods: { 
// declaramos el método de pago y sus restricciones
        excluded_payment_methods: [ 
// aca podemos excluir metodos de pagos, tengan en cuenta que es un array de objetos
          {
            id: "amex"
          }
        ],
        excluded_payment_types: [{ id: "atm" }], 
// aca podemos excluir TIPOS de pagos, es un array de objetos
        installments: 6, 
// limite superior de cantidad de cuotas permitidas
        default_installments: 6 
// la cantidad de cuotas que van a aparecer por defecto
      }, 
      back_urls: {
// declaramos las urls de redireccionamiento
        success: "https://localhost:3000/success", 
// url que va a redireccionar si sale todo bien
        pending: "https://localhost:3000.com/pending", 
// url a la que va a redireccionar si decide pagar en efectivo por ejemplo
        failure: "https://localhost:3000.com/error" 
// url a la que va a redireccionar si falla el pago
      }, 
      notification_url: "https://mercadopago-checkout.herokuapp.com/webhook", 
// declaramos nuestra url donde recibiremos las notificaciones
      auto_return: "approved" 
// si la compra es exitosa automaticamente redirige a "success" de back_urls
    };

    try {
      const request = await axios.post(url, preferences, {
 // hacemos el POST a la url que declaramos arriba, con las preferencias
        headers: { 
// y el header, que contiene content-Type
          "Content-Type": "application/json"
        }
      });

      return request.data; 
// devolvemos la data que devuelve el POST
    } catch (e) {
      console.log(e); 
// mostramos error en caso de que falle el POST
    }
  }
}

//NOTA: TODAS las URLS que usemos tienen que ser reales, 
//si prueban con localhost, va a fallar

module.exports = PaymentService;
Enter fullscreen mode Exit fullscreen mode

是的,一切都回来了。 Para terminar con el ciclo, desde el front, deberían realizar un POSTrequest a /payment/newy eso les va a devolver un link, que es el del pago.

Recuerden que el POSTejecutado desde el front tiene que tener un body que contenga (por lo menos), name, unit, img, y price.


Espero que este 教程 les haya servido como guía para iniciarse en este tipo de integraciones or para resolver dudas!

Toda la documentación de Mercado Pago, y lo que use para crear este codigo, está acá

请参阅有关使用说明的建议

Me pueden mandar sus Consultas o mejoras del código (porque hay mil cosas para mejorar) a mi twitter @ncastrogarcia

没有回复更多评论! si tienen dudas pueden Consultarme por twitter!

Tambien les dejo este 视频, que explico lo Mismo que este blog pero en formato video

与咖啡店比较

非常感谢你的时间!

文章来源:https://dev.to/nicolascatrogarcia/como-integrar-mercado-pago-a-tu-web-34al
PREV
关于 CORS 你应该知道什么 CORS 是什么,以及它不是什么 CORS 的工作原理。它在浏览器中的样子 CORS 的棘手之处
NEXT
用于清洁 React 组件通信的事件驱动架构