/*/*

Cómo integrar Wompi + Node.js: pagos reales en tu app

Si estás interesado en aprender cómo integrar Wompi + Node.js, quédate en este post, porque te voy a mostrar paso a paso cómo hacerlo en una aplicación real.

Este proceso tiene varias etapas importantes, desde la obtención de los datos del usuario hasta la respuesta final de la plataforma de pago. Cada una de ellas es clave para que la transacción sea aprobada o rechazada correctamente.

Lo que vas a necesitar

Frontend react: capturar y enviar datos al backend

Swiper en React: Slider y carrusel tipo Tinder con SwiperJS

Swiper en React: Slider y carrusel tipo Tinder con SwiperJS

Si estás buscando cómo crear un Swiper en React, quédate en este nuevo post donde hablaré cómo hacer…

alertas en react

Cómo crear alertas en React usando SweetAlert y React Toastify

Si estás buscando alertas en react, quédate porque en este post te enseñaré cómo implementarlas de f…

Cómo crear modal react: paso a paso

Cómo crear modal react: paso a paso

Crear modales en React es fundamental para mantener a los usuarios en el sitio web y facilitar conve…

En este primer paso nos vamos a enfocar en crear primero en el useEffect qué solicitará la información al usuario desde un formulario. Realmente la única información que necesitamos para ejecutar la compra es el precio del producto y el correo del cliente. Por esta razón la variable configWompi se inicializa con el correo del cliente.

const precioCOP = 50000;

  const [configWompi, setConfigWompi] = useState({
    customerEmail: "proyectos@pretwor.com",
  });

  useEffect(() => {
    (async () => {
      try {
        // método para obtener configuración de wompi
        const resConfig = await axios.post("/obtener-configa", {
          params: { precio: precioCOP }
        });

        setConfigWompi((prev) => ({
          ...prev,
          ...resConfig.data
        }));
      } 
      catch (error) {
        console.log("error: ", error);
      }
    })();
  }, []);

luego de esto si procedemos a solicitar la información de Wompi necesaria para la transacción, pre enviando como único parámetro el precio del producto. Es importante aclarar que hay otras variables que ya vamos a ver en el siguiente punto, qué tal vez si quieres agregarlas lo puedes hacer, pero por el momento estas son las únicas necesarias.

Backend: obtener datos para transacción

En este punto tenemos que analizar varias cosas. Lo primero es que tenemos que crear las llaves que nos da Wompi en la cuenta que creamos, en nuestro archivo env. Eso de vital importancia porque protege las llaves de cualquier repositorio donde vayamos a utilizar nuestra aplicación. Si quieres saber un poco más sobre las variables de entorno haz clic aquí para ver el post con video.

Estas variables como lo muestro en el video, son únicas para pruebas, pero cuando ya quieras pasar a producción, estas llaves cambian. Solamente tienes que solicitarlas en Wompi.

const {precio} = req.body.params;
        //console.log("precio obtenido: ", precio);
        

        const urlRetorno   = "https://app-wompi-prueba-fca2ed8ef38d.herokuapp.com/retorno-wompi"; // callback. 
        const moneda       = "COP";
        const centavos     = Math.round(precio * 100);
        
        const referencia = `id_eduardo_${Date.now()}`; // decirle a wompi quien ejecuto el pago. 

        const integritySignature = crypto
        .createHash('sha256') // crear hash usando algoritmo sha-256
        .update(`${referencia}${centavos}${moneda}${integridad}`) // unir todos los valores en un solo String
        .digest('hex') // convertir en hexa.



        return res.json({
            publicKey: llavePublica,
            currency: moneda,
            amountInCents: centavos,
            reference: referencia,
            integritySignature,
            redirectURL: urlRetorno,
        });

aquí podemos notar que la única variable que solicitamos del Frontend es el precio y con esto ya podemos construir la transacción. Luego creamos la URL de retorno o callback: URL que usa Wompi para volver a nuestra web luego el pago. Aunque realmente nunca sale de la web, si se despliega un modal para realizar el pago. También es usada para mostrar el usuario que la transacción a finalizado y que estamos esperando la respuesta.

  • luego puedes ver la variable centavos: básicamente es el precio pero enviarlo en centavos.
  • Referencia: este punto es de vital importancia porque es el que nosotros enviamos a la plataforma de pago para luego recuperar la información del pago específica de un usuario dentro del webhook. Entonces puede ser un ID de usuario que hayas creado en tu plataforma. Cabe aclarar que tiene que ser un ID único para que funcione.
  • Integrity signature: esta variable es justamente una de las más importantes porque es la que lleva en cripta con el algoritmo aes 256, la referencia, los centavos, la moneda y la llave de integridad.

todo esto lo retornamos al Frontend, pero enviando también la llave pública.

Crear widget wompi

en esta etapa realizamos diferentes acciones y aunque las explico todas en el video, voy a ir una por una. Lo primero es crear las variables sobre las cuales se va a desplegar el widget:

const contenedorRef = useRef(null); // guardar el div real del DOM donde se pone el script de wompi
const scriptRef     = useRef(null); // guarda el script de wompi que se crea dinamicamente
const [error, setError] = useState("");

Luego de esto vamos a crear una función que nos permita verificar que los datos que trae desde el Backend sean los correctos. Esta función se llama normalizar y básicamente verifica que si no trae un dato, entonces se completa con uno vacío. Esto con el fin de no enviarle nada a Wompi incompleto para que no nos cancele la transacción.

const normalizar = useMemo(() => {
        if(!wompiConfig) return null;
        console.log("wompiconfig: ", wompiConfig);
        return{
            amountInCents: wompiConfig.amountInCents,
            currency: wompiConfig.currency || "COP",
            customerEmail: wompiConfig.customerEmail || "",
            signature: wompiConfig.integritySignature || "",
            publicKey: wompiConfig.publicKey || "",
            reference: wompiConfig.reference || "",
            redirectUrl: wompiConfig.redirectURL || "",
            // ESTOS DATOS EN ADELANTE NO SON NECESARIOS PARA LA TRANSACCION. 
            expirationTime: wompiConfig.expirationTime || "",
            taxInCents: wompiConfig.taxInCents || null,
            shippingAddress: wompiConfig.shippingAddress || null,
            installments: wompiConfig.installments || null,
            extraAttributes: wompiConfig.extraAttributes || {},
        };
    }, [wompiConfig]);

Aquí podemos notar como lo mencione arriba que hay variables que no vamos a solicitar obligatoriamente como expirationTime. Si las quieres agregar pues enviarlas pero realmente no son necesarias. Luego de esto si podemos proceder a crear el primer useEffect el cual se encargará de configurar el componente del widget.

Lo primero es inicializarlo y verificar que el contenedor esté vacío para poder luego poner aquí dentro el script. Luego de esto pasamos a obtener las variables normalizadas.

 useEffect( () => {
        const contenedor = contenedorRef.current;
        if(!contenedor) return undefined;

        contenedor.innerHTML = "";
        setError("");


        const {
            amountInCents,
            currency,
            customerEmail,
            // entorno no está aqui, pero si viene en wompiConfig
            signature,
            publicKey,
            reference,
            redirectUrl,
            // de aqui abajo no son necesarios para el pago.
            expirationTime,
            taxInCents,
            shippingAddress,
            installments,
            extraAttributes,
        } = normalizar;

a continuación vamos a proceder con crear el script vacío. Y comenzar a darle contenido a ese script. Básicamente es poner las variables que obtenemos organizadas en el script, pero añadiendo una pequeña verificación adicional si en dado caso normalizar retorna un valor vacío, entonces evitamos su envío.

// PASO 1: CREAR EL ELEMENTO SCRIPT VACIO
        const script = document.createElement("script");
        // PASO 2: PONER EL SRC AL SCRIPT
        script.src = "https://checkout.wompi.co/widget.js";
        script.async = true;

        // DATOS NECESARIOS DE LA TRANSACCION
        script.setAttribute("data-render", "button");
        script.setAttribute("data-public-key", publicKey);
        script.setAttribute("data-currency", currency);
        script.setAttribute("data-amount-in-cents", String(amountInCents));
        script.setAttribute("data-reference", reference);
        script.setAttribute("data-signature:integrity", signature);

        // OPCIONALES Y QUE NO TENEMOS
        if (redirectUrl) { script.setAttribute("data-redirect-url", redirectUrl); }
        if (customerEmail) { script.setAttribute("data-customer-data:email", customerEmail); }
        if (expirationTime) { script.setAttribute("data-expiration-time", expirationTime); }

        if (taxInCents && typeof taxInCents === "object") {
        Object.entries(taxInCents).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(`data-tax-in-cents:${clave}`, String(valor));
            }
        });
        }

        if (shippingAddress && typeof shippingAddress === "object") {
        Object.entries(shippingAddress).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(`data-shipping-address:${clave}`, String(valor));
            }
        });
        }

        if (installments) { script.setAttribute("data-installments", String(installments)); }

        if (extraAttributes && typeof extraAttributes === "object") {
        Object.entries(extraAttributes).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(clave, String(valor));
            }
        });
        }

luego creamos las funciones onload y onerror. Estas dos se encargan de verificar el comportamiento de la ejecución si tiene éxito o si tiene error. Aunque en mi video y aquí tampoco los uso, los dejo en el algoritmo por si los deseas usar en tu caso. Y por último procedemos a la limpieza tanto del script como el contenedor.

// PASO 1: CREAR EL ELEMENTO SCRIPT VACIO
        const script = document.createElement("script");
        // PASO 2: PONER EL SRC AL SCRIPT
        script.src = "https://checkout.wompi.co/widget.js";
        script.async = true;

        // DATOS NECESARIOS DE LA TRANSACCION
        script.setAttribute("data-render", "button");
        script.setAttribute("data-public-key", publicKey);
        script.setAttribute("data-currency", currency);
        script.setAttribute("data-amount-in-cents", String(amountInCents));
        script.setAttribute("data-reference", reference);
        script.setAttribute("data-signature:integrity", signature);

        // OPCIONALES Y QUE NO TENEMOS
        if (redirectUrl) { script.setAttribute("data-redirect-url", redirectUrl); }
        if (customerEmail) { script.setAttribute("data-customer-data:email", customerEmail); }
        if (expirationTime) { script.setAttribute("data-expiration-time", expirationTime); }

        if (taxInCents && typeof taxInCents === "object") {
        Object.entries(taxInCents).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(`data-tax-in-cents:${clave}`, String(valor));
            }
        });
        }

        if (shippingAddress && typeof shippingAddress === "object") {
        Object.entries(shippingAddress).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(`data-shipping-address:${clave}`, String(valor));
            }
        });
        }

        if (installments) { script.setAttribute("data-installments", String(installments)); }

        if (extraAttributes && typeof extraAttributes === "object") {
        Object.entries(extraAttributes).forEach(([clave, valor]) => {
            if (valor !== undefined && valor !== null && valor !== "") {
            script.setAttribute(clave, String(valor));
            }
        });
        }

al finalizar, en return debemos crear o poner este contenedor dentro de un div con ref

return(
        <div className="mt-3 w-100 wompi-boton">
            {mostrarEstado && !error ?(<div className="small text-muted mb-2">{"Cargando métodos de pago..."}</div>) : null}
            {mostrarEstado && error ?( <div className="small text-danger mb-2">{"No fue posible cargar wompi."}</div> ) : null}

            <div ref={contenedorRef}></div>
        </div>
    );

Poner widget en página principal

Este último paso consta de poner el componente que acabamos de crear dentro de la página principal. Enviando justamente la variable configWompi, qué es la variable que creamos y actualizamos con el backend.

   {/* WIDGETWOMPI */}
          {configWompi?.publicKey ? (
            <WidgetWompi wompiConfig={configWompi} />
          ) : null}

