Integrar Mercado Pago en nuestra API
Tags: mercadopago, node, api
Published: 2024-04-18 00:43:20

En mi caso estas serian las rutas que tengo destinadas para el checkout

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yruvovthgq4pia9v1y7f.png)

- /checkout/:userId: Esta ruta permite obtener todas las órdenes de compra asociadas a un usuario específico.
- /checkout/dashboard/getAllOrders: Esta ruta permite obtener todas las órdenes de compra, en mi caso tengo un dashboard aparte para revisar las ordenes.
- /checkout/create_preference: Esta ruta se utiliza para crear una preferencia de pago en Mercado Pago.
- /checkout/getpayment_info: Esta ruta recibe la información de pago de Mercado Pago una vez completada la transacción.


Ahora dentro de los controladores lo primero que tenemos que hacer es importar del paquete de mercado pago MercadoPagoConfig y Preference e inicializar el accesToken ,este nos lo brinda Mercado Pago cuando nos registramos como desarrolladores desde [CheckOut Pro](https://www.mercadopago.com.ar/developers/es/docs/checkout-pro/landing), 


```
import Product from "../models";
import PurchaseModel from "../models/purchaseItemModel";
import { Request, Response } from "express";
import { MercadoPagoConfig, Preference } from "mercadopago";
require("dotenv").config();

const client = new MercadoPagoConfig({
  accessToken: process.env.ACCESS_TOKEN_MP as string,
});

```

**Crear una Preferencia de Pago**


La preferencia de pago nos va a permitir realizar el pago, Mercado Pago nos brinda ciertas opciones para ajustar dependiendo lo que necesitemos, en mi caso estoy mapeando el objeto que recibe (el carrito de compras).
Dentro del body, items vendria a ser nuestros productos, las back_urls son las urls a las que mercado pago nos va a redirigir despues de alguna acción cuando finalizemos la compra, notification_url es la url donde se va a enviar la notificacion cuando se complete la compra.
```
exports.createPreference = async (req: Request, res: Response) => {
  try {
    const productsData = req.body.map((item: any) => {
      return {
        id: item.productID,
        title: item.title,
        quantity: Number(item.quantity),
        unit_price: Number(item.price),
        currency_id: "ARS",
        description: item.userID,
        picture_url: item.productItemPosterPath,
      };
    });
    const body = {
      items: productsData,
      back_urls: {
        success: `${process.env.BACK_URL}postcheckout/-`,
        failure: `${process.env.BACK_URL}checkout`,
        pending: `${process.env.BACK_URL}checkout`,
      },
      auto_return: "approved",
      notification_url: `${process.env.NOTIFICACION_URL}getpayment_info`,
    };
    const preference = new Preference(client);
    const result = await preference.create({ body });
    res.json({
      id: result.id,
    });
  } catch (error: any) {
    console.log(error);
    res
      .status(500)
      .json({ msg: `Error al crear la preferencia: (${error.message})` });
  }
```

**Obtener Información de Pago**
El controlador getPaymentInfo se encarga de recibir la información de pago de Mercado Pago y procesarla, este controlador recibe la información de pago de Mercado Pago, verifica el estado de la orden y actualiza el stock de productos en la base de datos en caso de que la orden se haya pagado correctamente.
Es importante que responda un 200 para que mercado pago deje de enviar solicitudes a nuestro servidor.


```
exports.getPaymentInfo = async (req: Request, res: Response) => {
  try {
    const notificationData = req.body;
    if (notificationData.topic === "merchant_order") {
      const response = await fetch(notificationData.resource, {
        method: "GET",
        headers: {
          Authorization: `Bearer ${process.env.ACCESS_TOKEN_MP}`,
        },
      });

      if (response.ok) {
        const res = await response.json();
        console.log(res, "respuesta JSONN");
        if (res.status === "closed" && res.order_status === "paid") {
          const newPurchaseOrder = new PurchaseModel({
            userId: res.items[0].description,
            items: res.items,
            orderId: res.id,
          });
          const basketItems = res.items;
          for (const item of basketItems) {
            const product = await Product.findById(item.id);
            if (product) {
              product.sizes.forEach((size: any) => {
                size.qty -= item.quantity;
              });
              await product.save();
            }
          }
          await newPurchaseOrder.save();
        }
      }
    }

    res.sendStatus(200);
  } catch (error) {
    console.error("Error al procesar la notificación de Mercado Pago:", error);
    res.status(500).json({ error: "Internal server error" });
  }
};
```

**Obtener Órdenes de Usuario**
El controlador getUserOrders se encarga de obtener todas las órdenes de compra asociadas a un usuario específico, en mi caso lo uso para mostrarle al usuario sus compras exitosas:

```
exports.getUserOrders = async (req: Request, res: Response) => {
  try {
    const { userId } = req.params;
    const orders = await PurchaseModel.find({ userId: userId });

    res.json({
      msg: `Ordenes realizadas por el usuario ${userId}`,
      status: 200,
      orders,
    });
  } catch (error: any) {
    console.log(error);
    res.status(500).json({
      msg: `Error al traer las ordenes del usurio: (${error.message})`,
    });
  }
};
```