Webhooks

Cuándo ya podemos ejecutar una compra, es importante conocer el resultado de esta. Independientemente de los métodos que tenga la plataforma con la que trabajes SIEMPRE usa los webhooks como fuente de verdad para saber el resultado de una transacción.

básicamente cuando Wompi sabe el resultado de la transacción no lo envía, pero ¿a donde?. a crear la cuenta de Wompi justamente nos da el espacio para crear o poner nuestra URL hacia donde quiere que envíe los resultados. En mi caso yo seleccione la ruta: «/webhook-wompi».

Cabe aclarar que para que podamos recibir estos resultados tiene que ser en un servidor, no puede ser en localhost. Y una vez recibidos estos datos podemos proceder a actualizar nuestra base de datos con respecto a estos resultados: mostrarle al usuario el resultado de la transacción, almacenarlo, o ejecutar un sinfín de tareas que tengamos planeadas dentro de nuestro proyecto.

router.route("/webhook-wompi")
.post(async function(req, res){
    try{
        const evento = req.body || {};
        const tipoEvento = (evento?.event || '').toString().trim();
        const transaccion = evento?.data?.transaction || null;
        console.log("evento recibido: ", evento);


        // EJECUTAR MODIFICACIONES A MI BASE DE DATOS.

        res.status(200).json({mensaje: "recibido"});
    }
    catch(error){
        console.log("error :", error);
    }
});

Video de ayuda

Hice este video para guiarte en el proceso, haz click para verlo y si te gusta no olvides dar like y suscribirte para nuevos videos.

Producto sugerido

Uno de los mejores teclados del mercado, con firmware QMK, permitiendo que sea prácticamente 100% personalizable, desde teclas, luces, acciones por teclas, teclas duales, entre otros.

LAMPARA – 4528 valoraciones

Keychron K5 QMK – Teclado mecánico personalizado, ultra delgado de tamaño completo 104 teclas, teclado inalámbrico para juegos, interruptor marrón de perfil bajo con retroiluminación RGB para Mac

  • Keychron K5 versión 2: el Keychron K5 QMK versión 2 es un teclado mecánico inalámbrico de perfil bajo con un diseño 100%, ahora actualizado con firmware QMK y espumas acústicas mejoradas. Es compatible con Bluetooth 5.2 y conexiones por cable. ¡La aplicación web Launcher ofrece una personalización ilimitada y aumenta la productividad para su trabajo!
  • Espuma acústica mejorada: mejora tu escritura con K5 QMK versión 2 con espuma acústica IXPE avanzada para mayor comodidad, junto con espuma EPDM y espuma de látex para un soporte superior del interruptor de teclas, capacidad de respuesta y durabilidad, redefine la escritura silenciosa, cómoda y sensible.
  • Programa con QMK & Launcher: el firmware QMK de código abierto significa infinitas posibilidades para la reasignación de claves, macros, accesos directos y más. Ahora puedes personalizar fácilmente cada clave con la aplicación web Keychron Launcher. Mientras que la aplicación web Keychron Launcher es compatible con macOS, Windows y Linux. Incluye teclas para macOS y Windows para permitirle cambiar entre sistemas operativos con facilidad.

VER EN AMAZON

Conclusión

Sin duda alguna Wompi ha venido para quedarse. Si implementación a comparación de otros métodos de pago es mucho más sencilla, práctica por lo menos para mercados latinos. Asimismo cuenta con todos los métodos de pago necesarios o más usados, lo cual le permite al usuario final una gran variedad de opciones para pagar. Asimismo por el lado del desarrollador, nos permite una implementación práctica.

Así que esta la convierte en una excelente opción al momento de escoger una plataforma de pago para nuestro proyecto.

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuar!

Promedio de puntuación 0 / 5. Recuento de votos: 0

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en los medios sociales!

Resumen
Cómo integrar Wompi + Nodejs + react
Nombre del artículo
Cómo integrar Wompi + Nodejs + react
Descripción
Si quieres saber cómo integrar wompi + nodejs + react, haz clic para ver cómo hacerlo desde la solicitud de la información hasta la respuesta
Autor
Publisher Name
Eduardo Arias
Publisher Logo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Carrito de compra